From ae8db2e68b7b8516203f3cc0a35a6ff989095fda Mon Sep 17 00:00:00 2001 From: fangyang2021 <3020949587@qq.com> Date: Thu, 21 Nov 2024 10:52:23 +0800 Subject: [PATCH] first commit --- .editorconfig | 16 + .gitignore | 42 + .vscode/extensions.json | 4 + .vscode/launch.json | 5 + .vscode/tasks.json | 42 + README.md | 28 + angular.json | 239 + doc.md | 5 + mock/index.ts | 38 + package.json | 54 + pnpm-lock.yaml | 7380 +++++++++++++++++ projects/cdk/README.md | 24 + projects/cdk/ng-package.json | 7 + projects/cdk/package.json | 12 + projects/cdk/src/dec-module/base-href.ts | 8 + projects/cdk/src/dec-module/dec.module.ts | 41 + .../cdk/src/dec-module/http.interceptor.ts | 100 + .../form-error-tips.component.html | 36 + .../form-error-tips.component.less | 0 .../form-error-tips.component.ts | 28 + .../input-space-error.directive.ts | 24 + projects/cdk/src/public-api.ts | 14 + .../cdk/src/public-path/public-path.pipe.ts | 16 + .../quick-date-range.component.css | 0 .../quick-date-range.component.html | 17 + .../quick-date-range.component.ts | 94 + projects/cdk/src/storage/cache.service.ts | 71 + projects/cdk/src/storage/index.ts | 3 + projects/cdk/src/storage/storage.module.ts | 15 + projects/cdk/src/storage/storage.service.ts | 79 + projects/cdk/src/table-list/index.ts | 5 + .../cdk/src/table-list/table-list-options.ts | 143 + .../cdk/src/table-list/table-list.module.ts | 56 + .../table-list/table-list.component.html | 223 + .../table-list/table-list.component.less | 119 + .../table-list/table-list.component.ts | 386 + .../table-operation.component.html | 30 + .../table-operation.component.less | 25 + .../table-operation.component.ts | 61 + .../src/table-list/td-overflow.directive.ts | 30 + projects/cdk/src/types/index.ts | 58 + projects/cdk/src/utils/index.ts | 46 + projects/cdk/src/validators/index.ts | 66 + projects/cdk/tsconfig.lib.json | 14 + projects/cdk/tsconfig.lib.prod.json | 10 + projects/cdk/tsconfig.spec.json | 14 + projects/client/proxy.conf.json | 15 + projects/client/src/app/app-routing.module.ts | 26 + projects/client/src/app/app.component.html | 4 + projects/client/src/app/app.component.less | 0 projects/client/src/app/app.component.ts | 73 + projects/client/src/app/app.module.ts | 47 + .../client/src/app/core/gaurd/auth.guard.ts | 27 + .../src/app/core/gaurd/permisson.guard.ts | 33 + .../src/app/core/services/auth.service.ts | 56 + .../app/core/services/client.interceptor.ts | 43 + .../core/services/detection-api.service.ts | 269 + .../client/src/app/core/services/index.ts | 4 + .../src/app/core/services/utils.service.ts | 11 + .../core/services/websocket-api.service.ts | 65 + .../app/feature/auth/auth-routing.module.ts | 16 + .../src/app/feature/auth/auth.module.ts | 11 + .../src/app/feature/auth/pages/index.ts | 1 + .../auth/pages/login/login.component.html | 57 + .../auth/pages/login/login.component.less | 23 + .../auth/pages/login/login.component.ts | 50 + .../detection-graphics.component.html | 153 + .../detection-graphics.component.less | 204 + .../detection-graphics.component.ts | 375 + .../detection-value.component.html | 4 + .../detection-value.component.less | 0 .../detection-value.component.ts | 12 + .../device-table/device-table.component.html | 47 + .../device-table/device-table.component.less | 0 .../device-table/device-table.component.ts | 133 + .../forbidden/forbidden.component.html | 4 + .../forbidden/forbidden.component.less | 0 .../forbidden/forbidden.component.ts | 14 + .../components/home/home.component.html | 0 .../components/home/home.component.less | 0 .../components/home/home.component.ts | 34 + .../image-player/_image-player.component.ts | 129 + .../image-player/image-player.component.html | 52 + .../image-player/image-player.component.less | 44 + .../image-player/image-player.component.ts | 176 + .../app/feature/detection/components/index.ts | 10 + .../notfound/notfound.component.html | 6 + .../notfound/notfound.component.less | 0 .../components/notfound/notfound.component.ts | 10 + .../point-status/point-status.component.html | 29 + .../point-status/point-status.component.less | 0 .../point-status/point-status.component.ts | 16 + .../point-table/point-table.component.html | 41 + .../point-table/point-table.component.less | 0 .../point-table/point-table.component.ts | 115 + .../detection/detection-routing.module.ts | 156 + .../app/feature/detection/detection.module.ts | 56 + .../pages/analysis/analysis.component.html | 94 + .../pages/analysis/analysis.component.less | 34 + .../pages/analysis/analysis.component.ts | 347 + .../detection-index.component.html | 279 + .../detection-index.component.less | 120 + .../detection-index.component.ts | 459 + .../history-detail.component.html | 182 + .../history-detail.component.less | 83 + .../history-detail.component.ts | 133 + .../history-list/history-list.component.html | 91 + .../history-list/history-list.component.less | 3 + .../history-list/history-list.component.ts | 164 + .../src/app/feature/detection/pages/index.ts | 9 + .../algorithm-setting.component.html | 151 + .../algorithm-setting.component.less | 34 + .../algorithm-setting.component.ts | 200 + .../point-setting.component.html | 31 + .../point-setting.component.less | 0 .../point-setting/point-setting.component.ts | 73 + .../settings-layout.component.html | 29 + .../settings-layout.component.less | 25 + .../settings-layout.component.ts | 8 + .../system-setting.component.html | 43 + .../system-setting.component.less | 5 + .../system-setting.component.ts | 46 + .../temperature-setting.component.html | 72 + .../temperature-setting.component.less | 0 .../temperature-setting.component.ts | 129 + .../authorization-layout.component.html | 80 + .../authorization-layout.component.less | 144 + .../authorization-layout.component.ts | 50 + .../bg-border/bg-border.component.html | 63 + .../bg-border/bg-border.component.less | 220 + .../bg-border/bg-border.component.ts | 10 + .../client/src/app/shared/components/index.ts | 2 + .../shared/directives/dec-corner.directive.ts | 19 + .../client/src/app/shared/directives/index.ts | 1 + projects/client/src/app/shared/ng-zorro.ts | 96 + .../client/src/app/shared/shared.module.ts | 49 + projects/client/src/assets/.gitkeep | 0 projects/client/src/assets/icons/alert.svg | 3 + projects/client/src/assets/icons/bell.svg | 3 + .../client/src/assets/icons/disconnect.svg | 3 + projects/client/src/assets/icons/folder.svg | 3 + .../client/src/assets/icons/fullscreen.svg | 6 + projects/client/src/assets/icons/light.svg | 7 + projects/client/src/assets/icons/lock.svg | 3 + projects/client/src/assets/icons/moon.svg | 6 + .../src/assets/icons/no-image-white.png | Bin 0 -> 471 bytes projects/client/src/assets/icons/no-image.png | Bin 0 -> 678 bytes projects/client/src/assets/icons/no-image.svg | 3 + .../client/src/assets/icons/pie-center.svg | 41 + projects/client/src/assets/icons/power.svg | 3 + projects/client/src/assets/icons/success.svg | 3 + projects/client/src/assets/icons/user.svg | 3 + projects/client/src/assets/imgs/logo.png | Bin 0 -> 5380 bytes projects/client/src/dtos/alarm.dto.ts | 6 + projects/client/src/dtos/algorithm.dto.ts | 11 + projects/client/src/dtos/auth.dto.ts | 14 + projects/client/src/dtos/index.ts | 5 + projects/client/src/dtos/point.dto.ts | 71 + projects/client/src/dtos/temperature.dto.ts | 8 + .../src/environments/environment.prod.ts | 6 + .../client/src/environments/environment.ts | 19 + projects/client/src/favicon.ico | Bin 0 -> 2525 bytes projects/client/src/index.html | 69 + projects/client/src/main.ts | 7 + projects/client/src/styles.less | 568 ++ projects/client/src/theme.less | 207 + projects/client/tsconfig.app.json | 14 + projects/client/tsconfig.spec.json | 14 + projects/manage/proxy.conf.json | 15 + projects/manage/src/app/app-routing.module.ts | 26 + projects/manage/src/app/app.component.html | 1 + projects/manage/src/app/app.component.less | 0 projects/manage/src/app/app.component.ts | 35 + projects/manage/src/app/app.module.ts | 46 + .../manage/src/app/core/gaurd/auth.guard.ts | 50 + .../src/app/core/gaurd/permisson.guard.ts | 65 + .../src/app/core/services/auth-api.service.ts | 9 + .../manage/src/app/core/services/index.ts | 2 + .../app/core/services/manage-api.service.ts | 330 + .../app/feature/auth/auth-routing.module.ts | 16 + .../src/app/feature/auth/auth.module.ts | 11 + .../src/app/feature/auth/pages/index.ts | 1 + .../auth/pages/login/login.component.html | 59 + .../auth/pages/login/login.component.less | 49 + .../auth/pages/login/login.component.ts | 48 + .../algorithm-point-select.component.html | 67 + .../algorithm-point-select.component.less | 0 .../algorithm-point-select.component.ts | 118 + .../camera-form/camera-form.component.html | 91 + .../camera-form/camera-form.component.less | 0 .../camera-form/camera-form.component.ts | 70 + .../color-picker/color-picker.component.html | 19 + .../color-picker/color-picker.component.less | 20 + .../color-picker/color-picker.component.ts | 60 + .../forbidden/forbidden.component.html | 4 + .../forbidden/forbidden.component.less | 0 .../forbidden/forbidden.component.ts | 14 + .../components/home/home.component.html | 0 .../components/home/home.component.less | 0 .../manage/components/home/home.component.ts | 30 + .../app/feature/manage/components/index.ts | 15 + .../components/layout/layout.component.html | 138 + .../components/layout/layout.component.less | 84 + .../components/layout/layout.component.ts | 74 + .../machine-form/machine-form.component.html | 40 + .../machine-form/machine-form.component.less | 0 .../machine-form/machine-form.component.ts | 40 + .../notfound/notfound.component.html | 6 + .../notfound/notfound.component.less | 0 .../components/notfound/notfound.component.ts | 10 + .../components/page/page.component.html | 12 + .../components/page/page.component.less | 5 + .../manage/components/page/page.component.ts | 13 + .../point-form/point-form.component.html | 63 + .../point-form/point-form.component.less | 0 .../point-form/point-form.component.ts | 65 + .../station-form/station-form.component.html | 45 + .../station-form/station-form.component.less | 0 .../station-form/station-form.component.ts | 39 + .../system-user-layout.component.html | 77 + .../system-user-layout.component.less | 10 + .../system-user-layout.component.ts | 103 + .../temperature-form.component.html | 63 + .../temperature-form.component.less | 0 .../temperature-form.component.ts | 88 + .../user-form/user-form.component.html | 30 + .../user-form/user-form.component.less | 0 .../user-form/user-form.component.ts | 38 + .../feature/manage/manage-routing.module.ts | 209 + .../src/app/feature/manage/manage.module.ts | 67 + .../algorithm-form.component.html | 75 + .../algorithm-form.component.less | 0 .../algorithm-form.component.ts | 164 + .../algorithm-list.component.html | 32 + .../algorithm-list.component.less | 0 .../algorithm-list.component.ts | 87 + .../pages/device/camera/camera.component.html | 80 + .../pages/device/camera/camera.component.less | 0 .../pages/device/camera/camera.component.ts | 184 + .../temperature/temperature.component.html | 67 + .../temperature/temperature.component.less | 0 .../temperature/temperature.component.ts | 129 + .../src/app/feature/manage/pages/index.ts | 14 + .../pages/machine/machine.component.html | 31 + .../pages/machine/machine.component.less | 0 .../manage/pages/machine/machine.component.ts | 111 + .../manage/pages/point/point.component.html | 65 + .../manage/pages/point/point.component.less | 0 .../manage/pages/point/point.component.ts | 137 + .../pages/station/station.component.html | 22 + .../pages/station/station.component.less | 0 .../manage/pages/station/station.component.ts | 97 + .../system-info/system-info.component.html | 102 + .../system-info/system-info.component.less | 0 .../system-info/system-info.component.ts | 158 + .../system-theme/system-theme.component.html | 182 + .../system-theme/system-theme.component.less | 0 .../system-theme/system-theme.component.ts | 141 + .../user/permission/permission.component.html | 30 + .../user/permission/permission.component.less | 0 .../user/permission/permission.component.ts | 172 + .../user/user-list/user-list.component.html | 20 + .../user/user-list/user-list.component.less | 0 .../user/user-list/user-list.component.ts | 105 + .../manage/src/app/icons-provider.module.ts | 21 + .../manage/src/app/shared/components/index.ts | 0 projects/manage/src/app/shared/ng-zorro.ts | 100 + .../manage/src/app/shared/shared.module.ts | 38 + projects/manage/src/assets/.gitkeep | 0 projects/manage/src/assets/imgs/bg.jpg | Bin 0 -> 474548 bytes projects/manage/src/assets/imgs/logo.png | Bin 0 -> 5380 bytes projects/manage/src/dtos/index.ts | 33 + .../src/environments/environment.prod.ts | 6 + .../manage/src/environments/environment.ts | 20 + projects/manage/src/favicon.ico | Bin 0 -> 2525 bytes projects/manage/src/index.html | 68 + projects/manage/src/main.ts | 8 + projects/manage/src/styles.less | 43 + projects/manage/tsconfig.app.json | 14 + projects/manage/tsconfig.spec.json | 14 + tailwind.config.js | 8 + tsconfig.json | 45 + 282 files changed, 22276 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 README.md create mode 100644 angular.json create mode 100644 doc.md create mode 100644 mock/index.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 projects/cdk/README.md create mode 100644 projects/cdk/ng-package.json create mode 100644 projects/cdk/package.json create mode 100644 projects/cdk/src/dec-module/base-href.ts create mode 100644 projects/cdk/src/dec-module/dec.module.ts create mode 100644 projects/cdk/src/dec-module/http.interceptor.ts create mode 100644 projects/cdk/src/form-error-tips/form-error-tips.component.html create mode 100644 projects/cdk/src/form-error-tips/form-error-tips.component.less create mode 100644 projects/cdk/src/form-error-tips/form-error-tips.component.ts create mode 100644 projects/cdk/src/input-space-error/input-space-error.directive.ts create mode 100644 projects/cdk/src/public-api.ts create mode 100644 projects/cdk/src/public-path/public-path.pipe.ts create mode 100644 projects/cdk/src/quick-date-range/quick-date-range.component.css create mode 100644 projects/cdk/src/quick-date-range/quick-date-range.component.html create mode 100644 projects/cdk/src/quick-date-range/quick-date-range.component.ts create mode 100644 projects/cdk/src/storage/cache.service.ts create mode 100644 projects/cdk/src/storage/index.ts create mode 100644 projects/cdk/src/storage/storage.module.ts create mode 100644 projects/cdk/src/storage/storage.service.ts create mode 100644 projects/cdk/src/table-list/index.ts create mode 100644 projects/cdk/src/table-list/table-list-options.ts create mode 100644 projects/cdk/src/table-list/table-list.module.ts create mode 100644 projects/cdk/src/table-list/table-list/table-list.component.html create mode 100644 projects/cdk/src/table-list/table-list/table-list.component.less create mode 100644 projects/cdk/src/table-list/table-list/table-list.component.ts create mode 100644 projects/cdk/src/table-list/table-operation/table-operation.component.html create mode 100644 projects/cdk/src/table-list/table-operation/table-operation.component.less create mode 100644 projects/cdk/src/table-list/table-operation/table-operation.component.ts create mode 100644 projects/cdk/src/table-list/td-overflow.directive.ts create mode 100644 projects/cdk/src/types/index.ts create mode 100644 projects/cdk/src/utils/index.ts create mode 100644 projects/cdk/src/validators/index.ts create mode 100644 projects/cdk/tsconfig.lib.json create mode 100644 projects/cdk/tsconfig.lib.prod.json create mode 100644 projects/cdk/tsconfig.spec.json create mode 100644 projects/client/proxy.conf.json create mode 100644 projects/client/src/app/app-routing.module.ts create mode 100644 projects/client/src/app/app.component.html create mode 100644 projects/client/src/app/app.component.less create mode 100644 projects/client/src/app/app.component.ts create mode 100644 projects/client/src/app/app.module.ts create mode 100644 projects/client/src/app/core/gaurd/auth.guard.ts create mode 100644 projects/client/src/app/core/gaurd/permisson.guard.ts create mode 100644 projects/client/src/app/core/services/auth.service.ts create mode 100644 projects/client/src/app/core/services/client.interceptor.ts create mode 100644 projects/client/src/app/core/services/detection-api.service.ts create mode 100644 projects/client/src/app/core/services/index.ts create mode 100644 projects/client/src/app/core/services/utils.service.ts create mode 100644 projects/client/src/app/core/services/websocket-api.service.ts create mode 100644 projects/client/src/app/feature/auth/auth-routing.module.ts create mode 100644 projects/client/src/app/feature/auth/auth.module.ts create mode 100644 projects/client/src/app/feature/auth/pages/index.ts create mode 100644 projects/client/src/app/feature/auth/pages/login/login.component.html create mode 100644 projects/client/src/app/feature/auth/pages/login/login.component.less create mode 100644 projects/client/src/app/feature/auth/pages/login/login.component.ts create mode 100644 projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.html create mode 100644 projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.less create mode 100644 projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.ts create mode 100644 projects/client/src/app/feature/detection/components/detection-value/detection-value.component.html create mode 100644 projects/client/src/app/feature/detection/components/detection-value/detection-value.component.less create mode 100644 projects/client/src/app/feature/detection/components/detection-value/detection-value.component.ts create mode 100644 projects/client/src/app/feature/detection/components/device-table/device-table.component.html create mode 100644 projects/client/src/app/feature/detection/components/device-table/device-table.component.less create mode 100644 projects/client/src/app/feature/detection/components/device-table/device-table.component.ts create mode 100644 projects/client/src/app/feature/detection/components/forbidden/forbidden.component.html create mode 100644 projects/client/src/app/feature/detection/components/forbidden/forbidden.component.less create mode 100644 projects/client/src/app/feature/detection/components/forbidden/forbidden.component.ts create mode 100644 projects/client/src/app/feature/detection/components/home/home.component.html create mode 100644 projects/client/src/app/feature/detection/components/home/home.component.less create mode 100644 projects/client/src/app/feature/detection/components/home/home.component.ts create mode 100644 projects/client/src/app/feature/detection/components/image-player/_image-player.component.ts create mode 100644 projects/client/src/app/feature/detection/components/image-player/image-player.component.html create mode 100644 projects/client/src/app/feature/detection/components/image-player/image-player.component.less create mode 100644 projects/client/src/app/feature/detection/components/image-player/image-player.component.ts create mode 100644 projects/client/src/app/feature/detection/components/index.ts create mode 100644 projects/client/src/app/feature/detection/components/notfound/notfound.component.html create mode 100644 projects/client/src/app/feature/detection/components/notfound/notfound.component.less create mode 100644 projects/client/src/app/feature/detection/components/notfound/notfound.component.ts create mode 100644 projects/client/src/app/feature/detection/components/point-status/point-status.component.html create mode 100644 projects/client/src/app/feature/detection/components/point-status/point-status.component.less create mode 100644 projects/client/src/app/feature/detection/components/point-status/point-status.component.ts create mode 100644 projects/client/src/app/feature/detection/components/point-table/point-table.component.html create mode 100644 projects/client/src/app/feature/detection/components/point-table/point-table.component.less create mode 100644 projects/client/src/app/feature/detection/components/point-table/point-table.component.ts create mode 100644 projects/client/src/app/feature/detection/detection-routing.module.ts create mode 100644 projects/client/src/app/feature/detection/detection.module.ts create mode 100644 projects/client/src/app/feature/detection/pages/analysis/analysis.component.html create mode 100644 projects/client/src/app/feature/detection/pages/analysis/analysis.component.less create mode 100644 projects/client/src/app/feature/detection/pages/analysis/analysis.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.html create mode 100644 projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.less create mode 100644 projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.html create mode 100644 projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.less create mode 100644 projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.html create mode 100644 projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.less create mode 100644 projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/index.ts create mode 100644 projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.html create mode 100644 projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.less create mode 100644 projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.html create mode 100644 projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.less create mode 100644 projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.html create mode 100644 projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.less create mode 100644 projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.html create mode 100644 projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.less create mode 100644 projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.ts create mode 100644 projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.html create mode 100644 projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.less create mode 100644 projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.ts create mode 100644 projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.html create mode 100644 projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.less create mode 100644 projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.ts create mode 100644 projects/client/src/app/shared/components/bg-border/bg-border.component.html create mode 100644 projects/client/src/app/shared/components/bg-border/bg-border.component.less create mode 100644 projects/client/src/app/shared/components/bg-border/bg-border.component.ts create mode 100644 projects/client/src/app/shared/components/index.ts create mode 100644 projects/client/src/app/shared/directives/dec-corner.directive.ts create mode 100644 projects/client/src/app/shared/directives/index.ts create mode 100644 projects/client/src/app/shared/ng-zorro.ts create mode 100644 projects/client/src/app/shared/shared.module.ts create mode 100644 projects/client/src/assets/.gitkeep create mode 100644 projects/client/src/assets/icons/alert.svg create mode 100644 projects/client/src/assets/icons/bell.svg create mode 100644 projects/client/src/assets/icons/disconnect.svg create mode 100644 projects/client/src/assets/icons/folder.svg create mode 100644 projects/client/src/assets/icons/fullscreen.svg create mode 100644 projects/client/src/assets/icons/light.svg create mode 100644 projects/client/src/assets/icons/lock.svg create mode 100644 projects/client/src/assets/icons/moon.svg create mode 100644 projects/client/src/assets/icons/no-image-white.png create mode 100644 projects/client/src/assets/icons/no-image.png create mode 100644 projects/client/src/assets/icons/no-image.svg create mode 100644 projects/client/src/assets/icons/pie-center.svg create mode 100644 projects/client/src/assets/icons/power.svg create mode 100644 projects/client/src/assets/icons/success.svg create mode 100644 projects/client/src/assets/icons/user.svg create mode 100644 projects/client/src/assets/imgs/logo.png create mode 100644 projects/client/src/dtos/alarm.dto.ts create mode 100644 projects/client/src/dtos/algorithm.dto.ts create mode 100644 projects/client/src/dtos/auth.dto.ts create mode 100644 projects/client/src/dtos/index.ts create mode 100644 projects/client/src/dtos/point.dto.ts create mode 100644 projects/client/src/dtos/temperature.dto.ts create mode 100644 projects/client/src/environments/environment.prod.ts create mode 100644 projects/client/src/environments/environment.ts create mode 100644 projects/client/src/favicon.ico create mode 100644 projects/client/src/index.html create mode 100644 projects/client/src/main.ts create mode 100644 projects/client/src/styles.less create mode 100644 projects/client/src/theme.less create mode 100644 projects/client/tsconfig.app.json create mode 100644 projects/client/tsconfig.spec.json create mode 100644 projects/manage/proxy.conf.json create mode 100644 projects/manage/src/app/app-routing.module.ts create mode 100644 projects/manage/src/app/app.component.html create mode 100644 projects/manage/src/app/app.component.less create mode 100644 projects/manage/src/app/app.component.ts create mode 100644 projects/manage/src/app/app.module.ts create mode 100644 projects/manage/src/app/core/gaurd/auth.guard.ts create mode 100644 projects/manage/src/app/core/gaurd/permisson.guard.ts create mode 100644 projects/manage/src/app/core/services/auth-api.service.ts create mode 100644 projects/manage/src/app/core/services/index.ts create mode 100644 projects/manage/src/app/core/services/manage-api.service.ts create mode 100644 projects/manage/src/app/feature/auth/auth-routing.module.ts create mode 100644 projects/manage/src/app/feature/auth/auth.module.ts create mode 100644 projects/manage/src/app/feature/auth/pages/index.ts create mode 100644 projects/manage/src/app/feature/auth/pages/login/login.component.html create mode 100644 projects/manage/src/app/feature/auth/pages/login/login.component.less create mode 100644 projects/manage/src/app/feature/auth/pages/login/login.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.html create mode 100644 projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.less create mode 100644 projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.html create mode 100644 projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.less create mode 100644 projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.html create mode 100644 projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.less create mode 100644 projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/home/home.component.html create mode 100644 projects/manage/src/app/feature/manage/components/home/home.component.less create mode 100644 projects/manage/src/app/feature/manage/components/home/home.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/index.ts create mode 100644 projects/manage/src/app/feature/manage/components/layout/layout.component.html create mode 100644 projects/manage/src/app/feature/manage/components/layout/layout.component.less create mode 100644 projects/manage/src/app/feature/manage/components/layout/layout.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/notfound/notfound.component.html create mode 100644 projects/manage/src/app/feature/manage/components/notfound/notfound.component.less create mode 100644 projects/manage/src/app/feature/manage/components/notfound/notfound.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/page/page.component.html create mode 100644 projects/manage/src/app/feature/manage/components/page/page.component.less create mode 100644 projects/manage/src/app/feature/manage/components/page/page.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/point-form/point-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/point-form/point-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/point-form/point-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/station-form/station-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/station-form/station-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/station-form/station-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.html create mode 100644 projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.less create mode 100644 projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/components/user-form/user-form.component.html create mode 100644 projects/manage/src/app/feature/manage/components/user-form/user-form.component.less create mode 100644 projects/manage/src/app/feature/manage/components/user-form/user-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/manage-routing.module.ts create mode 100644 projects/manage/src/app/feature/manage/manage.module.ts create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/device/camera/camera.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/device/camera/camera.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/device/camera/camera.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/index.ts create mode 100644 projects/manage/src/app/feature/manage/pages/machine/machine.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/machine/machine.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/machine/machine.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/point/point.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/point/point.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/point/point.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/station/station.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/station/station.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/station/station.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.ts create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.html create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.less create mode 100644 projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.ts create mode 100644 projects/manage/src/app/icons-provider.module.ts create mode 100644 projects/manage/src/app/shared/components/index.ts create mode 100644 projects/manage/src/app/shared/ng-zorro.ts create mode 100644 projects/manage/src/app/shared/shared.module.ts create mode 100644 projects/manage/src/assets/.gitkeep create mode 100644 projects/manage/src/assets/imgs/bg.jpg create mode 100644 projects/manage/src/assets/imgs/logo.png create mode 100644 projects/manage/src/dtos/index.ts create mode 100644 projects/manage/src/environments/environment.prod.ts create mode 100644 projects/manage/src/environments/environment.ts create mode 100644 projects/manage/src/favicon.ico create mode 100644 projects/manage/src/index.html create mode 100644 projects/manage/src/main.ts create mode 100644 projects/manage/src/styles.less create mode 100644 projects/manage/tsconfig.app.json create mode 100644 projects/manage/tsconfig.spec.json create mode 100644 tailwind.config.js create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..59d9a3a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0711527 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..77b3745 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 + "recommendations": ["angular.ng-template"] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..0ca929b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,5 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a298b5b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "start", + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + }, + { + "type": "npm", + "script": "test", + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..74fd2b8 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# Dec 视觉检测项目 + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.2.0. + +## Development server + +* `npm run start:client` +* `npm run start:manage` + + + +## Build + +* `npm run build:client` +* `npm run build:manage` + + +# 7.10 问题 +1. 相机列表需要返回 监测点id、分组id、电站id、相机型号、延时参数 或者新增详情接口 +2. 系统信息管理 保存 一起保存 +3. 主题管理 保存 一起保存 +4. 颜色的设置 +5. ui 端接口 +6. 用户管理 id 、uid 、userId +7. ui 查看权限 +8. 编辑算法 需要的数据 & 名称? +9. 机组管理 机组编号 2#caa +10. 相机管理列表 保存了数据过后就报错了 diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..d88d01e --- /dev/null +++ b/angular.json @@ -0,0 +1,239 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "packageManager": "pnpm", + "analytics": false + }, + "newProjectRoot": "projects", + "projects": { + "client": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "less" + } + }, + "root": "projects/client", + "sourceRoot": "projects/client/src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "baseHref": "/ui/", + "outputPath": "dist/client", + "index": "projects/client/src/index.html", + "main": "projects/client/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "projects/client/tsconfig.app.json", + "inlineStyleLanguage": "less", + "assets": [ + "projects/client/src/favicon.ico", + "projects/client/src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + } + ], + "styles": ["projects/client/src/styles.less"], + "scripts": [], + "fileReplacements": [ + { + "replace": "projects/client/src/environments/environment.ts", + "with": "projects/client/src/environments/environment.prod.ts" + } + ] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "10mb", + "maximumError": "10mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "10mb", + "maximumError": "10mb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "client:build:production" + }, + "development": { + "browserTarget": "client:build:development", + "port": 4396, + "host": "0.0.0.0" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "client:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": ["zone.js", "zone.js/testing"], + "tsConfig": "projects/client/tsconfig.spec.json", + "inlineStyleLanguage": "less", + "assets": ["projects/client/src/favicon.ico", "projects/client/src/assets"], + "styles": ["projects/client/src/styles.less"], + "scripts": [] + } + } + } + }, + "manage": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "less" + } + }, + "root": "projects/manage", + "sourceRoot": "projects/manage/src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "baseHref": "/admin/", + "outputPath": "dist/manage", + "index": "projects/manage/src/index.html", + "main": "projects/manage/src/main.ts", + "polyfills": ["zone.js"], + "tsConfig": "projects/manage/tsconfig.app.json", + "inlineStyleLanguage": "less", + "assets": [ + "projects/manage/src/favicon.ico", + "projects/manage/src/assets", + { + "glob": "**/*", + "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", + "output": "/assets/" + } + ], + "styles": ["projects/manage/src/styles.less"], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "10mb", + "maximumError": "10mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "10mb", + "maximumError": "10mb" + } + ], + "outputHashing": "all", + "fileReplacements": [ + { + "replace": "projects/manage/src/environments/environment.ts", + "with": "projects/manage/src/environments/environment.prod.ts" + } + ] + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "manage:build:production" + }, + "development": { + "browserTarget": "manage:build:development", + "port": 4567, + "host": "0.0.0.0" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "manage:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": ["zone.js", "zone.js/testing"], + "tsConfig": "projects/manage/tsconfig.spec.json", + "inlineStyleLanguage": "less", + "assets": ["projects/manage/src/favicon.ico", "projects/manage/src/assets"], + "styles": ["projects/manage/src/styles.less"], + "scripts": [] + } + } + } + }, + "cdk": { + "projectType": "library", + "root": "projects/cdk", + "sourceRoot": "projects/cdk/src", + "prefix": "dec", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:ng-packagr", + "options": { + "project": "projects/cdk/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "projects/cdk/tsconfig.lib.prod.json" + }, + "development": { + "tsConfig": "projects/cdk/tsconfig.lib.json" + } + }, + "defaultConfiguration": "production" + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "tsConfig": "projects/cdk/tsconfig.spec.json", + "polyfills": ["zone.js", "zone.js/testing"] + } + } + } + } + } +} diff --git a/doc.md b/doc.md new file mode 100644 index 0000000..8a84c17 --- /dev/null +++ b/doc.md @@ -0,0 +1,5 @@ +enableDetect => 0 开启 1 关闭 + +高级设置 + +数据分析 diff --git a/mock/index.ts b/mock/index.ts new file mode 100644 index 0000000..6372d46 --- /dev/null +++ b/mock/index.ts @@ -0,0 +1,38 @@ +import * as Mock from "mockjs"; + +Mock.setup({ + timeout: "200-600", +}); + +const UserMock = [ + { + Url: "/api/user/list", + Method: "get", + Res: { + "data|5-10": [ + { + "Id|+1": "@guid", + "Name|1": "@cname(2)", + }, + ], + }, + }, + { + Url: "/api/user/add", + Method: "post", + Res: { + "Id|1": "@guid", + "Name|1": "@cname()", + }, + }, +]; +// mock数据集 +const routerList = [...UserMock]; + +// 循环创建mock接口拦截数据 +routerList.forEach((e) => { + Mock.mock(e.Url, e.Method, e.Res); +}); + +// 导出Mock +export default Mock; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e55b30c --- /dev/null +++ b/package.json @@ -0,0 +1,54 @@ +{ + "name": "dec-app", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start:client": "ng serve client --proxy-config ./projects/client/proxy.conf.json", + "build:client": "ng build client --vendor-chunk", + "start:manage": "ng serve manage --proxy-config ./projects/manage/proxy.conf.json", + "build:manage": "ng build manage --vendor-chunk", + "watch": "ng build --watch --configuration development", + "test": "ng test" + }, + "private": true, + "dependencies": { + "@angular/animations": "^15.2.0", + "@angular/cdk": "^15.2.6", + "@angular/common": "^15.2.0", + "@angular/compiler": "^15.2.0", + "@angular/core": "^15.2.0", + "@angular/forms": "^15.2.0", + "@angular/platform-browser": "^15.2.0", + "@angular/platform-browser-dynamic": "^15.2.0", + "@angular/router": "^15.2.0", + "@ant-design/icons-angular": "^15.0.0", + "@iplab/ngx-color-picker": "15", + "date-fns": "^2.30.0", + "echarts": "^5.4.2", + "immer": "^10.0.1", + "ng-zorro-antd": "15.1.0", + "ngx-permissions": "^15.0.1", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.12.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^15.2.6", + "@angular/cli": "~15.2.0", + "@angular/compiler-cli": "^15.2.0", + "@types/jasmine": "~4.3.0", + "@types/mockjs": "^1.0.7", + "autoprefixer": "^10.4.14", + "jasmine-core": "~4.5.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.0.0", + "mockjs": "^1.1.0", + "ng-packagr": "^15.2.2", + "postcss": "^8.4.21", + "tailwindcss": "^3.3.1", + "typescript": "~4.9.4" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..b8cf7d7 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7380 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@angular/animations': + specifier: ^15.2.0 + version: 15.2.7(@angular/core@15.2.7) + '@angular/cdk': + specifier: ^15.2.6 + version: 15.2.6(@angular/common@15.2.7)(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/common': + specifier: ^15.2.0 + version: 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/compiler': + specifier: ^15.2.0 + version: 15.2.7(@angular/core@15.2.7) + '@angular/core': + specifier: ^15.2.0 + version: 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/forms': + specifier: ^15.2.0 + version: 15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + '@angular/platform-browser': + specifier: ^15.2.0 + version: 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + '@angular/platform-browser-dynamic': + specifier: ^15.2.0 + version: 15.2.7(@angular/common@15.2.7)(@angular/compiler@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7) + '@angular/router': + specifier: ^15.2.0 + version: 15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + '@ant-design/icons-angular': + specifier: ^15.0.0 + version: 15.0.0(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + '@iplab/ngx-color-picker': + specifier: '15' + version: 15.0.2(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + date-fns: + specifier: ^2.30.0 + version: 2.30.0 + echarts: + specifier: ^5.4.2 + version: 5.4.2 + immer: + specifier: ^10.0.1 + version: 10.0.1 + ng-zorro-antd: + specifier: 15.1.0 + version: 15.1.0(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/forms@15.2.7)(@angular/platform-browser@15.2.7)(@angular/router@15.2.7)(rxjs@7.8.0) + ngx-permissions: + specifier: ^15.0.1 + version: 15.0.1(@angular/core@15.2.7)(@angular/router@15.2.7)(rxjs@7.8.0) + rxjs: + specifier: ~7.8.0 + version: 7.8.0 + tslib: + specifier: ^2.3.0 + version: 2.5.0 + zone.js: + specifier: ~0.12.0 + version: 0.12.0 + +devDependencies: + '@angular-devkit/build-angular': + specifier: ^15.2.6 + version: 15.2.6(@angular/compiler-cli@15.2.7)(karma@6.4.1)(ng-packagr@15.2.2)(tailwindcss@3.3.1)(typescript@4.9.5) + '@angular/cli': + specifier: ~15.2.0 + version: 15.2.6 + '@angular/compiler-cli': + specifier: ^15.2.0 + version: 15.2.7(@angular/compiler@15.2.7)(typescript@4.9.5) + '@types/jasmine': + specifier: ~4.3.0 + version: 4.3.1 + '@types/mockjs': + specifier: ^1.0.7 + version: 1.0.7 + autoprefixer: + specifier: ^10.4.14 + version: 10.4.14(postcss@8.4.21) + jasmine-core: + specifier: ~4.5.0 + version: 4.5.0 + karma: + specifier: ~6.4.0 + version: 6.4.1 + karma-chrome-launcher: + specifier: ~3.1.0 + version: 3.1.1 + karma-coverage: + specifier: ~2.2.0 + version: 2.2.0 + karma-jasmine: + specifier: ~5.1.0 + version: 5.1.0(karma@6.4.1) + karma-jasmine-html-reporter: + specifier: ~2.0.0 + version: 2.0.0(jasmine-core@4.5.0)(karma-jasmine@5.1.0)(karma@6.4.1) + mockjs: + specifier: ^1.1.0 + version: 1.1.0 + ng-packagr: + specifier: ^15.2.2 + version: 15.2.2(@angular/compiler-cli@15.2.7)(tailwindcss@3.3.1)(tslib@2.5.0)(typescript@4.9.5) + postcss: + specifier: ^8.4.21 + version: 8.4.21 + tailwindcss: + specifier: ^3.3.1 + version: 3.3.1(postcss@8.4.21) + typescript: + specifier: ~4.9.4 + version: 4.9.5 + +packages: + + /@ampproject/remapping@2.2.0: + resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.1.1 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@angular-devkit/architect@0.1502.6(chokidar@3.5.3): + resolution: {integrity: sha512-n4oJ9vzFWwabf+AfgqqevVzdJhNKNCav7ytefjD/Y01vkNwlXqWnHcvyyHCLkVibJ6WR8J9lK4t77j/HFlDvWQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 15.2.6(chokidar@3.5.3) + rxjs: 6.6.7 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/build-angular@15.2.6(@angular/compiler-cli@15.2.7)(karma@6.4.1)(ng-packagr@15.2.2)(tailwindcss@3.3.1)(typescript@4.9.5): + resolution: {integrity: sha512-OmMcdXXUrAdZNxwxDE8SUx1FMcq9FyMnrSv1PmP9sHPBoxAdBVc/qNdGA9V7C5yHvWHGgzsx7ZK5TDuvifzS5g==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^15.0.0 + '@angular/localize': ^15.0.0 + '@angular/platform-server': ^15.0.0 + '@angular/service-worker': ^15.0.0 + karma: ^6.3.0 + ng-packagr: ^15.0.0 + protractor: ^7.0.0 + tailwindcss: ^2.0.0 || ^3.0.0 + typescript: '>=4.8.2 <5.0' + peerDependenciesMeta: + '@angular/localize': + optional: true + '@angular/platform-server': + optional: true + '@angular/service-worker': + optional: true + karma: + optional: true + ng-packagr: + optional: true + protractor: + optional: true + tailwindcss: + optional: true + dependencies: + '@ampproject/remapping': 2.2.0 + '@angular-devkit/architect': 0.1502.6(chokidar@3.5.3) + '@angular-devkit/build-webpack': 0.1502.6(chokidar@3.5.3)(webpack-dev-server@4.11.1)(webpack@5.76.1) + '@angular-devkit/core': 15.2.6(chokidar@3.5.3) + '@angular/compiler-cli': 15.2.7(@angular/compiler@15.2.7)(typescript@4.9.5) + '@babel/core': 7.20.12 + '@babel/generator': 7.20.14 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-runtime': 7.19.6(@babel/core@7.20.12) + '@babel/preset-env': 7.20.2(@babel/core@7.20.12) + '@babel/runtime': 7.20.13 + '@babel/template': 7.20.7 + '@discoveryjs/json-ext': 0.5.7 + '@ngtools/webpack': 15.2.6(@angular/compiler-cli@15.2.7)(typescript@4.9.5)(webpack@5.76.1) + ansi-colors: 4.1.3 + autoprefixer: 10.4.13(postcss@8.4.21) + babel-loader: 9.1.2(@babel/core@7.20.12)(webpack@5.76.1) + babel-plugin-istanbul: 6.1.1 + browserslist: 4.21.5 + cacache: 17.0.4 + chokidar: 3.5.3 + copy-webpack-plugin: 11.0.0(webpack@5.76.1) + critters: 0.0.16 + css-loader: 6.7.3(webpack@5.76.1) + esbuild-wasm: 0.17.8 + glob: 8.1.0 + https-proxy-agent: 5.0.1 + inquirer: 8.2.4 + jsonc-parser: 3.2.0 + karma: 6.4.1 + karma-source-map-support: 1.4.0 + less: 4.1.3 + less-loader: 11.1.0(less@4.1.3)(webpack@5.76.1) + license-webpack-plugin: 4.0.2(webpack@5.76.1) + loader-utils: 3.2.1 + magic-string: 0.29.0 + mini-css-extract-plugin: 2.7.2(webpack@5.76.1) + ng-packagr: 15.2.2(@angular/compiler-cli@15.2.7)(tailwindcss@3.3.1)(tslib@2.5.0)(typescript@4.9.5) + open: 8.4.1 + ora: 5.4.1 + parse5-html-rewriting-stream: 7.0.0 + piscina: 3.2.0 + postcss: 8.4.21 + postcss-loader: 7.0.2(postcss@8.4.21)(webpack@5.76.1) + resolve-url-loader: 5.0.0 + rxjs: 6.6.7 + sass: 1.58.1 + sass-loader: 13.2.0(sass@1.58.1)(webpack@5.76.1) + semver: 7.3.8 + source-map-loader: 4.0.1(webpack@5.76.1) + source-map-support: 0.5.21 + tailwindcss: 3.3.1(postcss@8.4.21) + terser: 5.16.3 + text-table: 0.2.0 + tree-kill: 1.2.2 + tslib: 2.5.0 + typescript: 4.9.5 + webpack: 5.76.1(esbuild@0.17.8) + webpack-dev-middleware: 6.0.1(webpack@5.76.1) + webpack-dev-server: 4.11.1(webpack@5.76.1) + webpack-merge: 5.8.0 + webpack-subresource-integrity: 5.1.0(webpack@5.76.1) + optionalDependencies: + esbuild: 0.17.8 + transitivePeerDependencies: + - '@swc/core' + - bluebird + - bufferutil + - debug + - fibers + - html-webpack-plugin + - node-sass + - sass-embedded + - supports-color + - uglify-js + - utf-8-validate + - webpack-cli + dev: true + + /@angular-devkit/build-webpack@0.1502.6(chokidar@3.5.3)(webpack-dev-server@4.11.1)(webpack@5.76.1): + resolution: {integrity: sha512-X7XQ11QDz2Bs5qpJ3a5glIytvI+S74ORQxdzvT6a6KB8ayW0SgZEhTwD+GF7pa5My8draIaXBGzzQR1qmpWK5Q==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + webpack: ^5.30.0 + webpack-dev-server: ^4.0.0 + dependencies: + '@angular-devkit/architect': 0.1502.6(chokidar@3.5.3) + rxjs: 6.6.7 + webpack: 5.76.1(esbuild@0.17.8) + webpack-dev-server: 4.11.1(webpack@5.76.1) + transitivePeerDependencies: + - chokidar + dev: true + + /@angular-devkit/core@15.2.6(chokidar@3.5.3): + resolution: {integrity: sha512-YVTWZ+M+xNKdFX4EnY9QX49PZraawiaA0iTd2CUW8ZoTUvU7yOGMKZLSdz6aokTMRVfm0449wt6YL994ibOo1g==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^3.5.2 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + chokidar: 3.5.3 + jsonc-parser: 3.2.0 + rxjs: 6.6.7 + source-map: 0.7.4 + dev: true + + /@angular-devkit/schematics@15.2.6: + resolution: {integrity: sha512-f7VgnAcok7AwR/DhX0ZWskB0rFBo/KsvtIUA2qZSrpKMf8eFiwu03dv/b2mI0vnf+1FBfIQzJvO0ww45zRp6dA==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 15.2.6(chokidar@3.5.3) + jsonc-parser: 3.2.0 + magic-string: 0.29.0 + ora: 5.4.1 + rxjs: 6.6.7 + transitivePeerDependencies: + - chokidar + dev: true + + /@angular/animations@15.2.7(@angular/core@15.2.7): + resolution: {integrity: sha512-Vmy0AljHc/GOp87O2x0mxUDiyfJFW8ndDE9Xrm/g0rnLnNWsaLtLXr1TWbwF7eTqKA3k/QcUvYAjLMWKvjyKgQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/core': 15.2.7 + dependencies: + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + tslib: 2.5.0 + dev: false + + /@angular/cdk@15.2.6(@angular/common@15.2.7)(@angular/core@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-c6XFKMFowllHxb4tUt9en3bXBDqXKG2k4O9XGggJ1TL668d3Uhlk9qULywFNVWmNQSamkERmhFKAN4hEO3TPAQ==} + peerDependencies: + '@angular/common': ^15.0.0 || ^16.0.0 + '@angular/core': ^15.0.0 || ^16.0.0 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + rxjs: 7.8.0 + tslib: 2.5.0 + optionalDependencies: + parse5: 7.1.2 + dev: false + + /@angular/cli@15.2.6: + resolution: {integrity: sha512-wNkQ/qCVbd4pERaGVagKJPifEvjRNY5otwsd4iRVubY/XOcIHcYChUThZwgQdVfNAImfJPMZNrhbGxejuWLA9w==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + dependencies: + '@angular-devkit/architect': 0.1502.6(chokidar@3.5.3) + '@angular-devkit/core': 15.2.6(chokidar@3.5.3) + '@angular-devkit/schematics': 15.2.6 + '@schematics/angular': 15.2.6 + '@yarnpkg/lockfile': 1.1.0 + ansi-colors: 4.1.3 + ini: 3.0.1 + inquirer: 8.2.4 + jsonc-parser: 3.2.0 + npm-package-arg: 10.1.0 + npm-pick-manifest: 8.0.1 + open: 8.4.1 + ora: 5.4.1 + pacote: 15.1.0 + resolve: 1.22.1 + semver: 7.3.8 + symbol-observable: 4.0.0 + yargs: 17.6.2 + transitivePeerDependencies: + - bluebird + - chokidar + - supports-color + dev: true + + /@angular/common@15.2.7(@angular/core@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-CbmrQeZ0yChQrF/ab3v+gv6x2uLbv/s1wZNUBSO/p1STz6BZzHRJqObVlfPlQvyBx5btBBy/+I1sUh1yumARDA==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/core': 15.2.7 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + rxjs: 7.8.0 + tslib: 2.5.0 + dev: false + + /@angular/compiler-cli@15.2.7(@angular/compiler@15.2.7)(typescript@4.9.5): + resolution: {integrity: sha512-4v51dOaT8GDUzRh6+mCLZOaYuU9FYX6vOHaLod9np3tVWPhcpoF2ZklRSiQDeFqrhr5B4vuCp/Lh9N2wzc22XQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + hasBin: true + peerDependencies: + '@angular/compiler': 15.2.7 + typescript: '>=4.8.2 <5.0' + dependencies: + '@angular/compiler': 15.2.7(@angular/core@15.2.7) + '@babel/core': 7.19.3 + '@jridgewell/sourcemap-codec': 1.4.15 + chokidar: 3.5.3 + convert-source-map: 1.9.0 + dependency-graph: 0.11.0 + magic-string: 0.27.0 + reflect-metadata: 0.1.13 + semver: 7.4.0 + tslib: 2.5.0 + typescript: 4.9.5 + yargs: 17.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@angular/compiler@15.2.7(@angular/core@15.2.7): + resolution: {integrity: sha512-SesyYI2ExUa13XukXgIsmfg3ar90HbWeWDJTgmzsIfph0M9t6+SaPGpf3FCtdBgNADIpUFp3cieCOJgLESzxYQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/core': 15.2.7 + peerDependenciesMeta: + '@angular/core': + optional: true + dependencies: + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + tslib: 2.5.0 + + /@angular/core@15.2.7(rxjs@7.8.0)(zone.js@0.12.0): + resolution: {integrity: sha512-iS7JCJubRFqdndoUdAnvNkQRT3tY5tNFupBQS/sytkwxVrdBg+Is5jpdgk741n824vTMsE+CnuY0SETar8rN6g==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + rxjs: ^6.5.3 || ^7.4.0 + zone.js: ~0.11.4 || ~0.12.0 || ~0.13.0 + dependencies: + rxjs: 7.8.0 + tslib: 2.5.0 + zone.js: 0.12.0 + + /@angular/forms@15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-rzrebDIrtxxOeMcBzRBxqaOBZ+T1DJrysG/6YWZy428W/Z3MfPxUarPxgfx/oZI+x5uUsDaZmyoRdhVPJ2KhZg==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/common': 15.2.7 + '@angular/core': 15.2.7 + '@angular/platform-browser': 15.2.7 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/platform-browser': 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + rxjs: 7.8.0 + tslib: 2.5.0 + dev: false + + /@angular/platform-browser-dynamic@15.2.7(@angular/common@15.2.7)(@angular/compiler@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7): + resolution: {integrity: sha512-t1Nf7hgbcYvhmxuzgUtsV47jrI5CXUBqrtz5I0ilWG92zZTig5qvfd1/2Ub8NHz87uHNrnggyZpL2+4MJ26nyQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/common': 15.2.7 + '@angular/compiler': 15.2.7 + '@angular/core': 15.2.7 + '@angular/platform-browser': 15.2.7 + dependencies: + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/compiler': 15.2.7(@angular/core@15.2.7) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/platform-browser': 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + tslib: 2.5.0 + dev: false + + /@angular/platform-browser@15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7): + resolution: {integrity: sha512-aCbd7xyuP7c2eDITkOTDO2mqP550WHCBN8U6VnjysqtB5ocbJtR6z/MIRItN/Zx+xj3piiaKei//XIkb3Q5fXQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/animations': 15.2.7 + '@angular/common': 15.2.7 + '@angular/core': 15.2.7 + peerDependenciesMeta: + '@angular/animations': + optional: true + dependencies: + '@angular/animations': 15.2.7(@angular/core@15.2.7) + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + tslib: 2.5.0 + dev: false + + /@angular/router@15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-Wkk+oJSUrVafJjmv9uE1SoY4wDE9bjX7ald+UXePz+QyM/PFoLkm/CzLYjFBkJnsOkOVxw1VmvacoUjWN6BCTQ==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + peerDependencies: + '@angular/common': 15.2.7 + '@angular/core': 15.2.7 + '@angular/platform-browser': 15.2.7 + rxjs: ^6.5.3 || ^7.4.0 + dependencies: + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/platform-browser': 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + rxjs: 7.8.0 + tslib: 2.5.0 + dev: false + + /@ant-design/colors@5.1.1: + resolution: {integrity: sha512-Txy4KpHrp3q4XZdfgOBqLl+lkQIc3tEvHXOimRN1giX1AEC7mGtyrO9p8iRGJ3FLuVMGa2gNEzQyghVymLttKQ==} + dependencies: + '@ctrl/tinycolor': 3.6.0 + dev: false + + /@ant-design/icons-angular@15.0.0(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-9DMpuoqZBvS7+VJ0s3tl2g/kI1sTLDQWfykiXYa+AkZ2AvJwHebvR7Cw7/xfiXFDLyZTjPgtC0x0gex13EShuA==} + peerDependencies: + '@angular/common': ^15.0.0 + '@angular/core': ^15.0.0 + '@angular/platform-browser': ^15.0.0 + rxjs: ^6.4.0 || ^7.4.0 + dependencies: + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/platform-browser': 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + '@ant-design/colors': 5.1.1 + rxjs: 7.8.0 + tslib: 2.5.0 + dev: false + + /@assemblyscript/loader@0.10.1: + resolution: {integrity: sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==} + dev: true + + /@babel/code-frame@7.21.4: + resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.18.6 + dev: true + + /@babel/compat-data@7.21.4: + resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.19.3: + resolution: {integrity: sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.19.3) + '@babel/helper-module-transforms': 7.21.2 + '@babel/helpers': 7.21.0 + '@babel/parser': 7.21.4 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core@7.20.12: + resolution: {integrity: sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-module-transforms': 7.21.2 + '@babel/helpers': 7.21.0 + '@babel/parser': 7.21.4 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/core@7.21.4: + resolution: {integrity: sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.21.4) + '@babel/helper-module-transforms': 7.21.2 + '@babel/helpers': 7.21.0 + '@babel/parser': 7.21.4 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + convert-source-map: 1.9.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.20.14: + resolution: {integrity: sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + '@jridgewell/gen-mapping': 0.3.3 + jsesc: 2.5.2 + dev: true + + /@babel/generator@7.21.4: + resolution: {integrity: sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.18.6: + resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: + resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-explode-assignable-expression': 7.18.6 + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-compilation-targets@7.21.4(@babel/core@7.19.3): + resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.19.3 + '@babel/helper-validator-option': 7.21.0 + browserslist: 4.21.5 + lru-cache: 5.1.1 + semver: 6.3.0 + dev: true + + /@babel/helper-compilation-targets@7.21.4(@babel/core@7.20.12): + resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.20.12 + '@babel/helper-validator-option': 7.21.0 + browserslist: 4.21.5 + lru-cache: 5.1.1 + semver: 6.3.0 + dev: true + + /@babel/helper-compilation-targets@7.21.4(@babel/core@7.21.4): + resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.21.4 + '@babel/helper-validator-option': 7.21.0 + browserslist: 4.21.5 + lru-cache: 5.1.1 + semver: 6.3.0 + dev: true + + /@babel/helper-create-class-features-plugin@7.21.4(@babel/core@7.20.12): + resolution: {integrity: sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-split-export-declaration': 7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-create-regexp-features-plugin@7.21.4(@babel/core@7.20.12): + resolution: {integrity: sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-annotate-as-pure': 7.18.6 + regexpu-core: 5.3.2 + dev: true + + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.20.12): + resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.1 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.18.9: + resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-explode-assignable-expression@7.18.6: + resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-function-name@7.21.0: + resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-hoist-variables@7.18.6: + resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-member-expression-to-functions@7.21.0: + resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-module-imports@7.21.4: + resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-module-transforms@7.21.2: + resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-module-imports': 7.21.4 + '@babel/helper-simple-access': 7.20.2 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-optimise-call-expression@7.18.6: + resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-plugin-utils@7.20.2: + resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-wrap-function': 7.20.5 + '@babel/types': 7.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-replace-supers@7.20.7: + resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access@7.20.2: + resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.20.0: + resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-split-export-declaration@7.18.6: + resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/helper-string-parser@7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.19.1: + resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.21.0: + resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.20.5: + resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.21.0 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helpers@7.21.0: + resolution: {integrity: sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.4 + '@babel/types': 7.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.18.6: + resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.19.1 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.21.4: + resolution: {integrity: sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.21.4 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.20.12) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.20.12) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.20.12 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.20.12) + dev: true + + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.20.12) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} + engines: {node: '>=4'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.20.12): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.20.12): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.20.12): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.20.12): + resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.20.12): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.20.12): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.20.12): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.20.12): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.20.12): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-arrow-functions@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-imports': 7.21.4 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.20.12) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-split-export-declaration': 7.18.6 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-computed-properties@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/template': 7.20.7 + dev: true + + /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.20.12): + resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-for-of@7.21.0(@babel/core@7.20.12): + resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-function-name': 7.21.0 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.20.12): + resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.20.12): + resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-simple-access': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.20.12): + resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-identifier': 7.19.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.20.12): + resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.20.12): + resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-regenerator@7.20.5(@babel/core@7.20.12): + resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + regenerator-transform: 0.15.1 + dev: true + + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-runtime@7.19.6(@babel/core@7.20.12): + resolution: {integrity: sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-module-imports': 7.21.4 + '@babel/helper-plugin-utils': 7.20.2 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.20.12) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.20.12) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.20.12) + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-spread@7.20.7(@babel/core@7.20.12): + resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + dev: true + + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.20.12): + resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.20.12): + resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.20.12): + resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/preset-env@7.20.2(@babel/core@7.20.12): + resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.20.12 + '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.20.12) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.20.12) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.20.12) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.20.12) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.20.12) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.20.12) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.20.12) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.20.12) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.20.12) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.20.12) + '@babel/plugin-transform-arrow-functions': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-transform-computed-properties': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.20.12) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-for-of': 7.21.0(@babel/core@7.20.12) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.20.12) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.20.12) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.20.12) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.20.12) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.20.12) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-regenerator': 7.20.5(@babel/core@7.20.12) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.20.12) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.20.12) + '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.20.12) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.20.12) + '@babel/preset-modules': 0.1.5(@babel/core@7.20.12) + '@babel/types': 7.21.4 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.20.12) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.20.12) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.20.12) + core-js-compat: 3.30.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.5(@babel/core@7.20.12): + resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.20.12) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.20.12) + '@babel/types': 7.21.4 + esutils: 2.0.3 + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.20.13: + resolution: {integrity: sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: true + + /@babel/runtime@7.21.5: + resolution: {integrity: sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + + /@babel/template@7.20.7: + resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.21.4 + '@babel/parser': 7.21.4 + '@babel/types': 7.21.4 + dev: true + + /@babel/traverse@7.21.4: + resolution: {integrity: sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.21.4 + '@babel/generator': 7.21.4 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.21.4 + '@babel/types': 7.21.4 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.21.4: + resolution: {integrity: sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + dev: true + + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + dev: true + + /@ctrl/tinycolor@3.6.0: + resolution: {integrity: sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ==} + engines: {node: '>=10'} + dev: false + + /@discoveryjs/json-ext@0.5.7: + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + dev: true + + /@esbuild/android-arm64@0.17.8: + resolution: {integrity: sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.17.8: + resolution: {integrity: sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.17.8: + resolution: {integrity: sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.17.8: + resolution: {integrity: sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.17.8: + resolution: {integrity: sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.17.8: + resolution: {integrity: sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.17.8: + resolution: {integrity: sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.17.8: + resolution: {integrity: sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.17.8: + resolution: {integrity: sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.17.8: + resolution: {integrity: sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.17.8: + resolution: {integrity: sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.17.8: + resolution: {integrity: sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.17.8: + resolution: {integrity: sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.17.8: + resolution: {integrity: sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.17.8: + resolution: {integrity: sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.17.8: + resolution: {integrity: sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.17.8: + resolution: {integrity: sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.17.8: + resolution: {integrity: sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.17.8: + resolution: {integrity: sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.17.8: + resolution: {integrity: sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.17.8: + resolution: {integrity: sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.17.8: + resolution: {integrity: sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@gar/promisify@1.1.3: + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + dev: true + + /@iplab/ngx-color-picker@15.0.2(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7): + resolution: {integrity: sha512-wum0Hg4Ky/6mhvzolEpFpjGckOjN8L2nkXvy3mWUVclFHP9MZqqgpJaxghtax7/tMdEWQnwQI3PYsNyKfF15ug==} + peerDependencies: + '@angular/animations': ^15.0.0 + '@angular/common': ^15.0.0 + '@angular/core': ^15.0.0 + dependencies: + '@angular/animations': 15.2.7(@angular/core@15.2.7) + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + tslib: 2.5.0 + dev: false + + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jridgewell/gen-mapping@0.1.1: + resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@jridgewell/resolve-uri@3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.3: + resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 + dev: true + + /@jridgewell/sourcemap-codec@1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + + /@leichtgewicht/ip-codec@2.0.4: + resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} + dev: true + + /@ngtools/webpack@15.2.6(@angular/compiler-cli@15.2.7)(typescript@4.9.5)(webpack@5.76.1): + resolution: {integrity: sha512-I+kekKItfsCLdX+ZjjmsWqd0AyoYGTQPjlbQAiPtmdH73/rfPOF4Q/3AU4tzTdn0n0GXqZWv6VOs91w99ydi0A==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + '@angular/compiler-cli': ^15.0.0 + typescript: '>=4.8.2 <5.0' + webpack: ^5.54.0 + dependencies: + '@angular/compiler-cli': 15.2.7(@angular/compiler@15.2.7)(typescript@4.9.5) + typescript: 4.9.5 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@npmcli/fs@2.1.2: + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.4.0 + dev: true + + /@npmcli/fs@3.1.0: + resolution: {integrity: sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + semver: 7.4.0 + dev: true + + /@npmcli/git@4.0.4: + resolution: {integrity: sha512-5yZghx+u5M47LghaybLCkdSyFzV/w4OuH12d96HO389Ik9CDsLaDZJVynSGGVJOLn6gy/k7Dz5XYcplM3uxXRg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/promise-spawn': 6.0.2 + lru-cache: 7.18.3 + npm-pick-manifest: 8.0.1 + proc-log: 3.0.0 + promise-inflight: 1.0.1 + promise-retry: 2.0.1 + semver: 7.4.0 + which: 3.0.0 + transitivePeerDependencies: + - bluebird + dev: true + + /@npmcli/installed-package-contents@2.0.2: + resolution: {integrity: sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + npm-bundled: 3.0.0 + npm-normalize-package-bin: 3.0.0 + dev: true + + /@npmcli/move-file@2.0.1: + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + dev: true + + /@npmcli/node-gyp@3.0.0: + resolution: {integrity: sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@npmcli/promise-spawn@6.0.2: + resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + which: 3.0.0 + dev: true + + /@npmcli/run-script@6.0.0: + resolution: {integrity: sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/node-gyp': 3.0.0 + '@npmcli/promise-spawn': 6.0.2 + node-gyp: 9.3.1 + read-package-json-fast: 3.0.2 + which: 3.0.0 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /@rollup/plugin-json@6.0.0(rollup@3.20.6): + resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.20.6) + rollup: 3.20.6 + dev: true + + /@rollup/plugin-node-resolve@15.0.2(rollup@3.20.6): + resolution: {integrity: sha512-Y35fRGUjC3FaurG722uhUuG8YHOJRJQbI6/CkbRkdPotSpDj9NtIN85z1zrcyDcCQIW4qp5mgG72U+gJ0TAFEg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2(rollup@3.20.6) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-builtin-module: 3.2.1 + is-module: 1.0.0 + resolve: 1.22.1 + rollup: 3.20.6 + dev: true + + /@rollup/pluginutils@5.0.2(rollup@3.20.6): + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 3.20.6 + dev: true + + /@schematics/angular@15.2.6: + resolution: {integrity: sha512-OcBUvVAxZEMBX+fi0ytybeAdmStra+GwtlvipS70yOxcAgJ84ZrnZGN7a072cCVQcq7AgqUfssnyqCx1wu+yCg==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + dependencies: + '@angular-devkit/core': 15.2.6(chokidar@3.5.3) + '@angular-devkit/schematics': 15.2.6 + jsonc-parser: 3.2.0 + transitivePeerDependencies: + - chokidar + dev: true + + /@sigstore/protobuf-specs@0.1.0: + resolution: {integrity: sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@socket.io/component-emitter@3.1.0: + resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + dev: true + + /@tootallnate/once@2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true + + /@tufjs/canonical-json@1.0.0: + resolution: {integrity: sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /@tufjs/models@1.0.2: + resolution: {integrity: sha512-uxarDtxTIK3f8hJS4yFhW/lvTa3tsiQU5iDCRut+NCnOXvNtEul0Ct58NIIcIx9Rkt7OFEK31Ndpqsd663nsew==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@tufjs/canonical-json': 1.0.0 + minimatch: 8.0.4 + dev: true + + /@types/body-parser@1.19.2: + resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} + dependencies: + '@types/connect': 3.4.35 + '@types/node': 18.15.11 + dev: true + + /@types/bonjour@3.5.10: + resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/connect-history-api-fallback@1.3.5: + resolution: {integrity: sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==} + dependencies: + '@types/express-serve-static-core': 4.17.33 + '@types/node': 18.15.11 + dev: true + + /@types/connect@3.4.35: + resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/cookie@0.4.1: + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + dev: true + + /@types/cors@2.8.13: + resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/eslint-scope@3.7.4: + resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} + dependencies: + '@types/eslint': 8.37.0 + '@types/estree': 0.0.51 + dev: true + + /@types/eslint@8.37.0: + resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==} + dependencies: + '@types/estree': 0.0.51 + '@types/json-schema': 7.0.11 + dev: true + + /@types/estree@0.0.51: + resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + dev: true + + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: true + + /@types/express-serve-static-core@4.17.33: + resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} + dependencies: + '@types/node': 18.15.11 + '@types/qs': 6.9.7 + '@types/range-parser': 1.2.4 + dev: true + + /@types/express@4.17.17: + resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 4.17.33 + '@types/qs': 6.9.7 + '@types/serve-static': 1.15.1 + dev: true + + /@types/http-proxy@1.17.10: + resolution: {integrity: sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/jasmine@4.3.1: + resolution: {integrity: sha512-Vu8l+UGcshYmV1VWwULgnV/2RDbBaO6i2Ptx7nd//oJPIZGhoI1YLST4VKagD2Pq/Bc2/7zvtvhM7F3p4SN7kQ==} + dev: true + + /@types/json-schema@7.0.11: + resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} + dev: true + + /@types/mime@3.0.1: + resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} + dev: true + + /@types/mockjs@1.0.7: + resolution: {integrity: sha512-OCxXz6hEaJOVpRwuJMiVY5a6LtJcih+br9gwB/Q8ooOBikvk5FpBQ31OlNimXo3EqKha1Z7PFBni+q9m+8NCWg==} + dev: true + + /@types/node@18.15.11: + resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} + dev: true + + /@types/parse-json@4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: true + + /@types/qs@6.9.7: + resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} + dev: true + + /@types/range-parser@1.2.4: + resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} + dev: true + + /@types/resolve@1.20.2: + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + dev: true + + /@types/retry@0.12.0: + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + dev: true + + /@types/serve-index@1.9.1: + resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} + dependencies: + '@types/express': 4.17.17 + dev: true + + /@types/serve-static@1.15.1: + resolution: {integrity: sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==} + dependencies: + '@types/mime': 3.0.1 + '@types/node': 18.15.11 + dev: true + + /@types/sockjs@0.3.33: + resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@types/ws@8.5.4: + resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} + dependencies: + '@types/node': 18.15.11 + dev: true + + /@webassemblyjs/ast@1.11.1: + resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.1: + resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.1: + resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} + dev: true + + /@webassemblyjs/helper-buffer@1.11.1: + resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} + dev: true + + /@webassemblyjs/helper-numbers@1.11.1: + resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.1: + resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} + dev: true + + /@webassemblyjs/helper-wasm-section@1.11.1: + resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + dev: true + + /@webassemblyjs/ieee754@1.11.1: + resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128@1.11.1: + resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8@1.11.1: + resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} + dev: true + + /@webassemblyjs/wasm-edit@1.11.1: + resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/helper-wasm-section': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-opt': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + '@webassemblyjs/wast-printer': 1.11.1 + dev: true + + /@webassemblyjs/wasm-gen@1.11.1: + resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wasm-opt@1.11.1: + resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-buffer': 1.11.1 + '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + dev: true + + /@webassemblyjs/wasm-parser@1.11.1: + resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/helper-api-error': 1.11.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/ieee754': 1.11.1 + '@webassemblyjs/leb128': 1.11.1 + '@webassemblyjs/utf8': 1.11.1 + dev: true + + /@webassemblyjs/wast-printer@1.11.1: + resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} + dependencies: + '@webassemblyjs/ast': 1.11.1 + '@xtuc/long': 4.2.2 + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /@yarnpkg/lockfile@1.1.0: + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + dev: true + + /abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + dev: true + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: true + + /acorn-import-assertions@1.8.0(acorn@8.8.2): + resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.8.2 + dev: true + + /acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.2.11 + dev: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /agentkeepalive@4.3.0: + resolution: {integrity: sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==} + engines: {node: '>= 8.0.0'} + dependencies: + debug: 4.3.4 + depd: 2.0.0 + humanize-ms: 1.2.1 + transitivePeerDependencies: + - supports-color + dev: true + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + dev: true + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv-keywords@5.1.0(ajv@8.12.0): + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + dependencies: + ajv: 8.12.0 + fast-deep-equal: 3.1.3 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + dev: true + + /are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: true + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: true + + /array-flatten@2.1.2: + resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} + dev: true + + /autoprefixer@10.4.13(postcss@8.4.21): + resolution: {integrity: sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.21.5 + caniuse-lite: 1.0.30001478 + fraction.js: 4.2.0 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.21 + postcss-value-parser: 4.2.0 + dev: true + + /autoprefixer@10.4.14(postcss@8.4.21): + resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.21.5 + caniuse-lite: 1.0.30001478 + fraction.js: 4.2.0 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.21 + postcss-value-parser: 4.2.0 + dev: true + + /babel-loader@9.1.2(@babel/core@7.20.12)(webpack@5.76.1): + resolution: {integrity: sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.20.12 + find-cache-dir: 3.3.2 + schema-utils: 4.0.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.20.2 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.20.12): + resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.4 + '@babel/core': 7.20.12 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.20.12) + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.20.12): + resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.20.12) + core-js-compat: 3.30.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.20.12): + resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.20.12 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.20.12) + transitivePeerDependencies: + - supports-color + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + + /base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + dev: true + + /batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /bonjour-service@1.1.1: + resolution: {integrity: sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==} + dependencies: + array-flatten: 2.1.2 + dns-equal: 1.0.0 + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + dev: true + + /boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.21.5: + resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001478 + electron-to-chromium: 1.4.361 + node-releases: 2.0.10 + update-browserslist-db: 1.0.10(browserslist@4.21.5) + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.4.0 + dev: true + + /bytes@3.0.0: + resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} + engines: {node: '>= 0.8'} + dev: true + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + + /cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.1.13 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + dev: true + + /cacache@17.0.4: + resolution: {integrity: sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/fs': 3.1.0 + fs-minipass: 3.0.1 + glob: 8.1.0 + lru-cache: 7.18.3 + minipass: 4.2.8 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + ssri: 10.0.3 + tar: 6.1.13 + unique-filename: 3.0.0 + transitivePeerDependencies: + - bluebird + dev: true + + /cacache@17.0.5: + resolution: {integrity: sha512-Y/PRQevNSsjAPWykl9aeGz8Pr+OI6BYM9fYDNMvOkuUiG9IhG4LEmaYrZZZvioMUEQ+cBCxT0v8wrnCURccyKA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@npmcli/fs': 3.1.0 + fs-minipass: 3.0.1 + glob: 9.3.5 + lru-cache: 7.18.3 + minipass: 4.2.8 + minipass-collect: 1.0.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + promise-inflight: 1.0.1 + ssri: 10.0.3 + tar: 6.1.13 + unique-filename: 3.0.0 + transitivePeerDependencies: + - bluebird + dev: true + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.0 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite@1.0.30001478: + resolution: {integrity: sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + dev: true + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-spinners@2.8.0: + resolution: {integrity: sha512-/eG5sJcvEIwxcdYM86k5tPwn0MUzkX5YY3eImTGpJOZgVe4SdTMY14vQpcxgBzJ0wXwAYrS8E+c3uHeK4JNyzQ==} + engines: {node: '>=6'} + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone-deep@4.0.1: + resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} + engines: {node: '>=6'} + dependencies: + is-plain-object: 2.0.4 + kind-of: 6.0.3 + shallow-clone: 3.0.1 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + dev: true + + /colorette@2.0.19: + resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} + dev: true + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /compression@1.7.4: + resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + bytes: 3.0.0 + compressible: 2.0.18 + debug: 2.6.9 + on-headers: 1.0.2 + safe-buffer: 5.1.2 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: true + + /connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + dev: true + + /connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + dev: true + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: true + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cookie-signature@1.0.6: + resolution: {integrity: sha1-4wOogrNCzD7oylE6eZmXNNqzriw=} + dev: true + + /cookie@0.4.2: + resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} + engines: {node: '>= 0.6'} + dev: true + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: true + + /copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + dependencies: + is-what: 3.14.1 + dev: true + + /copy-webpack-plugin@11.0.0(webpack@5.76.1): + resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.1.0 + dependencies: + fast-glob: 3.2.12 + glob-parent: 6.0.2 + globby: 13.1.4 + normalize-path: 3.0.0 + schema-utils: 4.0.0 + serialize-javascript: 6.0.1 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /core-js-compat@3.30.0: + resolution: {integrity: sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==} + dependencies: + browserslist: 4.21.5 + dev: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: true + + /critters@0.0.16: + resolution: {integrity: sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==} + dependencies: + chalk: 4.1.2 + css-select: 4.3.0 + parse5: 6.0.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + postcss: 8.4.21 + pretty-bytes: 5.6.0 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /css-loader@6.7.3(webpack@5.76.1): + resolution: {integrity: sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.21) + postcss: 8.4.21 + postcss-modules-extract-imports: 3.0.0(postcss@8.4.21) + postcss-modules-local-by-default: 4.0.0(postcss@8.4.21) + postcss-modules-scope: 3.0.0(postcss@8.4.21) + postcss-modules-values: 4.0.0(postcss@8.4.21) + postcss-value-parser: 4.2.0 + semver: 7.4.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + dev: true + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /cuint@0.2.2: + resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} + dev: true + + /custom-event@1.0.1: + resolution: {integrity: sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==} + dev: true + + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.21.5 + dev: false + + /date-format@4.0.14: + resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} + engines: {node: '>=4.0'} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + optional: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + dependencies: + execa: 5.1.1 + dev: true + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + dev: true + + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dev: true + + /depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + dev: true + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: true + + /dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + dev: true + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: true + + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + dev: true + + /di@0.0.1: + resolution: {integrity: sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==} + dev: true + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: true + + /dns-equal@1.0.0: + resolution: {integrity: sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==} + dev: true + + /dns-packet@5.5.0: + resolution: {integrity: sha512-USawdAUzRkV6xrqTjiAEp6M9YagZEzWcSUaZTcIFAiyQWW1SoI6KyId8y2+/71wbgHKQAKd+iupLv4YvEwYWvA==} + engines: {node: '>=6'} + dependencies: + '@leichtgewicht/ip-codec': 2.0.4 + dev: true + + /dom-serialize@2.2.1: + resolution: {integrity: sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==} + dependencies: + custom-event: 1.0.1 + ent: 2.2.0 + extend: 3.0.2 + void-elements: 2.0.1 + dev: true + + /dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + dev: true + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: true + + /domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: true + + /domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + dev: true + + /echarts@5.4.2: + resolution: {integrity: sha512-2W3vw3oI2tWJdyAz+b8DuWS0nfXtSDqlDmqgin/lfzbkB01cuMEN66KWBlmur3YMp5nEDEEt5s23pllnAzB4EA==} + dependencies: + tslib: 2.3.0 + zrender: 5.4.3 + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=} + dev: true + + /electron-to-chromium@1.4.361: + resolution: {integrity: sha512-VocVwjPp05HUXzf3xmL0boRn5b0iyqC7amtDww84Jb1QJNPBc7F69gJyEeXRoriLBC4a5pSyckdllrXAg4mmRA==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: true + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: true + + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + requiresBuild: true + dependencies: + iconv-lite: 0.6.3 + dev: true + optional: true + + /engine.io-parser@5.0.6: + resolution: {integrity: sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==} + engines: {node: '>=10.0.0'} + dev: true + + /engine.io@6.4.1: + resolution: {integrity: sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==} + engines: {node: '>=10.0.0'} + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.13 + '@types/node': 18.15.11 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.4.2 + cors: 2.8.5 + debug: 4.3.4 + engine.io-parser: 5.0.6 + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /enhanced-resolve@5.12.0: + resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /ent@2.2.0: + resolution: {integrity: sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==} + dev: true + + /entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + dev: true + + /entities@4.4.0: + resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} + engines: {node: '>=0.12'} + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + dev: true + + /errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + requiresBuild: true + dependencies: + prr: 1.0.1 + dev: true + optional: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-module-lexer@0.9.3: + resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + dev: true + + /esbuild-wasm@0.17.8: + resolution: {integrity: sha512-zCmpxv95E0FuCmvdw1K836UHnj4EdiQnFfjTby35y3LAjRPtXMj3sbHDRHjbD8Mqg5lTwq3knacr/1qIFU51CQ==} + engines: {node: '>=12'} + hasBin: true + dev: true + + /esbuild@0.17.8: + resolution: {integrity: sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.8 + '@esbuild/android-arm64': 0.17.8 + '@esbuild/android-x64': 0.17.8 + '@esbuild/darwin-arm64': 0.17.8 + '@esbuild/darwin-x64': 0.17.8 + '@esbuild/freebsd-arm64': 0.17.8 + '@esbuild/freebsd-x64': 0.17.8 + '@esbuild/linux-arm': 0.17.8 + '@esbuild/linux-arm64': 0.17.8 + '@esbuild/linux-ia32': 0.17.8 + '@esbuild/linux-loong64': 0.17.8 + '@esbuild/linux-mips64el': 0.17.8 + '@esbuild/linux-ppc64': 0.17.8 + '@esbuild/linux-riscv64': 0.17.8 + '@esbuild/linux-s390x': 0.17.8 + '@esbuild/linux-x64': 0.17.8 + '@esbuild/netbsd-x64': 0.17.8 + '@esbuild/openbsd-x64': 0.17.8 + '@esbuild/sunos-x64': 0.17.8 + '@esbuild/win32-arm64': 0.17.8 + '@esbuild/win32-ia32': 0.17.8 + '@esbuild/win32-x64': 0.17.8 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + + /eventemitter-asyncresource@1.0.0: + resolution: {integrity: sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==} + dev: true + + /eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + dependencies: + websocket-driver: 0.7.4 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /follow-redirects@1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: true + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: true + + /fraction.js@4.2.0: + resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} + dev: true + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: true + + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /fs-minipass@3.0.1: + resolution: {integrity: sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 4.2.8 + dev: true + + /fs-monkey@1.0.3: + resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-intrinsic@1.2.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-symbols: 1.0.3 + dev: true + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + + /glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.6.4 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globby@13.1.4: + resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hdr-histogram-js@2.0.3: + resolution: {integrity: sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==} + dependencies: + '@assemblyscript/loader': 0.10.1 + base64-js: 1.5.1 + pako: 1.0.11 + dev: true + + /hdr-histogram-percentiles-obj@3.0.0: + resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==} + dev: true + + /hosted-git-info@6.1.1: + resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + lru-cache: 7.18.3 + dev: true + + /hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + dev: true + + /html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + + /http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + dev: true + + /http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: true + + /http-parser-js@0.5.8: + resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + dev: true + + /http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /http-proxy-middleware@2.0.6(@types/express@4.17.17): + resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + dependencies: + '@types/express': 4.17.17 + '@types/http-proxy': 1.17.10 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.5 + transitivePeerDependencies: + - debug + dev: true + + /http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.2 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + dependencies: + ms: 2.1.3 + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /icss-utils@5.1.0(postcss@8.4.21): + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.21 + dev: true + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + + /ignore-walk@6.0.2: + resolution: {integrity: sha512-ezmQ1Dg2b3jVZh2Dh+ar6Eu2MqNSTkyb32HU2MAQQQX9tKM3q/UQ/9lf03lQ5hW+fOeoMnwxwkleZ0xcNp0/qg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minimatch: 7.4.6 + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /immer@10.0.1: + resolution: {integrity: sha512-zg++jJLsKKTwXGeSYIw0HgChSYQGtu0UDTnbKx5aGLYgte4CwTmH9eJDYyQ6FheyUtBe+lQW9FrGxya1G+Dtmg==} + dev: false + + /immutable@4.3.0: + resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@3.0.1: + resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dev: true + + /injection-js@2.4.0: + resolution: {integrity: sha512-6jiJt0tCAo9zjHbcwLiPL+IuNe9SQ6a9g0PEzafThW3fOQi0mrmiJGBJvDD6tmhPh8cQHIQtCOrJuBfQME4kPA==} + dependencies: + tslib: 2.5.0 + dev: true + + /inquirer@8.2.4: + resolution: {integrity: sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /ip@2.0.0: + resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: true + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: true + + /ipaddr.js@2.0.1: + resolution: {integrity: sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==} + engines: {node: '>= 10'} + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-core-module@2.12.0: + resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + dev: true + + /is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + dev: true + + /is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + dependencies: + isobject: 3.0.1 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + dev: true + + /istanbul-lib-coverage@3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.21.4 + '@babel/parser': 7.21.4 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.0: + resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} + engines: {node: '>=8'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 3.1.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.5: + resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.0 + dev: true + + /jasmine-core@4.5.0: + resolution: {integrity: sha512-9PMzyvhtocxb3aXJVOPqBDswdgyAeSB81QnLop4npOpbqnheaTEwPc9ZloQeVswugPManznQBjD8kWDTjlnHuw==} + dev: true + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 18.15.11 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jiti@1.18.2: + resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==} + hasBin: true + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-parse-even-better-errors@3.0.0: + resolution: {integrity: sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /karma-chrome-launcher@3.1.1: + resolution: {integrity: sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==} + dependencies: + which: 1.3.1 + dev: true + + /karma-coverage@2.2.0: + resolution: {integrity: sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==} + engines: {node: '>=10.0.0'} + dependencies: + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /karma-jasmine-html-reporter@2.0.0(jasmine-core@4.5.0)(karma-jasmine@5.1.0)(karma@6.4.1): + resolution: {integrity: sha512-SB8HNNiazAHXM1vGEzf8/tSyEhkfxuDdhYdPBX2Mwgzt0OuF2gicApQ+uvXLID/gXyJQgvrM9+1/2SxZFUUDIA==} + peerDependencies: + jasmine-core: ^4.0.0 + karma: ^6.0.0 + karma-jasmine: ^5.0.0 + dependencies: + jasmine-core: 4.5.0 + karma: 6.4.1 + karma-jasmine: 5.1.0(karma@6.4.1) + dev: true + + /karma-jasmine@5.1.0(karma@6.4.1): + resolution: {integrity: sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==} + engines: {node: '>=12'} + peerDependencies: + karma: ^6.0.0 + dependencies: + jasmine-core: 4.5.0 + karma: 6.4.1 + dev: true + + /karma-source-map-support@1.4.0: + resolution: {integrity: sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==} + dependencies: + source-map-support: 0.5.21 + dev: true + + /karma@6.4.1: + resolution: {integrity: sha512-Cj57NKOskK7wtFWSlMvZf459iX+kpYIPXmkNUzP2WAFcA7nhr/ALn5R7sw3w+1udFDcpMx/tuB8d5amgm3ijaA==} + engines: {node: '>= 10'} + hasBin: true + dependencies: + '@colors/colors': 1.5.0 + body-parser: 1.20.2 + braces: 3.0.2 + chokidar: 3.5.3 + connect: 3.7.0 + di: 0.0.1 + dom-serialize: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + http-proxy: 1.18.1 + isbinaryfile: 4.0.10 + lodash: 4.17.21 + log4js: 6.9.1 + mime: 2.6.0 + minimatch: 3.1.2 + mkdirp: 0.5.6 + qjobs: 1.2.0 + range-parser: 1.2.1 + rimraf: 3.0.2 + socket.io: 4.6.1 + source-map: 0.6.1 + tmp: 0.2.1 + ua-parser-js: 0.7.35 + yargs: 16.2.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + dev: true + + /less-loader@11.1.0(less@4.1.3)(webpack@5.76.1): + resolution: {integrity: sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==} + engines: {node: '>= 14.15.0'} + peerDependencies: + less: ^3.5.0 || ^4.0.0 + webpack: ^5.0.0 + dependencies: + klona: 2.0.6 + less: 4.1.3 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /less@4.1.3: + resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.5.0 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /license-webpack-plugin@4.0.2(webpack@5.76.1): + resolution: {integrity: sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==} + peerDependencies: + webpack: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-sources: + optional: true + dependencies: + webpack: 5.76.1(esbuild@0.17.8) + webpack-sources: 3.2.3 + dev: true + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + dev: true + + /loader-utils@3.2.1: + resolution: {integrity: sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==} + engines: {node: '>= 12.13.0'} + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log4js@6.9.1: + resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} + engines: {node: '>=8.0'} + dependencies: + date-format: 4.0.14 + debug: 4.3.4 + flatted: 3.2.7 + rfdc: 1.3.0 + streamroller: 3.1.5 + transitivePeerDependencies: + - supports-color + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: true + + /lru-cache@9.0.1: + resolution: {integrity: sha512-C8QsKIN1UIXeOs3iWmiZ1lQY+EnKDojWd37fXy1aSbJvH4iSma1uy2OWuoB3m4SYRli5+CUjDv3Dij5DVoetmg==} + engines: {node: 14 || >=16.14} + dev: true + + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magic-string@0.29.0: + resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + pify: 4.0.1 + semver: 5.7.1 + dev: true + optional: true + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.0 + dev: true + + /make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + agentkeepalive: 4.3.0 + cacache: 16.1.3 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /make-fetch-happen@11.0.3: + resolution: {integrity: sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + agentkeepalive: 4.3.0 + cacache: 17.0.5 + http-cache-semantics: 4.1.1 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 4.2.8 + minipass-fetch: 3.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0 + ssri: 10.0.3 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /media-typer@0.3.0: + resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} + engines: {node: '>= 0.6'} + dev: true + + /memfs@3.5.0: + resolution: {integrity: sha512-yK6o8xVJlQerz57kvPROwTMgx5WtGwC2ZxDtOUsnGl49rHjYkfQoPNZPCKH73VdLE1BwBu/+Fx/NL8NYMUw2aA==} + engines: {node: '>= 4.0.0'} + dependencies: + fs-monkey: 1.0.3 + dev: true + + /merge-descriptors@1.0.1: + resolution: {integrity: sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=} + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /mime@2.5.2: + resolution: {integrity: sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==} + engines: {node: '>=4.0.0'} + hasBin: true + dev: true + + /mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mini-css-extract-plugin@2.7.2(webpack@5.76.1): + resolution: {integrity: sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + schema-utils: 4.0.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: true + + /minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: true + + /minipass-fetch@3.0.1: + resolution: {integrity: sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 4.2.8 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: true + + /minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-json-stream@1.0.1: + resolution: {integrity: sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==} + dependencies: + jsonparse: 1.3.1 + minipass: 3.3.6 + dev: true + + /minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + dependencies: + minipass: 3.3.6 + dev: true + + /minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + dependencies: + yallist: 4.0.0 + dev: true + + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + dev: true + + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + + /minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mockjs@1.1.0: + resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==} + hasBin: true + dependencies: + commander: 10.0.1 + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + dependencies: + dns-packet: 5.5.0 + thunky: 1.1.0 + dev: true + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /needle@3.2.0: + resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + requiresBuild: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.6.3 + sax: 1.2.4 + transitivePeerDependencies: + - supports-color + dev: true + optional: true + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /ng-packagr@15.2.2(@angular/compiler-cli@15.2.7)(tailwindcss@3.3.1)(tslib@2.5.0)(typescript@4.9.5): + resolution: {integrity: sha512-+042GBD35ztxbHywGJloAiDM/s3Ja3TZtQh361TWqd/xza3K5DMUu6VRGLTgMwG7CW1YsqYHWgMZslP1c+ng7A==} + engines: {node: ^14.20.0 || ^16.13.0 || >=18.10.0} + hasBin: true + peerDependencies: + '@angular/compiler-cli': ^15.0.0 || ^15.2.0-next.0 + tailwindcss: ^2.0.0 || ^3.0.0 + tslib: ^2.3.0 + typescript: '>=4.8.2 <5.0' + peerDependenciesMeta: + tailwindcss: + optional: true + dependencies: + '@angular/compiler-cli': 15.2.7(@angular/compiler@15.2.7)(typescript@4.9.5) + '@rollup/plugin-json': 6.0.0(rollup@3.20.6) + '@rollup/plugin-node-resolve': 15.0.2(rollup@3.20.6) + ajv: 8.12.0 + ansi-colors: 4.1.3 + autoprefixer: 10.4.14(postcss@8.4.21) + browserslist: 4.21.5 + cacache: 17.0.5 + chokidar: 3.5.3 + commander: 10.0.1 + convert-source-map: 2.0.0 + dependency-graph: 0.11.0 + esbuild-wasm: 0.17.8 + find-cache-dir: 3.3.2 + glob: 8.1.0 + injection-js: 2.4.0 + jsonc-parser: 3.2.0 + less: 4.1.3 + ora: 5.4.1 + piscina: 3.2.0 + postcss: 8.4.21 + postcss-url: 10.1.3(postcss@8.4.21) + rollup: 3.20.6 + rxjs: 7.8.0 + sass: 1.58.1 + tailwindcss: 3.3.1(postcss@8.4.21) + tslib: 2.5.0 + typescript: 4.9.5 + optionalDependencies: + esbuild: 0.17.8 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /ng-zorro-antd@15.1.0(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/forms@15.2.7)(@angular/platform-browser@15.2.7)(@angular/router@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-HkZpaG4+fBGP8jhJ/rzyK9fm1G8pPzT0zCQ+3sae3Mwvop5diRUS8lSX/1SucEqjsYAGv+1S5ipl0HwKTLQlQw==} + peerDependencies: + '@angular/animations': ^15.0.1 + '@angular/common': ^15.0.1 + '@angular/core': ^15.0.1 + '@angular/forms': ^15.0.1 + '@angular/platform-browser': ^15.0.1 + '@angular/router': ^15.0.1 + dependencies: + '@angular/animations': 15.2.7(@angular/core@15.2.7) + '@angular/cdk': 15.2.6(@angular/common@15.2.7)(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/common': 15.2.7(@angular/core@15.2.7)(rxjs@7.8.0) + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/forms': 15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + '@angular/platform-browser': 15.2.7(@angular/animations@15.2.7)(@angular/common@15.2.7)(@angular/core@15.2.7) + '@angular/router': 15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + '@ant-design/icons-angular': 15.0.0(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + date-fns: 2.30.0 + tslib: 2.5.0 + transitivePeerDependencies: + - rxjs + dev: false + + /ngx-permissions@15.0.1(@angular/core@15.2.7)(@angular/router@15.2.7)(rxjs@7.8.0): + resolution: {integrity: sha512-GjPF54B0DYtzqVb95YUh1XZivU4ilpCnx04gtADnIz4grihb/AtVwGwjgeeC1N/zrwUaZWLxTkIm5emN11JlDw==} + peerDependencies: + '@angular/core': '>=13 || >18' + '@angular/router': '>=13 || >18' + rxjs: '>=7 || >11' + dependencies: + '@angular/core': 15.2.7(rxjs@7.8.0)(zone.js@0.12.0) + '@angular/router': 15.2.7(@angular/common@15.2.7)(@angular/core@15.2.7)(@angular/platform-browser@15.2.7)(rxjs@7.8.0) + rxjs: 7.8.0 + tslib: 2.5.0 + dev: false + + /nice-napi@1.0.2: + resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} + os: ['!win32'] + requiresBuild: true + dependencies: + node-addon-api: 3.2.1 + node-gyp-build: 4.6.0 + dev: true + optional: true + + /node-addon-api@3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + requiresBuild: true + dev: true + optional: true + + /node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + dev: true + + /node-gyp-build@4.6.0: + resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /node-gyp@9.3.1: + resolution: {integrity: sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true + dependencies: + env-paths: 2.2.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1 + nopt: 6.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.4.0 + tar: 6.1.13 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /node-releases@2.0.10: + resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} + dev: true + + /nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /normalize-package-data@5.0.0: + resolution: {integrity: sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + hosted-git-info: 6.1.1 + is-core-module: 2.12.0 + semver: 7.4.0 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + dev: true + + /npm-bundled@3.0.0: + resolution: {integrity: sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + npm-normalize-package-bin: 3.0.0 + dev: true + + /npm-install-checks@6.1.1: + resolution: {integrity: sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + semver: 7.4.0 + dev: true + + /npm-normalize-package-bin@3.0.0: + resolution: {integrity: sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /npm-package-arg@10.1.0: + resolution: {integrity: sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + hosted-git-info: 6.1.1 + proc-log: 3.0.0 + semver: 7.3.8 + validate-npm-package-name: 5.0.0 + dev: true + + /npm-packlist@7.0.4: + resolution: {integrity: sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + ignore-walk: 6.0.2 + dev: true + + /npm-pick-manifest@8.0.1: + resolution: {integrity: sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + npm-install-checks: 6.1.1 + npm-normalize-package-bin: 3.0.0 + npm-package-arg: 10.1.0 + semver: 7.3.8 + dev: true + + /npm-registry-fetch@14.0.3: + resolution: {integrity: sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + make-fetch-happen: 11.0.3 + minipass: 4.2.8 + minipass-fetch: 3.0.1 + minipass-json-stream: 1.0.1 + minizlib: 2.1.2 + npm-package-arg: 10.1.0 + proc-log: 3.0.0 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + dev: true + + /nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + dependencies: + boolbase: 1.0.0 + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: true + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + dev: true + + /on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /open@8.4.1: + resolution: {integrity: sha512-/4b7qZNhv6Uhd7jjnREh1NjnPxlTq+XNWPG88Ydkj5AILcA5m3ajvcg57pB24EQjKv0dK62XnDqk9c/hkIG5Kg==} + engines: {node: '>=12'} + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + dev: true + + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.8.0 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /pacote@15.1.0: + resolution: {integrity: sha512-FFcjtIl+BQNfeliSm7MZz5cpdohvUV1yjGnqgVM4UnVF7JslRY0ImXAygdaCDV0jjUADEWu4y5xsDV8brtrTLg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + '@npmcli/git': 4.0.4 + '@npmcli/installed-package-contents': 2.0.2 + '@npmcli/promise-spawn': 6.0.2 + '@npmcli/run-script': 6.0.0 + cacache: 17.0.5 + fs-minipass: 3.0.1 + minipass: 4.2.8 + npm-package-arg: 10.1.0 + npm-packlist: 7.0.4 + npm-pick-manifest: 8.0.1 + npm-registry-fetch: 14.0.3 + proc-log: 3.0.0 + promise-retry: 2.0.1 + read-package-json: 6.0.1 + read-package-json-fast: 3.0.2 + sigstore: 1.2.0 + ssri: 10.0.3 + tar: 6.1.13 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.21.4 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + dev: true + + /parse5-html-rewriting-stream@7.0.0: + resolution: {integrity: sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==} + dependencies: + entities: 4.4.0 + parse5: 7.1.2 + parse5-sax-parser: 7.0.0 + dev: true + + /parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: true + + /parse5-sax-parser@7.0.0: + resolution: {integrity: sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==} + dependencies: + parse5: 7.1.2 + dev: true + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.6.4: + resolution: {integrity: sha512-Qp/9IHkdNiXJ3/Kon++At2nVpnhRiPq/aSvQN+H3U1WZbvNRK0RIQK/o4HMqPoXjpuGJUEWpHSs6Mnjxqh3TQg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 9.0.1 + minipass: 5.0.0 + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: true + optional: true + + /pirates@4.0.5: + resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} + engines: {node: '>= 6'} + dev: true + + /piscina@3.2.0: + resolution: {integrity: sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==} + dependencies: + eventemitter-asyncresource: 1.0.0 + hdr-histogram-js: 2.0.3 + hdr-histogram-percentiles-obj: 3.0.0 + optionalDependencies: + nice-napi: 1.0.2 + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /postcss-import@14.1.0(postcss@8.4.21): + resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.21 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.1 + dev: true + + /postcss-js@4.0.1(postcss@8.4.21): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.21 + dev: true + + /postcss-load-config@3.1.4(postcss@8.4.21): + resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} + engines: {node: '>= 10'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.21 + yaml: 1.10.2 + dev: true + + /postcss-loader@7.0.2(postcss@8.4.21)(webpack@5.76.1): + resolution: {integrity: sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==} + engines: {node: '>= 14.15.0'} + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + dependencies: + cosmiconfig: 7.1.0 + klona: 2.0.6 + postcss: 8.4.21 + semver: 7.4.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /postcss-modules-extract-imports@3.0.0(postcss@8.4.21): + resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.21 + dev: true + + /postcss-modules-local-by-default@4.0.0(postcss@8.4.21): + resolution: {integrity: sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.21) + postcss: 8.4.21 + postcss-selector-parser: 6.0.11 + postcss-value-parser: 4.2.0 + dev: true + + /postcss-modules-scope@3.0.0(postcss@8.4.21): + resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + postcss: 8.4.21 + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-modules-values@4.0.0(postcss@8.4.21): + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + dependencies: + icss-utils: 5.1.0(postcss@8.4.21) + postcss: 8.4.21 + dev: true + + /postcss-nested@6.0.0(postcss@8.4.21): + resolution: {integrity: sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.21 + postcss-selector-parser: 6.0.11 + dev: true + + /postcss-selector-parser@6.0.11: + resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + + /postcss-url@10.1.3(postcss@8.4.21): + resolution: {integrity: sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==} + engines: {node: '>=10'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + make-dir: 3.1.0 + mime: 2.5.2 + minimatch: 3.0.8 + postcss: 8.4.21 + xxhashjs: 0.2.2 + dev: true + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + dev: true + + /postcss@8.4.21: + resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + dev: true + + /proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + dev: true + + /promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + dev: true + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: true + + /prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + dev: true + optional: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /qjobs@1.2.0: + resolution: {integrity: sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==} + engines: {node: '>=0.9'} + dev: true + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: true + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: true + + /read-package-json-fast@3.0.2: + resolution: {integrity: sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + json-parse-even-better-errors: 3.0.0 + npm-normalize-package-bin: 3.0.0 + dev: true + + /read-package-json@6.0.1: + resolution: {integrity: sha512-AaHqXxfAVa+fNL07x8iAghfKOds/XXsu7zoouIVsbm7PEbQ3nMWXlvjcbrNLjElnUHWQtAo4QEa0RXuvD4XlpA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + glob: 9.3.5 + json-parse-even-better-errors: 3.0.0 + normalize-package-data: 5.0.0 + npm-normalize-package-bin: 3.0.0 + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /reflect-metadata@0.1.13: + resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==} + dev: true + + /regenerate-unicode-properties@10.1.0: + resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + /regenerator-transform@0.15.1: + resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} + dependencies: + '@babel/runtime': 7.21.5 + dev: true + + /regex-parser@2.2.11: + resolution: {integrity: sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==} + dev: true + + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.0 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: true + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-url-loader@5.0.0: + resolution: {integrity: sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==} + engines: {node: '>=12'} + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 8.4.21 + source-map: 0.6.1 + dev: true + + /resolve@1.22.1: + resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + hasBin: true + dependencies: + is-core-module: 2.12.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + dev: true + + /retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@3.20.6: + resolution: {integrity: sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: true + + /rxjs@7.8.0: + resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} + dependencies: + tslib: 2.5.0 + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /sass-loader@13.2.0(sass@1.58.1)(webpack@5.76.1): + resolution: {integrity: sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==} + engines: {node: '>= 14.15.0'} + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + dependencies: + klona: 2.0.6 + neo-async: 2.6.2 + sass: 1.58.1 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /sass@1.58.1: + resolution: {integrity: sha512-bnINi6nPXbP1XNRaranMFEBZWUfdW/AF16Ql5+ypRxfTvCRTTKrLsMIakyDcayUt2t/RZotmL4kgJwNH5xO+bg==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.0 + source-map-js: 1.0.2 + dev: true + + /sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: true + optional: true + + /schema-utils@3.1.1: + resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.11 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: true + + /schema-utils@4.0.0: + resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==} + engines: {node: '>= 12.13.0'} + dependencies: + '@types/json-schema': 7.0.11 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + ajv-keywords: 5.1.0(ajv@8.12.0) + dev: true + + /select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + dev: true + + /selfsigned@2.1.1: + resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==} + engines: {node: '>=10'} + dependencies: + node-forge: 1.3.1 + dev: true + + /semver@5.7.1: + resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} + hasBin: true + dev: true + optional: true + + /semver@6.3.0: + resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} + hasBin: true + dev: true + + /semver@7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /semver@7.4.0: + resolution: {integrity: sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + dev: true + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: true + + /shallow-clone@3.0.1: + resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} + engines: {node: '>=8'} + dependencies: + kind-of: 6.0.3 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + object-inspect: 1.12.3 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /sigstore@1.2.0: + resolution: {integrity: sha512-Fr9+W1nkBSIZCkJQR7jDn/zI0UXNsVpp+7mDQkCnZOIxG9p6yNXBx9xntHsfUyYHE55XDkkVV3+rYbrkzAeesA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + '@sigstore/protobuf-specs': 0.1.0 + make-fetch-happen: 11.0.3 + tuf-js: 1.1.3 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: true + + /socket.io-adapter@2.5.2: + resolution: {integrity: sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==} + dependencies: + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /socket.io-parser@4.2.2: + resolution: {integrity: sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /socket.io@4.6.1: + resolution: {integrity: sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==} + engines: {node: '>=10.0.0'} + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + debug: 4.3.4 + engine.io: 6.4.1 + socket.io-adapter: 2.5.2 + socket.io-parser: 4.2.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + dev: true + + /socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: true + + /socks@2.7.1: + resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 2.0.0 + smart-buffer: 4.2.0 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-loader@4.0.1(webpack@5.76.1): + resolution: {integrity: sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.72.1 + dependencies: + abab: 2.0.6 + iconv-lite: 0.6.3 + source-map-js: 1.0.2 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.13 + dev: true + + /spdx-license-ids@3.0.13: + resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==} + dev: true + + /spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + dependencies: + debug: 4.3.4 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + dev: true + + /spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + dependencies: + debug: 4.3.4 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /ssri@10.0.3: + resolution: {integrity: sha512-lJtX/BFPI/VEtxZmLfeh7pzisIs6micwZ3eruD3+ds9aPsXKlYpwDS2Q7omD6WC42WO9+bnUSzlMmfv8uK8meg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + minipass: 4.2.8 + dev: true + + /ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + minipass: 3.3.6 + dev: true + + /statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + dev: true + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: true + + /streamroller@3.1.5: + resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} + engines: {node: '>=8.0'} + dependencies: + date-format: 4.0.14 + debug: 4.3.4 + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /sucrase@3.32.0: + resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + commander: 4.1.1 + glob: 7.1.6 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.5 + ts-interface-checker: 0.1.13 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + dev: true + + /tailwindcss@3.3.1(postcss@8.4.21): + resolution: {integrity: sha512-Vkiouc41d4CEq0ujXl6oiGFQ7bA3WEhUZdTgXAhtKxSy49OmKs8rEfQmupsfF0IGW8fv2iQkp1EVUuapCFrZ9g==} + engines: {node: '>=12.13.0'} + hasBin: true + peerDependencies: + postcss: ^8.0.9 + dependencies: + arg: 5.0.2 + chokidar: 3.5.3 + color-name: 1.1.4 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.2.12 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.18.2 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.21 + postcss-import: 14.1.0(postcss@8.4.21) + postcss-js: 4.0.1(postcss@8.4.21) + postcss-load-config: 3.1.4(postcss@8.4.21) + postcss-nested: 6.0.0(postcss@8.4.21) + postcss-selector-parser: 6.0.11 + postcss-value-parser: 4.2.0 + quick-lru: 5.1.1 + resolve: 1.22.1 + sucrase: 3.32.0 + transitivePeerDependencies: + - ts-node + dev: true + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /tar@6.1.13: + resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==} + engines: {node: '>=10'} + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 4.2.8 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + dev: true + + /terser-webpack-plugin@5.3.7(esbuild@0.17.8)(webpack@5.76.1): + resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + esbuild: 0.17.8 + jest-worker: 27.5.1 + schema-utils: 3.1.1 + serialize-javascript: 6.0.1 + terser: 5.16.9 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /terser@5.16.3: + resolution: {integrity: sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.3 + acorn: 8.8.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /terser@5.16.9: + resolution: {integrity: sha512-HPa/FdTB9XGI2H1/keLFZHxl6WNvAI4YalHGtDQTlMnJcoqSab1UwL4l1hGEhs6/GmLHBZIg/YgB++jcbzoOEg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.3 + acorn: 8.8.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /tmp@0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + dependencies: + rimraf: 3.0.2 + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: true + + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.3.0: + resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==} + dev: false + + /tslib@2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + + /tuf-js@1.1.3: + resolution: {integrity: sha512-jGYi5nG/kqgfTFQSdoN6PW9eIn+XRZqdXku+fSwNk6UpWIsWaV7pzAqPgFr85edOPhoyJDyBqCS+DCnHroMvrw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + '@tufjs/models': 1.0.2 + make-fetch-happen: 11.0.3 + transitivePeerDependencies: + - bluebird + - supports-color + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: true + + /typed-assert@1.0.9: + resolution: {integrity: sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==} + dev: true + + /typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /ua-parser-js@0.7.35: + resolution: {integrity: sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==} + dev: true + + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + unique-slug: 3.0.0 + dev: true + + /unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + unique-slug: 4.0.0 + dev: true + + /unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + dev: true + + /unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + imurmurhash: 0.1.4 + dev: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: true + + /update-browserslist-db@1.0.10(browserslist@4.21.5): + resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.5 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /utils-merge@1.0.1: + resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=} + engines: {node: '>= 0.4.0'} + dev: true + + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /validate-npm-package-name@5.0.0: + resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dependencies: + builtins: 5.0.1 + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /void-elements@2.0.1: + resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} + engines: {node: '>=0.10.0'} + dev: true + + /watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: true + + /wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + dependencies: + minimalistic-assert: 1.0.1 + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /webpack-dev-middleware@5.3.3(webpack@5.76.1): + resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + dependencies: + colorette: 2.0.19 + memfs: 3.5.0 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.0.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /webpack-dev-middleware@6.0.1(webpack@5.76.1): + resolution: {integrity: sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==} + engines: {node: '>= 14.15.0'} + peerDependencies: + webpack: ^5.0.0 + dependencies: + colorette: 2.0.19 + memfs: 3.5.0 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.0.0 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /webpack-dev-server@4.11.1(webpack@5.76.1): + resolution: {integrity: sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==} + engines: {node: '>= 12.13.0'} + hasBin: true + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/bonjour': 3.5.10 + '@types/connect-history-api-fallback': 1.3.5 + '@types/express': 4.17.17 + '@types/serve-index': 1.9.1 + '@types/serve-static': 1.15.1 + '@types/sockjs': 0.3.33 + '@types/ws': 8.5.4 + ansi-html-community: 0.0.8 + bonjour-service: 1.1.1 + chokidar: 3.5.3 + colorette: 2.0.19 + compression: 1.7.4 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.18.2 + graceful-fs: 4.2.11 + html-entities: 2.3.3 + http-proxy-middleware: 2.0.6(@types/express@4.17.17) + ipaddr.js: 2.0.1 + open: 8.4.1 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.0.0 + selfsigned: 2.1.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack: 5.76.1(esbuild@0.17.8) + webpack-dev-middleware: 5.3.3(webpack@5.76.1) + ws: 8.11.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + dev: true + + /webpack-merge@5.8.0: + resolution: {integrity: sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==} + engines: {node: '>=10.0.0'} + dependencies: + clone-deep: 4.0.1 + wildcard: 2.0.0 + dev: true + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack-subresource-integrity@5.1.0(webpack@5.76.1): + resolution: {integrity: sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==} + engines: {node: '>= 12'} + peerDependencies: + html-webpack-plugin: '>= 5.0.0-beta.1 < 6' + webpack: ^5.12.0 + peerDependenciesMeta: + html-webpack-plugin: + optional: true + dependencies: + typed-assert: 1.0.9 + webpack: 5.76.1(esbuild@0.17.8) + dev: true + + /webpack@5.76.1(esbuild@0.17.8): + resolution: {integrity: sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.4 + '@types/estree': 0.0.51 + '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/wasm-edit': 1.11.1 + '@webassemblyjs/wasm-parser': 1.11.1 + acorn: 8.8.2 + acorn-import-assertions: 1.8.0(acorn@8.8.2) + browserslist: 4.21.5 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.12.0 + es-module-lexer: 0.9.3 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.1.1 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.7(esbuild@0.17.8)(webpack@5.76.1) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + dependencies: + http-parser-js: 0.5.8 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + dev: true + + /websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@3.0.0: + resolution: {integrity: sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + dependencies: + string-width: 4.2.3 + dev: true + + /wildcard@2.0.0: + resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /ws@8.11.0: + resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + + /xxhashjs@0.2.2: + resolution: {integrity: sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==} + dependencies: + cuint: 0.2.2 + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: true + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: true + + /yargs@17.6.2: + resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yargs@17.7.1: + resolution: {integrity: sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /zone.js@0.12.0: + resolution: {integrity: sha512-XtC+I5dXU14HrzidAKBNMqneIVUykLEAA1x+v4KVrd6AUPWlwYORF8KgsVqvgdHiKZ4BkxxjvYi/ksEixTPR0Q==} + dependencies: + tslib: 2.5.0 + + /zrender@5.4.3: + resolution: {integrity: sha512-DRUM4ZLnoaT0PBVvGBDO9oWIDBKFdAVieNWxWwK0niYzJCMwGchRk21/hsE+RKkIveH3XHCyvXcJDkgLVvfizQ==} + dependencies: + tslib: 2.3.0 + dev: false diff --git a/projects/cdk/README.md b/projects/cdk/README.md new file mode 100644 index 0000000..1a23b4e --- /dev/null +++ b/projects/cdk/README.md @@ -0,0 +1,24 @@ +# Cdk + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 15.2.0. + +## Code scaffolding + +Run `ng generate component component-name --project cdk` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project cdk`. +> Note: Don't forget to add `--project cdk` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build cdk` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build cdk`, go to the dist folder `cd dist/cdk` and run `npm publish`. + +## Running unit tests + +Run `ng test cdk` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/projects/cdk/ng-package.json b/projects/cdk/ng-package.json new file mode 100644 index 0000000..c3205e0 --- /dev/null +++ b/projects/cdk/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/cdk", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/projects/cdk/package.json b/projects/cdk/package.json new file mode 100644 index 0000000..2052836 --- /dev/null +++ b/projects/cdk/package.json @@ -0,0 +1,12 @@ +{ + "name": "cdk", + "version": "0.0.1", + "peerDependencies": { + "@angular/common": "^15.2.0", + "@angular/core": "^15.2.0" + }, + "dependencies": { + "tslib": "^2.3.0" + }, + "sideEffects": false +} diff --git a/projects/cdk/src/dec-module/base-href.ts b/projects/cdk/src/dec-module/base-href.ts new file mode 100644 index 0000000..01c083d --- /dev/null +++ b/projects/cdk/src/dec-module/base-href.ts @@ -0,0 +1,8 @@ +import { PlatformLocation } from "@angular/common"; +import { InjectionToken } from "@angular/core"; + +export const PUBLIC_PATH = new InjectionToken("pablic-path"); + +export function getBaseHref(platformLocation: PlatformLocation): string { + return platformLocation.getBaseHrefFromDOM(); +} diff --git a/projects/cdk/src/dec-module/dec.module.ts b/projects/cdk/src/dec-module/dec.module.ts new file mode 100644 index 0000000..249b270 --- /dev/null +++ b/projects/cdk/src/dec-module/dec.module.ts @@ -0,0 +1,41 @@ +import { InjectionToken, ModuleWithProviders, NgModule } from "@angular/core"; +import { CommonModule, PlatformLocation } from "@angular/common"; +import { NzMessageModule } from "ng-zorro-antd/message"; +import { HttpResponse, HTTP_INTERCEPTORS } from "@angular/common/http"; +import { HTTPInterceptor } from "./http.interceptor"; +import { DecSafeAny } from "@cdk/types"; +import { getBaseHref, PUBLIC_PATH } from "./base-href"; + +export const decConfigToken = new InjectionToken("decConfig"); + +export type DecConfig = { + environment: DecSafeAny; + isClient?: boolean; + loginUrl?: string; + localStroageKey: string; + triggerError?: (res: HttpResponse) => void; +}; + +@NgModule({ + declarations: [], + imports: [NzMessageModule], + providers: [{ provide: HTTP_INTERCEPTORS, useClass: HTTPInterceptor, multi: true }], +}) +export class DecModule { + public static forRoot(decConfig: DecConfig): ModuleWithProviders { + return { + ngModule: DecModule, + providers: [ + { + provide: decConfigToken, + useValue: decConfig, + }, + { + provide: PUBLIC_PATH, + useFactory: getBaseHref, + deps: [PlatformLocation], + }, + ], + }; + } +} diff --git a/projects/cdk/src/dec-module/http.interceptor.ts b/projects/cdk/src/dec-module/http.interceptor.ts new file mode 100644 index 0000000..a686af8 --- /dev/null +++ b/projects/cdk/src/dec-module/http.interceptor.ts @@ -0,0 +1,100 @@ +import { Inject, Injectable } from "@angular/core"; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor, + HttpErrorResponse, + HttpResponse, +} from "@angular/common/http"; +import { catchError, Observable, switchMap, tap, throwError, timer } from "rxjs"; +import { Router } from "@angular/router"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { decConfigToken, DecConfig } from "./dec.module"; +import { ResponseType } from "@cdk/types"; + +@Injectable({ providedIn: "root" }) +export class HTTPInterceptor implements HttpInterceptor { + constructor( + @Inject(decConfigToken) private decConfig: Required, + private router: Router, + private msg: NzMessageService + ) {} + + private msgFlag = false; + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + const { localStroageKey } = this.decConfig; + + const token = localStorage.getItem(localStroageKey); + + if (token) { + req = req.clone({ + // headers: req.headers.set('Authorization', `Bearer ${token}`), + headers: req.headers.set("Authorization", token), + }); + } + + return this.handleResult(next, req); + } + + private handleResult(next: HttpHandler, authReq: HttpRequest): Observable> { + return next.handle(authReq).pipe( + tap((res) => { + if (res instanceof HttpResponse) { + const Authorization = res.headers.get("Authorization"); + if (Authorization) { + localStorage.setItem(this.decConfig.localStroageKey, Authorization); + } + + if (this.decConfig.triggerError) { + this.decConfig.triggerError(res); + } + + if (res.body?.success === false && res.body.desc) { + throw new HttpErrorResponse({ error: res.body }); + } + } + }), + + catchError((err: HttpErrorResponse) => { + const throwErr = throwError(() => err); + if (this.msgFlag) { + return throwErr; + } + const { isClient } = this.decConfig; + setTimeout(() => { + this.msgFlag = false; + }, 1500); + const error: ResponseType = err.error; + this.msgFlag = true; + + if (error.success === false) { + if (isClient) { + switch (error.code) { + case 401: + break; + + default: + this.msg.error(error.desc); + break; + } + } else { + this.msg.error(error.desc); + switch (error.code) { + case 401: + this.router.navigate([this.decConfig.loginUrl]); + break; + default: + break; + } + } + } else { + this.msg.error("服务器出错了!"); + } + + return throwErr; + }) + ); + } +} diff --git a/projects/cdk/src/form-error-tips/form-error-tips.component.html b/projects/cdk/src/form-error-tips/form-error-tips.component.html new file mode 100644 index 0000000..914ea00 --- /dev/null +++ b/projects/cdk/src/form-error-tips/form-error-tips.component.html @@ -0,0 +1,36 @@ + + + {{item.value.message}} + + + +
+ 不能为空 +
+
+ 首末字符不能为空格 +
+
+ 请输入正确的邮箱地址 +
+
+ 最多输入{{item.value.requiredLength}}位字符 +
+
+ 最少输入{{item.value.requiredLength}}位字符 +
+
+ 不能小于{{item.value.min}} +
+
+ 不能大于{{item.value.max}} +
+
+ 请输入正确的内容 +
+
+ 字段验证失败 +
+
+
+
\ No newline at end of file diff --git a/projects/cdk/src/form-error-tips/form-error-tips.component.less b/projects/cdk/src/form-error-tips/form-error-tips.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/cdk/src/form-error-tips/form-error-tips.component.ts b/projects/cdk/src/form-error-tips/form-error-tips.component.ts new file mode 100644 index 0000000..0b20dbc --- /dev/null +++ b/projects/cdk/src/form-error-tips/form-error-tips.component.ts @@ -0,0 +1,28 @@ +import { CommonModule } from "@angular/common"; +import { Component, Input, OnChanges, OnInit, SimpleChanges } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; + +@Component({ + standalone: true, + selector: "dec-form-error-tips", + templateUrl: "./form-error-tips.component.html", + styleUrls: ["./form-error-tips.component.less"], + imports: [CommonModule], +}) +export class FormErrorTipsComponent implements OnInit, OnChanges { + constructor() {} + + @Input() control!: FormControl; + + ngOnChanges(changes: SimpleChanges): void { + // console.log("FormErrorTipsComponent changes", changes["control"]?.currentValue); + // const formControl: FormControl = changes["control"].currentValue; + // const root = formControl.root as FormGroup; + // console.log("formControl.root", formControl); + // if (formControl && !this.label) { + // if(initLabelFormControlNameMaps.has(formControl)) + // } + } + + ngOnInit(): void {} +} diff --git a/projects/cdk/src/input-space-error/input-space-error.directive.ts b/projects/cdk/src/input-space-error/input-space-error.directive.ts new file mode 100644 index 0000000..87bfc07 --- /dev/null +++ b/projects/cdk/src/input-space-error/input-space-error.directive.ts @@ -0,0 +1,24 @@ +import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, ValidatorFn } from "@angular/forms"; +import { Directive } from "@angular/core"; + +const VALIDATE_WHITE_SPACE_REGEX = /^[\s]|[\s]$/; + +export function stringWhiteSpaceForbiddenValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } | null => { + const isInvalid = VALIDATE_WHITE_SPACE_REGEX.test(control.value); + return isInvalid ? { inputTrim: { value: control.value } } : null; + }; +} + +@Directive({ + standalone: true, + selector: "[nz-input]", + providers: [{ provide: NG_VALIDATORS, useExisting: InputSpaceErrorDirective, multi: true }], +}) +export class InputSpaceErrorDirective implements Validator { + constructor() {} + + validate(control: AbstractControl): ValidationErrors | null { + return stringWhiteSpaceForbiddenValidator()(control); + } +} diff --git a/projects/cdk/src/public-api.ts b/projects/cdk/src/public-api.ts new file mode 100644 index 0000000..9fb6967 --- /dev/null +++ b/projects/cdk/src/public-api.ts @@ -0,0 +1,14 @@ +/* + * Public API Surface of cdk + */ + +export * from "./types"; +export * from "./utils"; +export * from "./validators"; +export * from "./dec-module/dec.module"; +export * from "./form-error-tips/form-error-tips.component"; +export * from "./input-space-error/input-space-error.directive"; +export * from "./public-path/public-path.pipe"; +export * from "./quick-date-range/quick-date-range.component"; +export * from "./table-list"; +export * from "./storage"; diff --git a/projects/cdk/src/public-path/public-path.pipe.ts b/projects/cdk/src/public-path/public-path.pipe.ts new file mode 100644 index 0000000..50f568e --- /dev/null +++ b/projects/cdk/src/public-path/public-path.pipe.ts @@ -0,0 +1,16 @@ +import { Inject, Pipe, PipeTransform } from "@angular/core"; +import { PUBLIC_PATH } from "@cdk/dec-module/base-href"; + +@Pipe({ + name: "publicPath", + standalone: true, +}) +export class PublicPathPipe implements PipeTransform { + constructor(@Inject(PUBLIC_PATH) private publicPath: string) {} + transform(value: string): string { + if (value.startsWith("/")) { + value = value.replace("/", ""); + } + return this.publicPath + value; + } +} diff --git a/projects/cdk/src/quick-date-range/quick-date-range.component.css b/projects/cdk/src/quick-date-range/quick-date-range.component.css new file mode 100644 index 0000000..e69de29 diff --git a/projects/cdk/src/quick-date-range/quick-date-range.component.html b/projects/cdk/src/quick-date-range/quick-date-range.component.html new file mode 100644 index 0000000..2e05348 --- /dev/null +++ b/projects/cdk/src/quick-date-range/quick-date-range.component.html @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/projects/cdk/src/quick-date-range/quick-date-range.component.ts b/projects/cdk/src/quick-date-range/quick-date-range.component.ts new file mode 100644 index 0000000..cac0b56 --- /dev/null +++ b/projects/cdk/src/quick-date-range/quick-date-range.component.ts @@ -0,0 +1,94 @@ +import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from "@angular/forms"; +import { NzRadioModule } from "ng-zorro-antd/radio"; +import { NzSpaceModule } from "ng-zorro-antd/space"; +import { CommonModule } from "@angular/common"; +import { Component, OnInit } from "@angular/core"; +import { NzDatePickerModule } from "ng-zorro-antd/date-picker"; +import { subDays, format } from "date-fns"; + +@Component({ + standalone: true, + selector: "dec-quick-date-range", + templateUrl: "./quick-date-range.component.html", + styleUrls: ["./quick-date-range.component.css"], + imports: [CommonModule, NzDatePickerModule, NzSpaceModule, NzRadioModule, FormsModule], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: QuickDateRangeComponent, + }, + ], +}) +export class QuickDateRangeComponent implements OnInit, ControlValueAccessor { + constructor() {} + + dateFilterOptions = [ + { + label: "今日", + value: 0, + }, + { + label: "近7日", + value: 7, + }, + { + label: "近30日", + value: 30, + }, + { + label: "近90日", + value: 90, + }, + ]; + + quick: number | null = null; + + range: Date[] = []; + + onQuickChange(v: number) { + this.quick = v; + this.range = this.getDateRange(v).map((d) => new Date(d)); + const val = this.range.map((date) => format(date, "yyyy-MM-dd")); + // console.log("val", val); + this.onChange(val); + } + + getDateRange(n: number): [string, string] { + const today = new Date(); + const previousDay = subDays(today, n); + const formattedToday = format(today, "yyyy-MM-dd"); + const formattedPreviousDay = format(previousDay, "yyyy-MM-dd"); + return [formattedPreviousDay, formattedToday]; + } + + ngOnInit(): void {} + + onRangeChange(v: Date[]) { + this.quick = null; + this.range = v; + const val = v.map((date) => format(date, "yyyy-MM-dd")); + this.onChange(val); + } + + onChange(v: any) {} + + ontouch(v: any) {} + + writeValue(v: string[]): void { + // console.log("v", v); + if (v && Array.isArray(v)) { + this.range = v?.map((d) => new Date(d)); + } else { + this.onQuickChange(90); + } + } + + registerOnChange(fn: any): void { + this.onChange = fn; + } + + registerOnTouched(fn: any): void { + this.ontouch = fn; + } +} diff --git a/projects/cdk/src/storage/cache.service.ts b/projects/cdk/src/storage/cache.service.ts new file mode 100644 index 0000000..dfa3dd5 --- /dev/null +++ b/projects/cdk/src/storage/cache.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from "@angular/core"; +import { NavigationEnd, Router } from "@angular/router"; +import { filter } from "rxjs/operators"; +import { DecSafeAny } from "../types"; +import { StorageService } from "./storage.service"; + +type IcacheUrlMap = Record>; + +export class CacheItem { + constructor(private storage: StorageService, private cacheKey: string) {} + + getItem(): T { + return this.storage.get(this.cacheKey, { stroage: "session" }); + } + + setItem(query: T) { + this.storage.set(this.cacheKey, query, { stroage: "session" }); + } + + remove() { + this.storage.set(this.cacheKey, null, { stroage: "session" }); + } +} + +@Injectable() +export class CacheService { + constructor(private router: Router, private storage: StorageService) {} + + /** + * cacheKey 与 url 之间的映射 + */ + private get cacheUrlMap(): IcacheUrlMap { + return this.storage.get("cacheUrlMap") ?? {}; + } + + private set cacheUrlMap(o: IcacheUrlMap) { + this.storage.set("cacheUrlMap", o); + } + + listen() { + this.router.events.pipe(filter((f): f is NavigationEnd => f instanceof NavigationEnd)).subscribe((r) => { + const currentUrl = r.url; + for (const [api, urls] of Object.entries(this.cacheUrlMap)) { + if (!urls.some((s) => currentUrl.startsWith(s))) { + this.storage.remove(api, { stroage: "session" }); + } + } + }); + } + + /** + * + * @param cacheKey 缓存的key + * @param cacheInUrl 当前 cacheKey 该url中缓存,若页面跳转到非url中时删除 缓存的数据 + * @return 返回一个可以操作该缓存的对象 getItem & setItem + */ + initCache(cacheKey: string, cacheInUrl?: string): CacheItem; + initCache(cacheKey: string, cacheInUrl?: Array): CacheItem; + initCache(cacheKey: string, cacheInUrl?: string | Array): CacheItem { + if (!cacheInUrl) { + cacheInUrl = [this.router.url]; + } + if (!this.cacheUrlMap[cacheKey]) { + cacheInUrl = (Array.isArray(cacheInUrl) ? cacheInUrl : [cacheInUrl]) as Array; + const storageData = this.cacheUrlMap; + storageData[cacheKey] = cacheInUrl; + this.cacheUrlMap = storageData; + } + return new CacheItem(this.storage, cacheKey); + } +} diff --git a/projects/cdk/src/storage/index.ts b/projects/cdk/src/storage/index.ts new file mode 100644 index 0000000..9cbe252 --- /dev/null +++ b/projects/cdk/src/storage/index.ts @@ -0,0 +1,3 @@ +export * from "./storage.module"; +export * from "./storage.service"; +export * from "./cache.service"; diff --git a/projects/cdk/src/storage/storage.module.ts b/projects/cdk/src/storage/storage.module.ts new file mode 100644 index 0000000..0e2155f --- /dev/null +++ b/projects/cdk/src/storage/storage.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from "@angular/core"; +import { CacheService } from "./cache.service"; +import { StorageService } from "./storage.service"; + +@NgModule({ + declarations: [], + imports: [], + providers: [StorageService, CacheService], + exports: [], +}) +export class StorageModule { + constructor(private cache: CacheService) { + this.cache.listen(); + } +} diff --git a/projects/cdk/src/storage/storage.service.ts b/projects/cdk/src/storage/storage.service.ts new file mode 100644 index 0000000..641cb3a --- /dev/null +++ b/projects/cdk/src/storage/storage.service.ts @@ -0,0 +1,79 @@ +import { Injectable } from "@angular/core"; + +export interface IFunc { + (prev?: T): T; +} + +interface Option { + stroage?: "local" | "session"; + defaultValue?: T | IFunc; + serializer?: (v: T) => string; + deserializer?: (v: string) => T; +} + +export const isFunction = (value: unknown): value is Function => typeof value === "function"; + +@Injectable() +export class StorageService { + constructor() {} + + private parseOption(option?: Option) { + const storage = option?.stroage === "session" ? sessionStorage : localStorage; + const serializer = option?.serializer ? option?.serializer : JSON.stringify; + const deserializer = option?.deserializer ? option?.deserializer : JSON.parse; + let defaultValue = option?.defaultValue; + + if (isFunction(option?.defaultValue)) { + defaultValue = option?.defaultValue(); + } + + return { + storage, + serializer, + deserializer, + defaultValue, + }; + } + + get(key: string, option?: Option) { + const { storage, deserializer, defaultValue } = this.parseOption(option); + try { + const val = storage.getItem(key); + if (val) { + return deserializer(val); + } + } catch (error) { + console.error(error); + } + return defaultValue; + } + + set(key: string, value: T | IFunc, option?: Option) { + const { storage, serializer, defaultValue } = this.parseOption(option); + const val = (isFunction(value) ? value() : value) ?? defaultValue; + if (typeof val === "undefined") { + storage.removeItem(key); + } else { + try { + storage.setItem(key, serializer(val)); + } catch (error) { + console.error(error); + } + } + } + + remove(key: string, option?: Pick) { + const { storage } = this.parseOption(option); + storage.removeItem(key); + } + + clear(option?: Pick) { + const { storage } = this.parseOption(option); + storage.clear(); + } + + keys(option?: Pick) { + const { storage } = this.parseOption(option); + return Object.keys(storage); + } +} diff --git a/projects/cdk/src/table-list/index.ts b/projects/cdk/src/table-list/index.ts new file mode 100644 index 0000000..05a28dc --- /dev/null +++ b/projects/cdk/src/table-list/index.ts @@ -0,0 +1,5 @@ +export * from "./table-list.module"; + +export * from "./table-list-options"; +export * from "./table-list/table-list.component"; +export * from "./table-operation/table-operation.component"; diff --git a/projects/cdk/src/table-list/table-list-options.ts b/projects/cdk/src/table-list/table-list-options.ts new file mode 100644 index 0000000..b5a57bf --- /dev/null +++ b/projects/cdk/src/table-list/table-list-options.ts @@ -0,0 +1,143 @@ +import { Observable, Subject } from "rxjs"; +import { produce, immerable, setAutoFreeze } from "immer"; +import { DecSafeAny, TableListColumns, TableOperation } from "../types"; +import { EventEmitter } from "@angular/core"; + +type IfetchData = (...args: DecSafeAny[]) => Observable; + +type ITableListConfig = { + manual?: boolean; + cacheKey?: string; + cacheTo?: string[]; + rowKey?: string; + columnKey?: string; + selectable?: boolean; + withOutDefaultColumns?: boolean; + theadSettable?: boolean; + pageFromZero?: boolean; + frontPagination?: boolean; +}; + +type TableListState = { + selectedKeys: string[]; +}; + +type TableListPager = { + page: number; + size: number; + total: number; + loading: boolean; + sort: { [K: string]: "ascend" | "descend" }; +}; + +setAutoFreeze(false); + +export class TableListOption { + [immerable] = true; + + trigger$ = new Subject(); + + getState$ = new EventEmitter(); + + columns: TableListColumns[] = []; + + operations!: TableOperation[]; + + fetchData: IfetchData; + + manual?: boolean = false; + + cacheKey?: string; + + cacheTo?: string[]; + + rowKey: string; + + columnKey?: string; + + selectable: boolean = false; + + withOutDefaultColumns?: boolean; + + pageFromZero?: boolean; + + theadSettable: boolean = false; + + frontPagination: boolean = true; + + scroll: { x?: string | null; y?: string | null } = { x: "2000px", y: null }; + + pager: TableListPager = { + page: 1, + size: 5, + loading: false, + total: 0, + sort: {}, + }; + + constructor(fetchData: IfetchData, config?: ITableListConfig) { + this.fetchData = fetchData; + this.manual = config?.manual; + this.cacheKey = config?.cacheKey; + this.cacheTo = config?.cacheTo; + this.rowKey = config?.rowKey ?? "id"; + this.selectable = config?.selectable ?? false; + this.withOutDefaultColumns = config?.withOutDefaultColumns; + this.theadSettable = config?.theadSettable ?? false; + this.columnKey = config?.columnKey; + this.pageFromZero = config?.pageFromZero; + this.frontPagination = config?.frontPagination ?? true; + } + + /** + * 设置表格的列,❗❗不可变数据❗❗ + * @param columns TableListColumns + * @returns + */ + setColumns(columns: TableListColumns[]) { + return produce(this, (draft) => { + // if (!this.withOutDefaultColumns) { + // columns = columns.concat( + // { key: "createTime", title: "创建时间", sort: true }, + // { key: "updateTime", title: "更新时间", sort: true, visible: false } + // ); + // draft.pager.sort = { createTime: "descend" }; + // } + draft.columns = columns; + }); + } + + /** + * 设置表格的操作项,❗❗不可变数据❗❗ + * @param columns TableListColumns + * @returns + */ + setOptions(operations: TableOperation[]) { + return produce(this, (draft) => { + draft.operations = operations; + }); + } + + /** + * 设置表格CacheKey,❗❗不可变数据❗❗ + * @param columns TableListColumns + * @returns + */ + setCacheKey(cacheKey: string) { + return produce(this, (draft) => { + draft.cacheKey = cacheKey; + }); + } + + run(e?: DecSafeAny) { + setTimeout(() => { + // 防止 还没有 subscribe 就 next 了 + this.trigger$.next(e); + }, 10); + } + + reset() { + this.pager.page = 1; + this.run(); + } +} diff --git a/projects/cdk/src/table-list/table-list.module.ts b/projects/cdk/src/table-list/table-list.module.ts new file mode 100644 index 0000000..d95859a --- /dev/null +++ b/projects/cdk/src/table-list/table-list.module.ts @@ -0,0 +1,56 @@ +import { NgxPermissionsModule } from "ngx-permissions"; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { RouterModule } from "@angular/router"; +import { DragDropModule } from "@angular/cdk/drag-drop"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { NzDrawerModule } from "ng-zorro-antd/drawer"; +import { NzDropDownModule } from "ng-zorro-antd/dropdown"; +import { NzCheckboxModule } from "ng-zorro-antd/checkbox"; +import { NzEmptyModule } from "ng-zorro-antd/empty"; +import { NzTableModule } from "ng-zorro-antd/table"; +import { NzPaginationModule } from "ng-zorro-antd/pagination"; +import { NzCardModule } from "ng-zorro-antd/card"; +import { NzFormModule } from "ng-zorro-antd/form"; +import { NzSpaceModule } from "ng-zorro-antd/space"; +import { NzIconModule } from "ng-zorro-antd/icon"; +import { NzSwitchModule } from "ng-zorro-antd/switch"; +import { NzSkeletonModule } from "ng-zorro-antd/skeleton"; +import { NzDividerModule } from "ng-zorro-antd/divider"; +import { NzPopoverModule } from "ng-zorro-antd/popover"; +import { NzButtonModule } from "ng-zorro-antd/button"; +import { TableListComponent } from "./table-list/table-list.component"; +import { TableOperationComponent } from "./table-operation/table-operation.component"; +import { TdOverflowDirective } from "./td-overflow.directive"; + +@NgModule({ + declarations: [TableListComponent, TableOperationComponent, TdOverflowDirective], + imports: [ + CommonModule, + RouterModule, + FormsModule, + ReactiveFormsModule, + DragDropModule, + + NzSwitchModule, + NzDividerModule, + NzCheckboxModule, + NzDrawerModule, + NzDropDownModule, + NzEmptyModule, + NzTableModule, + NzPaginationModule, + NzCardModule, + NzFormModule, + NzSpaceModule, + NzButtonModule, + NzPopoverModule, + NzIconModule, + NzSkeletonModule, + NgxPermissionsModule.forRoot(), + ], + exports: [TableListComponent, TableOperationComponent], +}) +export class TableListModule { + constructor() {} +} diff --git a/projects/cdk/src/table-list/table-list/table-list.component.html b/projects/cdk/src/table-list/table-list/table-list.component.html new file mode 100644 index 0000000..0068332 --- /dev/null +++ b/projects/cdk/src/table-list/table-list/table-list.component.html @@ -0,0 +1,223 @@ +
+ +
+
+ + +
+ + + + + + + + + +
+
+
+
+ + + +
+
+ +
+
+ + + + +
+ + + + + + + + {{col.title}} + + + + 操作 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{dataItem[col.key]}} + + + + + + + + + + + + + + +
+ +
+
+ + + + + + + + + + + + +
+ +
+ + +
+
+ + +
+
+ + + + + +
+
+ + + + + +
    +
  • +
    +
    +
    + +
    +
    + {{item.title}} +
    +
    + + +
    +
    +
  • +
+
+
+ + + + + + + 共{{total}}条 + + + + + {{date| date:'yyyy-MM-dd HH:mm:ss'}} + \ No newline at end of file diff --git a/projects/cdk/src/table-list/table-list/table-list.component.less b/projects/cdk/src/table-list/table-list/table-list.component.less new file mode 100644 index 0000000..f99a107 --- /dev/null +++ b/projects/cdk/src/table-list/table-list/table-list.component.less @@ -0,0 +1,119 @@ +.advance-search-btn { + position: relative; + .up-arrow { + position: absolute; + bottom: calc(-100% + 10px); + left: 50%; + transform: translateX(-50%); + color: #fff; + font-size: 28px; + filter: drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.1)); + } + .double-arrow { + transform: rotate(90deg); + transition: transform 0.3s; + &.up { + transform: rotate(-90deg); + } + } +} + +.hidden-option { + display: inline-block; + height: 0; + opacity: 0; + overflow: hidden; + pointer-events: none; +} + +.table-list { + td { + word-break: break-all; + } + th { + white-space: nowrap; + } + ::ng-deep { + .ant-table-pagination.ant-pagination { + padding: 0 16px; + } + + // tbody { + // tr td:last-child { + // width: 0; + // } + // } + } +} + +.advance-search { + ::ng-deep { + .ant-card-body { + padding: 16px 24px; + } + } +} + +.search-row { + ::ng-deep { + > * { + padding: 6px; + } + } +} +.query-form { + ::ng-deep { + .hor { + nz-form-item { + align-items: center; + } + } + nz-form-item { + margin-bottom: 0; + + // flex-direction: column; + // align-items: flex-start; + // justify-content: flex-start; + // margin-right: 12px; + } + } +} + +::ng-deep { + .table-settings { + .ant-drawer-body { + padding: 12px 0; + } + } + .table-setting-item { + background-color: #fff; + &:hover { + background-color: var(--bg-light); + } + } +} + +.cdk-drag-preview { + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12); +} + +.cdk-drag-animating { + transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.table-setting-item:last-child { + border: none; +} + +.columns-list.cdk-drop-list-dragging .table-setting-item:not(.cdk-drag-placeholder) { + transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.columns-item-placeholder { + background: #fff; + border: 3px dotted var(--p); + min-height: 38px; + transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1); +} diff --git a/projects/cdk/src/table-list/table-list/table-list.component.ts b/projects/cdk/src/table-list/table-list/table-list.component.ts new file mode 100644 index 0000000..21381d0 --- /dev/null +++ b/projects/cdk/src/table-list/table-list/table-list.component.ts @@ -0,0 +1,386 @@ +import { + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + SimpleChanges, + TemplateRef, + ViewChild, + Pipe, + PipeTransform, + AfterViewInit, + ElementRef, + ViewChildren, + QueryList, + Renderer2, + ChangeDetectorRef, + OnDestroy, +} from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { SelectionModel } from "@angular/cdk/collections"; +import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop"; + +import { Router } from "@angular/router"; +import { debounceTime, finalize } from "rxjs/operators"; +import { FormsModule, FormControl, FormGroup, AbstractControl } from "@angular/forms"; +import { NzDrawerModule, NzDrawerService } from "ng-zorro-antd/drawer"; + +import { DecSafeAny, PageResult, TableListColumns, TableOperation } from "../../types"; +import { TableListOption } from "../table-list-options"; +import { CacheItem, CacheService, StorageService } from "../../storage"; +import { TableOperationComponent } from "../table-operation/table-operation.component"; + +@Pipe({ + name: "operationFilter", +}) +export class OperationPipe implements PipeTransform { + transform(operations: TableOperation[], rowItem: any): TableOperation[] { + return operations?.filter((f) => (f.visible ? f.visible(rowItem) : true)) ?? []; + } +} + +const DATE_RANGE_FIELDS = ["createTime", "updateTime"]; + +@Component({ + selector: "dec-table-list", + templateUrl: "./table-list.component.html", + styleUrls: ["./table-list.component.less"], +}) +export class TableListComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy { + constructor( + // private modal: NzModalService, + private cdr: ChangeDetectorRef, + private el: ElementRef, + private router: Router, + private drawerService: NzDrawerService, + private storage: StorageService, + private cacheService: CacheService + ) {} + + @Input() props!: TableListOption; + + // https://github.com/angular/angular/issues/13761 + @Input() formGroup = new FormGroup({}); + + /** + * 在表格模式下渲染具体每一个列的模板。 + * $implicit:dataItem[col.key] `具体的值`、 + * key:col.key `字段名`、 + * row:dataItem `当前行数据`、 + * column:col `当前列`、 + */ + @Input() renderColumns?: TemplateRef; + + /** + * 不使用表格模式,自定义渲染 + */ + @Input() renderItem?: TemplateRef; + + @Input() action?: TemplateRef; + + @Input() search?: TemplateRef; + + @Input() searchLayout: "horizontal" | "vertical" = "horizontal"; + + /** + * @deprecated + */ + @Input() advanceSearch?: TemplateRef; + + @Input() showTotal?: TemplateRef; + + @Input() beforeReset?: Function; + + @Input() rowClass?: string; + + // @Input() resizeable?: boolean; + + @Output() onRowClick = new EventEmitter(); + + dataSource: DecSafeAny[] = []; + + totalPages = 0; + + public selection = new SelectionModel(true); + + public advanceSearchVisible: boolean = false; + + public optionWidth: string = "200px"; + + private cache?: CacheItem; + + get columns(): TableListColumns[] { + return this.props.columns ?? []; + } + + get operation(): TableOperation[] { + return this.props.operations ?? []; + } + + get createTime() { + return this.formGroup.get("createTime"); + } + + ngOnInit(): void { + this.props.trigger$.pipe(debounceTime(100)).subscribe((e?: any) => { + if (this.props.fetchData) { + this.props.pager.loading = true; + this.selection.clear(); + this.emitState(); + const query = this.formGroup.getRawValue(); + // this.saveQueryDataToCache(query); + const pager = this.parsePager(); + this.props + .fetchData(pager, this.parseQueryValue(), e) + .pipe( + finalize(() => { + this.props.pager.loading = false; + }) + ) + .subscribe((f: PageResult) => { + this.dataSource = f.records ?? f.content; + console.log("this.dataSource", f); + this.props.pager.total = f.total; + this.totalPages = Math.ceil(f.total / this.props.pager.size); + this.checkPage(); + }); + } + }); + + setTimeout(() => { + this.emitState(); + }, 10); + + // 初始化的时候? + if (!this.props.manual) { + this.props.run(); + } + this.getCacheData(); + } + + ngOnDestroy(): void { + // console.log("ngOnDestroy"); + } + + ngAfterViewInit(): void { + const opEl: HTMLDivElement = this.el.nativeElement.querySelector(".hidden-option"); + + if (opEl) { + setTimeout(() => { + const paddingX = 2 * 24; + this.optionWidth = Math.ceil(opEl.offsetWidth + paddingX) + "px"; + this.cdr.detectChanges(); + }); + } + } + + ngOnChanges(changes: SimpleChanges): void { + const props = changes["props"]; + const currentProps = props?.currentValue; + const previousProps = props?.previousValue; + if (currentProps) { + if (previousProps?.["cacheKey"] !== currentProps?.["cacheKey"]) { + this.removeOldCache(); + this.getCacheData(); + } + this.parseColumus(currentProps?.["columns"]); + this.parseFormControls(currentProps?.["queryForm"]); + } + } + + private saveQueryDataToCache(query: {}) { + if (this.cache) { + const { page, size, sort, total } = this.props.pager; + this.cache.setItem({ page, size, sort, total, ...query }); + } + } + + private removeOldCache() { + this.cache?.remove(); + } + + private getCacheData() { + let { cacheKey, cacheTo = [] } = this.props; + + this.formGroup.reset(); + if (!cacheKey) { + cacheKey = `DATA_CACHE_${this.formatePathname()}`; + } + if (!this.cache) { + this.cache = this.cacheService.initCache(cacheKey, [this.router.url, ...cacheTo]); + } + const cacheData = this.cache?.getItem(); + if (cacheData) { + const { page, size, sort, total, ...query } = cacheData; + this.props.pager = { + ...this.props.pager, + total, + page, + size, + sort, + }; + + this.formGroup.patchValue(query); + } + } + + private parsePager() { + let { page, size } = this.props.pager; + if (this.props.pageFromZero) { + page = page - 1; + } + const pager = { page: page, current: page, size, sort: this.formatSort() }; + return pager; + } + + private parseQueryValue(): {} { + const o = Object.create(null); + Object.entries(this.formGroup.getRawValue()).forEach(([k, v]) => { + if (DATE_RANGE_FIELDS.includes(k) && Array.isArray(v)) { + const from = v?.[0] instanceof Date ? v?.[0]?.toISOString() : v[0]; + const to = v?.[1] instanceof Date ? v?.[1]?.toISOString() : v[1]; + o[k] = { from, to }; + } else { + o[k] = v; + } + }); + return o; + } + + private checkPage() { + const maxPages = this.totalPages === 0 ? 1 : this.totalPages; + if (maxPages < this.props.pager.page) { + this.props.pager.page = maxPages; + this.reload(); + } + } + + private emitState() { + this.props.getState$.emit({ selectedKeys: this.selection.selected }); + } + + private parseColumus(currentCols: TableListColumns[]) { + if (this.props.columns.some((s) => s.coverStorage)) { + this.onColumnsChange(); + } + const colsFormStorage: TableListColumns[] = this.storage.get(this.formatePathname()) ?? []; + this.props.columns = currentCols + .map((i: TableListColumns) => { + const storageCol = colsFormStorage.find((f) => f.key === i.key); + let visible = i.visible !== void 0 ? i.visible : true; + let width = i.width; + // if (["createTime", "updateTime"].includes(i.key)) { + // width = "180px"; + // } + return { + ...i, + visible, + width, + ...(storageCol ?? {}), + }; + }) + .sort((a, b) => (a.order ?? 0) - (b.order ?? 0)); + } + + private parseFormControls(formGroup?: FormGroup) { + // if (!this.props.withOutDefaultColumns) { + // this.formGroup.addControl("updateTime", new FormControl(null)); + // this.formGroup.addControl("createTime", new FormControl(null)); + // } + } + + formatSort() { + const { sort } = this.props.pager; + if (!sort) { + return null; + } + const sortArr = [...Object.entries(sort)]?.[0]; + if (!sortArr) { + return null; + } + return `${sortArr[0]},${sortArr[1] === "ascend" ? "asc" : "desc"}`; + } + + colunmsSort(event: unknown) { + const e = event as CdkDragDrop; + moveItemInArray(this.props.columns, e.previousIndex, e.currentIndex); + this.onColumnsChange(); + } + + reload() { + this.props.run(); + } + + onPageChange() { + if (!this.props.frontPagination) { + this.props.run(); + } + } + + doQuery() { + this.props.pager.page = 1; + this.reload(); + } + + reset() { + this.beforeReset?.(); + this.formGroup.reset(); + this.doQuery(); + } + + onSort(v: string | null, fieldName: string) { + this.props.pager.sort = { [fieldName]: v as "ascend" | "descend" }; + this.reload(); + } + + toggleAdvanceSearch(show?: boolean) { + if (typeof show === "boolean") { + this.advanceSearchVisible = show; + } else { + this.advanceSearchVisible = !this.advanceSearchVisible; + } + } + + filteroperation(dataItem: any): TableOperation[] { + return this.operation?.filter((f) => (f.visible ? f.visible(dataItem) : true)) ?? []; + } + + toggleColumnVisible(nzContent: TemplateRef) { + this.drawerService.create({ + nzTitle: "设置展示项", + nzWidth: 280, + nzContent, + nzWrapClassName: "table-settings", + }); + } + + private formatePathname() { + return this.props.columnKey ?? this.router.url.replace(/\//g, "_"); + } + + onColumnsChange() { + const columnStorageKey = `COLUMN_${this.formatePathname()}`; + this.storage.set( + columnStorageKey, + this.columns.map((i, idx) => { + const { key, width, visible } = i; + return { key, width, visible, order: idx }; + }) + ); + } + + onChecked(checked: boolean, rowKey?: DecSafeAny) { + const fn = checked ? "select" : "deselect"; + const rowKeys = rowKey ? [rowKey] : this.dataSource.map((i) => i[this.props.rowKey]); + this.selection[fn](...rowKeys); + this.emitState(); + } + + onTrClick(dataItem: DecSafeAny) { + if (this.onRowClick) { + this.onRowClick.emit(dataItem); + } + } +} diff --git a/projects/cdk/src/table-list/table-operation/table-operation.component.html b/projects/cdk/src/table-list/table-operation/table-operation.component.html new file mode 100644 index 0000000..321537a --- /dev/null +++ b/projects/cdk/src/table-list/table-operation/table-operation.component.html @@ -0,0 +1,30 @@ +
+ + + + {{item.title}} + + + + + + + + 更多操作 + + + +
    +
  • + {{item.title}} +
  • +
+
+
+
\ No newline at end of file diff --git a/projects/cdk/src/table-list/table-operation/table-operation.component.less b/projects/cdk/src/table-list/table-operation/table-operation.component.less new file mode 100644 index 0000000..88222d3 --- /dev/null +++ b/projects/cdk/src/table-list/table-operation/table-operation.component.less @@ -0,0 +1,25 @@ +.operation { + display: inline-block; + min-width: 120px; +} + +.danger { + color: var(--red); +} +.disabled { + cursor: not-allowed; + a { + pointer-events: none; + color: rgba(0, 0, 0, 0.65); + } +} + +.operation { + a { + // color: rgba(0, 0, 0, 0.65); + &:hover { + color: var(--p); + text-decoration: underline; + } + } +} diff --git a/projects/cdk/src/table-list/table-operation/table-operation.component.ts b/projects/cdk/src/table-list/table-operation/table-operation.component.ts new file mode 100644 index 0000000..e2003ad --- /dev/null +++ b/projects/cdk/src/table-list/table-operation/table-operation.component.ts @@ -0,0 +1,61 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { NgxPermissionsService } from "ngx-permissions"; + +import { DecSafeAny, TableOperation } from "../../types"; + +@Component({ + selector: "dec-table-operation", + templateUrl: "./table-operation.component.html", + styleUrls: ["./table-operation.component.less"], +}) +export class TableOperationComponent implements OnInit { + constructor(private premission: NgxPermissionsService) {} + + @Input() options: TableOperation[] = []; + + @Input() maximum: number = 3; + + @Input() rowData: DecSafeAny; + + ngOnInit(): void { + // this.options = this.options.filter(async (f) => { + // if (f.visible) { + // return f.visible(this.rowData); + // } + // if (f.premissions.length) { + // console.log("f.premissions", f.premissions, this.premission.hasPermission(f.premissions)); + // return await this.premission.hasPermission(f.premissions); + // } + // return true; + // }); + this.filterOption(); + } + + async filterOption() { + const o = []; + for (const f of this.options) { + let visible = true; + if (typeof f.visible === "function") { + visible = f.visible(this.rowData); + } + if (!visible) { + continue; + } + if (f.premissions.length) { + const r = await this.premission.hasPermission(f.premissions); + if (r) { + o.push(f); + } + continue; + } + o.push(f); + } + this.options = o; + } + + onClick(item: TableOperation) { + if (item.onClick) { + item?.onClick(this.rowData); + } + } +} diff --git a/projects/cdk/src/table-list/td-overflow.directive.ts b/projects/cdk/src/table-list/td-overflow.directive.ts new file mode 100644 index 0000000..49dd892 --- /dev/null +++ b/projects/cdk/src/table-list/td-overflow.directive.ts @@ -0,0 +1,30 @@ +import { AfterContentInit, AfterViewInit, ChangeDetectorRef, Directive, ElementRef, Input } from "@angular/core"; +import { NzPopoverDirective } from "ng-zorro-antd/popover"; + +@Directive({ + selector: "[jwTdOverflow]", +}) +export class TdOverflowDirective implements AfterViewInit { + @Input("jwTdOverflow") content!: string; + + constructor( + private elementRef: ElementRef, + private popoverDirective: NzPopoverDirective, + private cdr: ChangeDetectorRef + ) {} + + ngOnInit() {} + + ngAfterViewInit(): void { + const element = this.elementRef.nativeElement as HTMLElement; + console.log("element", element.offsetWidth, element.scrollWidth); + // 如果元素的实际宽度大于可见宽度,就使用 nz-popover 指令来显示完整的内容 + if (element.offsetWidth < element.scrollWidth) { + this.popoverDirective.content = this.content; + } else { + this.popoverDirective.trigger = null; + this.popoverDirective.content = "da"; + element.textContent = this.content; + } + } +} diff --git a/projects/cdk/src/types/index.ts b/projects/cdk/src/types/index.ts new file mode 100644 index 0000000..50b1044 --- /dev/null +++ b/projects/cdk/src/types/index.ts @@ -0,0 +1,58 @@ +export type AnyObject = { [k: string]: any }; + +export type DecSafeAny = any; + +export type DecText = number | string; + +export type Augmented = O & AnyObject; + +export interface ResponseType { + body: T; + code: number; + desc: string; + success: boolean; +} + +export interface TableListColumns { + key: string; + title: string; + visible?: boolean; + width?: string; + sort?: boolean; + order?: number; + disabled?: boolean; + coverStorage?: boolean; +} + +export interface TableOperation { + title: string; + href?: string; + link?: string[]; + target?: string; + premissions: string[]; + danger?: boolean; + disabled?: boolean; + onClick?: (v: DecSafeAny) => void; + visible?: (v: DecSafeAny) => boolean; +} + +export interface PageResult { + total: number; + content: T[]; + records: T[]; +} + +export interface AuthInterface { + role: string; + userId: string; + userName: string; + permissionList: AuthPermissionInterface[]; +} + +export interface AuthPermissionInterface { + name: string; + roleId: string; + scope: 1 | 0; + type: number; + value: "true" | "false"; +} diff --git a/projects/cdk/src/utils/index.ts b/projects/cdk/src/utils/index.ts new file mode 100644 index 0000000..596c713 --- /dev/null +++ b/projects/cdk/src/utils/index.ts @@ -0,0 +1,46 @@ +import { AbstractControl, FormControl, FormGroup } from "@angular/forms"; + +export class Utils { + static validateFormGroup(formGroup: FormGroup) { + if (!formGroup.valid) { + Object.keys(formGroup.controls).forEach((field) => { + const control = formGroup.get(field); + if (control instanceof FormControl) { + control.markAsDirty(); + control.markAsTouched({ onlySelf: true }); + control.updateValueAndValidity({ onlySelf: true }); + } else if (control instanceof FormGroup) { + Utils.validateFormGroup(control); + } + }); + } + return formGroup.valid; + } + + static validateFormControl(control: AbstractControl) { + control.markAsDirty(); + control.markAsTouched({ onlySelf: true }); + control.updateValueAndValidity({ onlySelf: true }); + return control.valid; + } + + static queryify(query: {}): string { + const o = Object.create(null); + Object.entries(query).forEach(([k, v]) => { + if (v !== void 0 && v !== null) { + o[k] = v; + } + }); + return new URLSearchParams(o).toString(); + } + + static getHostByEnvironment(prod?: boolean) { + const protocol = window.location.protocol; + const host = prod ? window.location.host : `localhost:${window.location.port}`; + return `${protocol}//${host}`; + } + + // static detectionImagePath(jobId: string, imgName: string) { + // return `/record/${jobId}/detect/${imgName}`; + // } +} diff --git a/projects/cdk/src/validators/index.ts b/projects/cdk/src/validators/index.ts new file mode 100644 index 0000000..2d6d986 --- /dev/null +++ b/projects/cdk/src/validators/index.ts @@ -0,0 +1,66 @@ +import { ValidatorFn, Validators } from "@angular/forms"; + +export class DecValidators { + static required(message?: string): ValidatorFn { + return (control) => { + const error = Validators.required(control); + return error ? { ...error, required: { message } } : null; + }; + } + static maxLength(maxLength: number, message?: string): ValidatorFn { + return (control) => { + const error = Validators.maxLength(maxLength)(control); + if (error) { + error["maxlength"]["message"] = message; + return error; + } + return null; + }; + } + static minLength(maxLength: number, message?: string): ValidatorFn { + return (control) => { + const error = Validators.minLength(maxLength)(control); + if (error) { + error["minlength"]["message"] = message; + return error; + } + return null; + }; + } + static pattern(pattern: RegExp | string, message?: string): ValidatorFn { + return (control) => { + const error = Validators.pattern(pattern)(control); + if (error) { + error["pattern"]["message"] = message; + return error; + } + return null; + }; + } + static min(maxLength: number, message?: string): ValidatorFn { + return (control) => { + const error = Validators.min(maxLength)(control); + if (error) { + error["min"]["message"] = message; + return error; + } + return null; + }; + } + static max(maxLength: number, message?: string): ValidatorFn { + return (control) => { + const error = Validators.max(maxLength)(control); + if (error) { + error["max"]["message"] = message; + return error; + } + return null; + }; + } + static email(message?: string): ValidatorFn { + return (control) => { + const error = Validators.email(control); + return error ? { ...error, email: { message } } : null; + }; + } +} diff --git a/projects/cdk/tsconfig.lib.json b/projects/cdk/tsconfig.lib.json new file mode 100644 index 0000000..543fd47 --- /dev/null +++ b/projects/cdk/tsconfig.lib.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": [ + "**/*.spec.ts" + ] +} diff --git a/projects/cdk/tsconfig.lib.prod.json b/projects/cdk/tsconfig.lib.prod.json new file mode 100644 index 0000000..06de549 --- /dev/null +++ b/projects/cdk/tsconfig.lib.prod.json @@ -0,0 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "declarationMap": false + }, + "angularCompilerOptions": { + "compilationMode": "partial" + } +} diff --git a/projects/cdk/tsconfig.spec.json b/projects/cdk/tsconfig.spec.json new file mode 100644 index 0000000..ce7048b --- /dev/null +++ b/projects/cdk/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/projects/client/proxy.conf.json b/projects/client/proxy.conf.json new file mode 100644 index 0000000..d6d46c0 --- /dev/null +++ b/projects/client/proxy.conf.json @@ -0,0 +1,15 @@ +{ + "/api": { + "target": "http://47.109.27.8:8081", + "secure": false + }, + "/record": { + "target": "http://47.109.27.8", + "secure": false + }, + "/websocket": { + "target": "http://47.109.27.8:8081", + "secure": false, + "ws": true + } +} \ No newline at end of file diff --git a/projects/client/src/app/app-routing.module.ts b/projects/client/src/app/app-routing.module.ts new file mode 100644 index 0000000..0a1c5b8 --- /dev/null +++ b/projects/client/src/app/app-routing.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { authGuard } from "./core/gaurd/auth.guard"; + +const routes: Routes = [ + { + path: "auth", + loadChildren: () => import("./feature/auth/auth.module").then((m) => m.AuthModule), + }, + { + path: "", + pathMatch: "full", + redirectTo: "detection", + }, + { + path: "detection", + loadChildren: () => import("./feature/detection/detection.module").then((m) => m.DetectionModule), + canActivate: [authGuard], + }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/projects/client/src/app/app.component.html b/projects/client/src/app/app.component.html new file mode 100644 index 0000000..35b5ef8 --- /dev/null +++ b/projects/client/src/app/app.component.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/projects/client/src/app/app.component.less b/projects/client/src/app/app.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/app.component.ts b/projects/client/src/app/app.component.ts new file mode 100644 index 0000000..6823499 --- /dev/null +++ b/projects/client/src/app/app.component.ts @@ -0,0 +1,73 @@ +import { Component, OnInit, Renderer2 } from "@angular/core"; +import { AuthService } from "@client/app/core/services"; +import { delay, finalize } from "rxjs"; + +@Component({ + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.less"], +}) +export class AppComponent implements OnInit { + constructor(private api: AuthService, private rd2: Renderer2) {} + + loading = true; + + ngOnInit(): void { + this.loading = true; + this.api + .getSystemInfo() + .pipe( + finalize(() => { + this.loading = false; + }) + ) + .subscribe((res) => { + if (res.theme) { + let style = ""; + Object.entries(res.theme as Record).forEach(([k, v]) => { + if (!["themeName", "themeId"].includes(k)) { + const key = k.replaceAll("_", "-"); + style += `--${key}:${v};`; + if (k === "primary") { + const pRgba = this.parseRGB(v); + style += `--p-rgb:${pRgba.join(",")};`; + style += `--p:${v};`; + } + + if (k === "text_color") { + style += `--thead-color:${v};`; + style += `--input-color:${v};`; + style += `--table-color:${v};`; + } + } + }); + + this.rd2.setAttribute(document.body, "style", style); + } + if (res.systemInfo) { + const { reservedField, systemInfoName } = res.systemInfo; + const title = (reservedField ? `${reservedField} · ` : "") + systemInfoName; + document.title = title; + } + }); + } + + parseRGB(color: string) { + color = color.replace(/\s/g, ""); + + const rgbRegex = /^rgb\((\d+),(\d+),(\d+)\)$/; + const rgbaRegex = /^rgba\((\d+),(\d+),(\d+),(\d+(\.\d+)?)\)$/; + + let matches = color.match(rgbRegex) || color.match(rgbaRegex); + + if (matches) { + const r = parseInt(matches[1], 10); + const g = parseInt(matches[2], 10); + const b = parseInt(matches[3], 10); + + return [r, g, b]; + } else { + return []; + } + } +} diff --git a/projects/client/src/app/app.module.ts b/projects/client/src/app/app.module.ts new file mode 100644 index 0000000..bb4aef1 --- /dev/null +++ b/projects/client/src/app/app.module.ts @@ -0,0 +1,47 @@ +import { HTTP_INTERCEPTORS, HttpClientModule } from "@angular/common/http"; +import { NgModule } from "@angular/core"; +import { HashLocationStrategy, LocationStrategy, registerLocaleData } from "@angular/common"; +import { BrowserModule } from "@angular/platform-browser"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { NzConfig, NZ_CONFIG } from "ng-zorro-antd/core/config"; +import { NZ_I18N } from "ng-zorro-antd/i18n"; +import { zh_CN } from "ng-zorro-antd/i18n"; +import zh from "@angular/common/locales/zh"; +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { SharedModule } from "./shared/shared.module"; +import { NgxPermissionsModule } from "ngx-permissions"; +import { ClientHTTPInterceptor } from "./core/services/client.interceptor"; + +registerLocaleData(zh); + +const ngZorroConfig: NzConfig = { + pageHeader: { + nzGhost: false, + }, +}; + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + BrowserAnimationsModule, + HttpClientModule, + SharedModule, + AppRoutingModule, + NgxPermissionsModule.forRoot(), + ], + providers: [ + { provide: NZ_I18N, useValue: zh_CN }, + + { provide: NZ_CONFIG, useValue: ngZorroConfig }, + + { + provide: LocationStrategy, + useClass: HashLocationStrategy, + }, + { provide: HTTP_INTERCEPTORS, useClass: ClientHTTPInterceptor, multi: true }, + ], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/projects/client/src/app/core/gaurd/auth.guard.ts b/projects/client/src/app/core/gaurd/auth.guard.ts new file mode 100644 index 0000000..0e115ec --- /dev/null +++ b/projects/client/src/app/core/gaurd/auth.guard.ts @@ -0,0 +1,27 @@ +import { inject } from "@angular/core"; +import { Router } from "@angular/router"; +import { decConfigToken } from "@cdk/public-api"; +import { map } from "rxjs"; +import { DetectionApiService } from "../services"; + +export const authGuard = () => { + const api = inject(DetectionApiService); + const router = inject(Router); + const decConfig = inject(decConfigToken); + // const token = localStorage.getItem(decConfig.localStroageKey); + + // if (!token) { + // router.navigate([decConfig.loginUrl]); + // return false; + // } + return api.getAllPoint().pipe( + map((res) => { + if (res) { + return true; + } else { + router.navigate([decConfig.loginUrl]); + return false; + } + }) + ); +}; diff --git a/projects/client/src/app/core/gaurd/permisson.guard.ts b/projects/client/src/app/core/gaurd/permisson.guard.ts new file mode 100644 index 0000000..2409789 --- /dev/null +++ b/projects/client/src/app/core/gaurd/permisson.guard.ts @@ -0,0 +1,33 @@ +import { inject } from "@angular/core"; +import { + ActivatedRoute, + ActivatedRouteSnapshot, + CanActivateChildFn, + CanActivateFn, + Route, + Router, + RouterStateSnapshot, +} from "@angular/router"; +import { AuthInterface } from "@cdk/public-api"; +import { NgxPermissionsService } from "ngx-permissions"; + +export const PermissionLoadGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const permissionsService = inject(NgxPermissionsService); + const auth = localStorage.getItem("auth"); + if (auth) { + try { + const authData = JSON.parse(auth) as AuthInterface; + if (Array.isArray(authData.permissionList)) { + const permissionList = authData.permissionList; + const permissions = permissionList.reduce((a, c) => { + if (c.scope === 0 && c.value === "true") { + return a.concat(c.roleId); + } + return a; + }, [] as string[]); + permissionsService.loadPermissions(permissions); + } + } catch (error) {} + } + return true; +}; diff --git a/projects/client/src/app/core/services/auth.service.ts b/projects/client/src/app/core/services/auth.service.ts new file mode 100644 index 0000000..c6142d8 --- /dev/null +++ b/projects/client/src/app/core/services/auth.service.ts @@ -0,0 +1,56 @@ +import { HttpClient, HttpParams, HttpResponse } from "@angular/common/http"; +import { Inject, Injectable } from "@angular/core"; +import { DecConfig, decConfigToken } from "@cdk/public-api"; +import { AnyObject, ResponseType } from "@cdk/types"; +import { environment } from "@client/environments/environment"; +import { map, of, tap } from "rxjs"; + +export interface SystemInfoInterface { + theme?: Record; + info?: { logoImg: string; systemInfoName: string }; +} + +@Injectable({ + providedIn: "root", +}) +export class AuthService { + constructor(private http: HttpClient, @Inject(decConfigToken) private decConfig: Required) {} + + private system: SystemInfoInterface = {}; + + private systemLoaded = false; + + getSystemInfo() { + if (this.systemLoaded) { + return of(this.system); + } + return this.http.post("/api/config/selectSystemInfoById", {}).pipe( + map((res) => { + return res.body; + }), + tap((res) => { + if (res.systemInfo) { + localStorage.setItem("systemInfo", JSON.stringify(res.systemInfo)); + this.system.info = res.systemInfo; + } + if (res.theme) { + localStorage.setItem("theme", JSON.stringify(res.theme)); + this.system.theme = res.theme; + } + console.log("this.system", this.system); + this.systemLoaded = true; + }) + ); + } + + login(vals: AnyObject) { + const auth = { ...vals, clientVersion: environment.clientVersion, clientType: environment.clientType }; + return this.http.post("/api/user/login", auth).pipe( + tap((res) => { + if (res.success) { + localStorage.setItem("auth", JSON.stringify(res.body)); + } + }) + ); + } +} diff --git a/projects/client/src/app/core/services/client.interceptor.ts b/projects/client/src/app/core/services/client.interceptor.ts new file mode 100644 index 0000000..e639fbc --- /dev/null +++ b/projects/client/src/app/core/services/client.interceptor.ts @@ -0,0 +1,43 @@ +import { Inject, Injectable } from "@angular/core"; +import { + HttpRequest, + HttpHandler, + HttpEvent, + HttpInterceptor, + HttpErrorResponse, + HttpResponse, +} from "@angular/common/http"; +import { catchError, Observable, switchMap, tap, throwError, timer } from "rxjs"; +import { Router } from "@angular/router"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { ResponseType } from "@cdk/types"; +import { AuthService } from "./auth.service"; + +@Injectable({ providedIn: "root" }) +export class ClientHTTPInterceptor implements HttpInterceptor { + constructor(private auth: AuthService, private router: Router) {} + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + return this.handleResult(next, req); + } + + private handleResult(next: HttpHandler, authReq: HttpRequest): Observable> { + return next.handle(authReq).pipe( + catchError((err: HttpErrorResponse) => { + const throwErr = throwError(() => err); + + const error: ResponseType = err.error; + + if (error.success === false) { + if (error.code === 401) { + this.auth.login({ uid: "", password: "" }).subscribe(() => { + this.router.navigate(["/"]); + }); + } + } + + return throwErr; + }) + ); + } +} diff --git a/projects/client/src/app/core/services/detection-api.service.ts b/projects/client/src/app/core/services/detection-api.service.ts new file mode 100644 index 0000000..d844b95 --- /dev/null +++ b/projects/client/src/app/core/services/detection-api.service.ts @@ -0,0 +1,269 @@ +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { AnyObject, Augmented, DecText, ResponseType } from "@cdk/types"; +import { Utils } from "@cdk/utils"; +import { AlarmDTO, AlgorithmDTO } from "@client/dtos"; +import { + DeviceDTO, + PointDTO, + PointGroupDTO, + PointStatusEnum, + PoleItemDTO, + PoleQueryDTO, + PowerStationDTO, +} from "@client/dtos/point.dto"; +import { map, Observable, of, tap } from "rxjs"; + +@Injectable({ + providedIn: "root", +}) +export class DetectionApiService { + constructor(private http: HttpClient) {} + + allPoint: PowerStationDTO[] = []; + + imgBaseUrl: string = ""; + + loadImage(jobId: string, img: string) { + return this.http.post>("/api/img/base", { jobId, img }).pipe( + map((res) => { + return "data:image/jpeg;base64," + res.body; + }) + ); + } + + loadImages(url: string): Promise { + return new Promise((resolve, reject) => { + if (url.startsWith("data:image/jpeg;base64,")) { + resolve(url); + return; + } + this.http.get(url, { responseType: "blob" }).subscribe({ + next(blob: Blob) { + // setTimeout(() => { + // resolve(""); + // }, 150); + const reader = new FileReader(); + reader.onloadend = () => { + resolve(reader.result as string); + }; + reader.readAsDataURL(blob); + }, + error(error) { + reject(new Error(`Failed to load image ${url}, ${error}`)); + }, + }); + }); + } + + getAllPoint(force?: boolean) { + if (this.allPoint.length > 0 && !force) { + return of(this.allPoint); + } + return this.http.post>("/api/point/getAll", {}).pipe( + map((res) => { + return res.body.map((station) => { + return { + ...station, + groupList: station.groupList.map((group) => { + let status = PointStatusEnum.NORMAL; + if (group.pointList.some((s) => s.status === PointStatusEnum.ABNORMAL)) { + status = PointStatusEnum.ABNORMAL; + } else if (group.pointList.some((s) => s.status === PointStatusEnum.DISCONNECT)) { + status = PointStatusEnum.DISCONNECT; + } + return { + ...group, + status, + }; + }), + }; + }); + }), + tap((points) => { + this.allPoint = points; + }) + ); + } + + getImageBaseUrl(force?: boolean) { + if (!force) { + if (this.imgBaseUrl) { + return of(this.imgBaseUrl); + } + } + return this.http.post>("/api/img/path", {}).pipe( + map((res) => { + return res.body; + }), + tap((imgBaseUrl) => { + this.imgBaseUrl = imgBaseUrl; + }) + ); + } + + getFlatPoints(): Observable<{ points: PointDTO[]; groups: PointGroupDTO[] }> { + return this.getAllPoint().pipe( + map((p) => { + const groups = p?.[0]?.groupList; + const points: PointDTO[] = []; + if (Array.isArray(groups)) { + groups.forEach((g) => { + points.push( + ...g.pointList.map((p) => ({ + ...p, + gid: g.motorGroupId, + gname: g.name, + })) + ); + }); + } + return { points, groups }; + }) + ); + } + + getNotice() { + return this.http.post>("/api/detect/alarm", null); + } + + getRealtimeJob(pointId: DecText) { + return this.http.post>("/api/detect/getRealtimeJob", { pointId }); + } + + getDetcttionHistoryPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post(`/api/history/query`, q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.records, + }; + }) + ); + } + + getHistoryDetail(jobId: DecText) { + return this.http + .post>(`/api/history/detail`, { + jobId, + current: 1, + size: 5, + }) + .pipe( + map((r) => { + return r.body.dataList; + }) + ); + } + + exportWord(data: {}) { + return this.http.post("/api/history/exportWord", data, { + observe: "response", + responseType: "blob" as "json", + }); + } + + exportExcel(data: {}) { + return this.http.post("/api/history/exportExcel", data, { + observe: "response", + responseType: "blob" as "json", + }); + } + + getQuery(jobId: string) { + return this.http.post>("/api/detect/query", { jobId }).pipe( + map((r) => { + return r; + return { + body: {}, + success: true, + }; + }) + ); + // .pipe( + // map((i) => { + // i.body[5][2].value = 6; + // i.body[8][8].value = 116; + // i.body[4][8].alarm = true; + // i.body[2][8].alarm = true; + // i.body[1][8].alarm = true; + // i.body[1][10].alarm = true; + // i.body[20][10].alarm = true; + // i.body[4][8].alarm = true; + // i.body[15][9].alarm = true; + // i.body[11][1].alarm = true; + + // return i; + // }) + // ); + } + + getImg(jobId: string) { + return this.http.post>>("/api/detect/getImg", { jobId }); + } + + getBase64Image(o: { jobID: string; img: string }) { + return this.http.post("/api/img/base", o); + } + + getFeatures(pointId?: string) { + // return of({ + // body: { + // line: "引出线变形", + // bolt: "螺栓松动", + // temperature: "无线测温", + // pole: "磁极开闸", + // }, + // }); + return this.http.post>>("/api/analysis/features", { pointId }); + } + + manualDetection(pointId: string) { + return this.http.post("/api/detect/manualDetection", { pointId }); + } + + getAnalysisChartData(q: {}) { + return this.http.post[]>>>("/api/analysis/chartData", q); + } + + getVersion() { + return this.http.post("/api/config/selectVersion", null); + } + + getExportConfig(config: {}) { + return this.http.post("/api/config/select", config); + } + + updateExportConfig(config: {}) { + return this.http.post("/api/config/update", config); + } + + resetPointData(pointId: string) { + return this.http.post("/api/point/reset", { pointId }); + } + + savePointEnable(data: AnyObject[]) { + return this.http.post("/api/point/switch", data); + } + + getAlgorithm() { + return this.http.post>("/api/algorithm/selectParams", null); + } + + saveAlgorithm(vals: {}) { + return this.http.post("/api/algorithm/updateParams", vals); + } + + saveTemperatureSetting(vals: {}) { + return this.http.post>("/api/device/updateTemp", vals); + } + + getTemperatureSettings() { + return this.http.post("/api/device/selectTemp", null); + } + + getDeviceListByPointId(pointId: string) { + return this.http.post>("/api/device/select", { pointId }); + } +} diff --git a/projects/client/src/app/core/services/index.ts b/projects/client/src/app/core/services/index.ts new file mode 100644 index 0000000..34c8587 --- /dev/null +++ b/projects/client/src/app/core/services/index.ts @@ -0,0 +1,4 @@ +export * from "./auth.service"; +export * from "./detection-api.service"; +export * from "./websocket-api.service"; +export * from "./utils.service"; diff --git a/projects/client/src/app/core/services/utils.service.ts b/projects/client/src/app/core/services/utils.service.ts new file mode 100644 index 0000000..08cfb78 --- /dev/null +++ b/projects/client/src/app/core/services/utils.service.ts @@ -0,0 +1,11 @@ +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { ResponseType } from "@cdk/types"; +import { map } from "rxjs"; + +@Injectable({ + providedIn: "root", +}) +export class UtilsService { + constructor(private http: HttpClient) {} +} diff --git a/projects/client/src/app/core/services/websocket-api.service.ts b/projects/client/src/app/core/services/websocket-api.service.ts new file mode 100644 index 0000000..798cf82 --- /dev/null +++ b/projects/client/src/app/core/services/websocket-api.service.ts @@ -0,0 +1,65 @@ +import { Injectable } from "@angular/core"; +import { WebSocketSubject } from "rxjs/webSocket"; +import { environment } from "@client/environments/environment"; + +@Injectable({ + providedIn: "root", +}) +export class WebsocketApiService { + connect(wsUrl: string): WebSocketSubject { + const protocol = window.location.protocol.replace("http", "ws"); + const host = environment.production ? window.location.host : `localhost:${window.location.port}`; + wsUrl = `${protocol}//${host}${wsUrl}`; + console.log("wsUrl", environment, wsUrl); + return new WebSocketSubject(wsUrl); + } +} +// const CHAT_URL = "ws://localhost:8082"; + +// @Injectable({ +// providedIn: "root", +// }) +// export class WebsocketApiService { +// private subject?: AnonymousSubject; + +// public messages: Subject; + +// constructor() { +// this.messages = >this.connect(CHAT_URL).pipe( +// map((response: MessageEvent): AnyObject => { +// console.log(response.data); +// let data = JSON.parse(response.data); +// return data; +// }) +// ); +// } + +// public connect(url: string): AnonymousSubject { +// if (!this.subject) { +// this.subject = this.create(url); +// console.log("Successfully connected: " + url); +// } +// return this.subject; +// } + +// private create(url: string): AnonymousSubject { +// let ws = new WebSocket(url); +// let observable = new Observable((obs: Observer) => { +// ws.onmessage = obs.next.bind(obs); +// ws.onerror = obs.error.bind(obs); +// ws.onclose = obs.complete.bind(obs); +// return ws.close.bind(ws); +// }); +// let observer = { +// error: () => {}, +// complete: () => {}, +// next: (data: AnyObject) => { +// console.log("Message sent to websocket: ", data, ws.readyState, WebSocket.OPEN); +// if (ws.readyState === WebSocket.OPEN) { +// ws.send(JSON.stringify(data)); +// } +// }, +// }; +// return new AnonymousSubject(observer, observable); +// } +// } diff --git a/projects/client/src/app/feature/auth/auth-routing.module.ts b/projects/client/src/app/feature/auth/auth-routing.module.ts new file mode 100644 index 0000000..80cd35a --- /dev/null +++ b/projects/client/src/app/feature/auth/auth-routing.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { LoginComponent } from "./pages"; + +const routes: Routes = [ + { + path: "login", + component: LoginComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class AuthRoutingModule {} diff --git a/projects/client/src/app/feature/auth/auth.module.ts b/projects/client/src/app/feature/auth/auth.module.ts new file mode 100644 index 0000000..76db313 --- /dev/null +++ b/projects/client/src/app/feature/auth/auth.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from "@angular/core"; +import { SharedModule } from "@client/app/shared/shared.module"; +import { AuthRoutingModule } from "./auth-routing.module"; + +import { LoginComponent } from "./pages"; + +@NgModule({ + declarations: [LoginComponent], + imports: [SharedModule, AuthRoutingModule], +}) +export class AuthModule {} diff --git a/projects/client/src/app/feature/auth/pages/index.ts b/projects/client/src/app/feature/auth/pages/index.ts new file mode 100644 index 0000000..97961b0 --- /dev/null +++ b/projects/client/src/app/feature/auth/pages/index.ts @@ -0,0 +1 @@ +export * from "./login/login.component"; diff --git a/projects/client/src/app/feature/auth/pages/login/login.component.html b/projects/client/src/app/feature/auth/pages/login/login.component.html new file mode 100644 index 0000000..41adfc1 --- /dev/null +++ b/projects/client/src/app/feature/auth/pages/login/login.component.html @@ -0,0 +1,57 @@ +
+ +
+ + +
+ +
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/auth/pages/login/login.component.less b/projects/client/src/app/feature/auth/pages/login/login.component.less new file mode 100644 index 0000000..4505de9 --- /dev/null +++ b/projects/client/src/app/feature/auth/pages/login/login.component.less @@ -0,0 +1,23 @@ +.login { + width: 320px; + height: 404px; + h1 { + margin-bottom: 12px; + font-size: 40px; + font-weight: 400; + } + p { + font-size: 16px; + line-height: 24px; + letter-spacing: 0.23em; + text-shadow: 0px 8px 20px rgba(0, 0, 0, 0.1); + } + + form { + margin-top: 48px; + } + + .btn { + margin-top: 16px; + } +} diff --git a/projects/client/src/app/feature/auth/pages/login/login.component.ts b/projects/client/src/app/feature/auth/pages/login/login.component.ts new file mode 100644 index 0000000..bb10991 --- /dev/null +++ b/projects/client/src/app/feature/auth/pages/login/login.component.ts @@ -0,0 +1,50 @@ +import { Router } from "@angular/router"; +import { Component, Inject, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; +import { DecValidators } from "@cdk/validators"; +import { PUBLIC_PATH } from "@cdk/dec-module/base-href"; +import { AuthService } from "@client/app/core/services"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { finalize, lastValueFrom, tap } from "rxjs"; + +@Component({ + selector: "app-login", + templateUrl: "./login.component.html", + styleUrls: ["./login.component.less"], +}) +export class LoginComponent implements OnInit { + constructor( + @Inject(PUBLIC_PATH) public baseHref: string, + private msg: NzMessageService, + private api: AuthService, + private router: Router + ) {} + + public loginForm = new FormGroup({ + uid: new FormControl("", [DecValidators.required("请输入账户")]), + password: new FormControl("", [DecValidators.required("请输入密码")]), + }); + + public loading: boolean = false; + + system$ = this.api.getSystemInfo(); + + ngOnInit(): void {} + + async onLogin() { + if (Utils.validateFormGroup(this.loginForm)) { + const { value } = this.loginForm; + this.loading = true; + const res = await lastValueFrom( + this.api.login(value).pipe( + finalize(() => { + this.loading = false; + }) + ) + ); + this.msg.success(res.desc); + this.router.navigate(["/"]); + } + } +} diff --git a/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.html b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.html new file mode 100644 index 0000000..4683861 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.html @@ -0,0 +1,153 @@ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +    +    +    +    +    +    +    +    +    +    +    +    +    +    +    +    +    +    +   + #{{pole.zone}} + 开匝 + + + + + + + + + + + + + + + + + + + + + #{{pole.zone}}磁极 + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.less b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.less new file mode 100644 index 0000000..8c37bf2 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.less @@ -0,0 +1,204 @@ +:host { + display: block; + width: 100%; + height: 100%; + overflow: hidden; +} + +.circle { + display: block; + width: 400px; + height: 400px; + border: 3px solid #6e5ac9; + box-sizing: border-box; +} + +.inner-bg { + stroke: #183265; + stroke-width: 4px; +} + +.piepath { + .tooltip { + opacity: 0; + pointer-events: none; + } + path { + // stroke: #fff; + stroke-width: 4px; + fill: transparent; + position: relative; + opacity: 0.1; + &.selected { + stroke: #68bbe9; + opacity: 1; + // & + .textpath { + // display: block; + // } + } + + &:hover { + stroke: #68bbe9; + opacity: 0.6; + & + .tooltip { + opacity: 1; + } + } + } +} + +.center-img { + position: absolute; + top: 50%; + left: 50%; + z-index: 100; + width: 225px; + height: 225px; + transform: translate(-50%, -50%) scale(1.5); + border: 1px solid #2b529a; + border-radius: 50%; + // background-color: rgba(255, 255, 255, 0.05); + transform-origin: center; + pointer-events: none; + + img { + position: absolute; + top: 50%; + left: 50%; + + transform-origin: center; + + &:nth-child(1) { + transform: translate(-60%, -131%) rotate(-2deg); + } + &:nth-child(2) { + transform: translate(31%, -127%) rotate(18deg); + } + &:nth-child(3) { + transform: translate(114%, -115%) rotate(36deg); + } + &:nth-child(4) { + transform: translate(180%, -96%) rotate(54deg); + } + &:nth-child(5) { + transform: translate(219%, -73%) rotate(72deg); + } + &:nth-child(6) { + transform: translate(232%, -47%) rotate(90deg); + } + &:nth-child(7) { + transform: translate(217%, -21%) rotate(108deg); + } + &:nth-child(8) { + transform: translate(174%, 2%) rotate(126deg); + } + &:nth-child(9) { + transform: translate(109%, 20%) rotate(144deg); + } + &:nth-child(10) { + transform: translate(30%, 31%) rotate(162deg); + } + &:nth-child(11) { + transform: translate(-57%, 35%) rotate(180deg); + } + &:nth-child(12) { + transform: translate(-147%, 31%) rotate(196deg); + } + &:nth-child(13) { + transform: translate(-228%, 20%) rotate(214deg); + } + &:nth-child(14) { + transform: translate(-295%, 3%) rotate(232deg); + } + &:nth-child(15) { + transform: translate(-336%, -20%) rotate(250deg); + } + &:nth-child(16) { + transform: translate(-352%, -45%) rotate(268deg); + } + &:nth-child(17) { + transform: translate(-340%, -71%) rotate(286deg); + } + &:nth-child(18) { + transform: translate(-298%, -95%) rotate(304deg); + } + &:nth-child(19) { + transform: translate(-234%, -114%) rotate(322deg); + } + &:nth-child(20) { + transform: translate(-154%, -126%) rotate(343deg); + } + } +} + +.box { + width: 500px; + height: 500px; + margin: 0 auto; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + position: relative; + z-index: 10; + + .polygons { + pointer-events: none; + path { + stroke: rgba(255, 255, 255, 0.85); + stroke-width: 2px; + fill: rgba(255, 255, 255, 0.45); + } + } + + svg { + display: block; + // border: 1px solid red; + transition: transform 0.3s; + transform-origin: center; + position: relative; + z-index: 10; + text { + font-size: 30px; + } + } + + .action { + position: absolute; + bottom: 20px; + right: 20px; + button { + margin: 6px; + } + } +} +.lines { + .alarm { + stroke: var(--red-1) !important; + } +} +.points { + circle { + fill: #fff; + &.alarm { + fill: var(--red-1); + } + } +} + +.textpath { + pointer-events: none; + path { + stroke: none; + fill: none; + } +} + +.center { + fill: linear-gradient(to right, red, yellow); + opacity: 0.99; +} + +.text { + fill: #5eb7e8; +} diff --git a/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.ts b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.ts new file mode 100644 index 0000000..8537ff7 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/detection-graphics/detection-graphics.component.ts @@ -0,0 +1,375 @@ +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + EventEmitter, + HostListener, + Input, + OnChanges, + OnDestroy, + OnInit, + Output, + Renderer2, + SimpleChanges, + ViewChild, +} from "@angular/core"; +import { PoleItemDTO } from "@client/dtos"; +import { BehaviorSubject } from "rxjs"; + +class PathLine { + constructor(public cx: number, public cy: number, public r: number, public dr: number = 0) {} + x0: number = 0; + y0: number = 0; + x1: number = 0; + y1: number = 0; + angle: number = 0; +} + +class Point { + constructor(public x: number, public y: number, public r: number = 10) {} +} + +interface Pie { + piePath: string; + textPath: string; + polygons: [path: string, path: string]; + points: [Point, Point, Point, Point, Point, Point, Point, Point]; +} + +export type PoleGroupInterface = { + zone: number; + pole: PoleItemDTO; + bolt: Array; + line: Array; +}; + +const createDefaultPole = (idx: number) => { + return { + zone: idx + 1, + pole: { + alarm: false, + img: "img1.jpg", + position: 1, + type: "pole", + value: 0, + zone: 1, + }, + line: Array.from({ length: 2 }, (_, i) => { + return { + alarm: false, + img: "img1.jpg", + position: i + 1, + type: "line", + value: 0, + zone: idx, + }; + }), + bolt: Array.from({ length: 8 }, (_, i) => { + return { + alarm: false, + img: "img1.jpg", + position: i + 1, + type: "bolt", + value: 0, + zone: idx, + }; + }), + } as PoleGroupInterface; +}; + +@Component({ + selector: "app-detection-graphics", + templateUrl: "./detection-graphics.component.html", + styleUrls: ["./detection-graphics.component.less"], +}) +export class DetectionGraphicsComponent implements OnDestroy, OnInit, AfterViewInit, OnChanges { + constructor(private rd2: Renderer2, private cdr: ChangeDetectorRef) {} + + @Input() props$!: BehaviorSubject<{ poles: Array }>; + + @Input() public selectedZone?: number; + + poleNum: number = 0; + + @Output() onPoleSelect = new EventEmitter(); + + @ViewChild("wapper") wapper!: ElementRef; + + @ViewChild("box") box!: ElementRef; + + @ViewChild("centerImage") centerImage!: ElementRef; + + public poles: Array = []; + + public size: number = 800; + + public d: string = ""; + + public pies: Pie[] = []; + + public rd = Math.ceil(Math.random() * 10); + + public scale: number = 1; + + public borderPath = ""; + + public RATIO = 1; + + private isDragging = false; + + private startX = 0; + + private startY = 0; + + private translateX = 0; + + private translateY = 0; + + private readonly MIN_SCALE = 1; + + private readonly MAX_SCALE = 2.5; + + ngOnChanges(changes: SimpleChanges): void {} + + ngOnInit(): void { + this.RATIO = this.size / 800; + this.drawBorderPath(); + + this.props$.subscribe((r) => { + // console.log('graphics-poles', r) + if (r.poles.length > 0) { + this.poles = r.poles; + this.poleNum = r.poles.length; + this.createPie(); + } + }); + } + + ngAfterViewInit(): void { + this.dragMove(); + this.setBoxSize(); + } + + ngOnDestroy(): void { + this.wapper?.nativeElement.removeEventListener("mousedown", this.onMouseDown); + this.box?.nativeElement.removeEventListener("mousemove", this.onMouseMove); + document.removeEventListener("mouseup", this.onMouseUp); + } + + onSelect(poleZone: number) { + // this.selectedZone = poleZone; + this.onPoleSelect.emit(poleZone); + } + + drawBorderPath() { + const { RATIO } = this; + + const d1 = 700 * RATIO; + const d2 = 60 * RATIO; + const d3 = 10 * RATIO; + const d4 = 900 * RATIO; + const d5 = 720 * RATIO; + + const d7 = 1540 * RATIO; + const d8 = 1590 * RATIO; + + this.borderPath = `M${d1},${d2} L${d1},${d3} L${d4},${d3} L${d4},${d2} + A ${d5} ${d5} 0 0 1 ${d7} ${d1} + L${d8},${d1} L${d8},${d4} L${d7},${d4} + A ${d5} ${d5} 0 0 1 ${d4} ${d7} + L${d4},${d8} L${d1},${d8} L${d1},${d7} + A ${d5} ${d5} 0 0 1 ${d2} ${d4} + L${d3},${d4} L${d3},${d1} L${d2},${d1} + A ${d5} ${d5} 0 0 1 ${d1} ${d2}`; + } + + createPie() { + const { size, RATIO, poleNum } = this; + + const cx = size; + const cy = size; + const radius = size - 80 * RATIO; + + const pie = new PathLine(cx, cy, radius); + + const polygon1_1 = new PathLine(cx, cy, 710 * RATIO, 0.6 * RATIO); + const polygon1_2 = new PathLine(cx, cy, 675 * RATIO, 0.7 * RATIO); + const polygon2_1 = new PathLine(cx, cy, 660 * RATIO, 0.7 * RATIO); + const polygon2_2 = new PathLine(cx, cy, 625 * RATIO, 0.75 * RATIO); + + const dot1 = new PathLine(cx, cy, 700 * RATIO, 1.3 * RATIO); + const dot2 = new PathLine(cx, cy, 685 * RATIO, 1.4 * RATIO); + const dot3 = new PathLine(cx, cy, 650 * RATIO, 1.3 * RATIO); + const dot4 = new PathLine(cx, cy, 635 * RATIO, 1.4 * RATIO); + + let sweep = 0; + + if ((1 / poleNum) * 360 > 180) { + sweep = 1; + } + this.pies = Array.from({ length: this.poleNum }, (_, idx) => { + this.calcPos(pie, idx); + + this.calcPos(polygon1_1, idx); + this.calcPos(polygon1_2, idx); + this.calcPos(polygon2_1, idx); + this.calcPos(polygon2_2, idx); + + this.calcPos(dot1, idx); + this.calcPos(dot2, idx); + this.calcPos(dot3, idx); + this.calcPos(dot4, idx); + + const dotSize = 4 * RATIO; + + // this.poles.push(createDefaultPole(idx)); + + return { + textPath: `M ${cx} ${cy},L ${pie.x0} ${pie.y0}`, + piePath: `M ${cx} ${cy},L ${pie.x0} ${pie.y0} A ${pie.r} ${pie.r} 0 ${sweep} 1 ${pie.x1} ${pie.y1} Z`, + polygons: [ + `M ${polygon1_1.x0} ${polygon1_1.y0} A ${polygon1_1.r} ${polygon1_1.r} 0 ${sweep} 1 ${polygon1_1.x1} ${polygon1_1.y1} L ${polygon1_2.x1} ${polygon1_2.y1} A ${polygon1_2.r} ${polygon1_2.r} 0 ${sweep} 0 ${polygon1_2.x0} ${polygon1_2.y0} Z`, + `M ${polygon2_1.x0} ${polygon2_1.y0} A ${polygon2_1.r} ${polygon2_1.r} 0 ${sweep} 1 ${polygon2_1.x1} ${polygon2_1.y1} L ${polygon2_2.x1} ${polygon2_2.y1} A ${polygon2_2.r} ${polygon2_2.r} 0 ${sweep} 0 ${polygon2_2.x0} ${polygon2_2.y0} Z`, + ], + dots: [dot1, dot2, dot3, dot4], + points: [ + new Point(dot1.x0, dot1.y0, dotSize), + new Point(dot1.x1, dot1.y1, dotSize), + new Point(dot2.x0, dot2.y0, dotSize), + new Point(dot2.x1, dot2.y1, dotSize), + new Point(dot3.x0, dot3.y0, dotSize), + new Point(dot3.x1, dot3.y1, dotSize), + new Point(dot4.x0, dot4.y0, dotSize), + new Point(dot4.x1, dot4.y1, dotSize), + ], + }; + }); + } + + calcPos(line: PathLine, idx: number): PathLine { + const { poleNum } = this; + const n = poleNum; + let { cx, cy, dr, r } = line; + let currentIndex = 0; + currentIndex = idx + 1; + if (idx === 0) { + line.x0 = cx + r * Math.cos((dr * Math.PI) / 180); + line.y0 = cy + r * Math.sin((dr * Math.PI) / 180); + line.angle = (currentIndex / n) * 360; + line.x1 = cx + r * Math.cos(((line.angle - dr) * Math.PI) / 180); + line.y1 = cy + r * Math.sin(((line.angle - dr) * Math.PI) / 180); + } else if (idx > 0 && idx < n - 1) { + line.x0 = cx + r * Math.cos(((line.angle + dr) * Math.PI) / 180); + line.y0 = cy + r * Math.sin(((line.angle + dr) * Math.PI) / 180); + line.angle = (currentIndex / n) * 360; + line.x1 = cx + r * Math.cos(((line.angle - dr) * Math.PI) / 180); + line.y1 = cy + r * Math.sin(((line.angle - dr) * Math.PI) / 180); + } else { + line.x0 = cx + r * Math.cos(((line.angle + dr) * Math.PI) / 180); + line.y0 = cy + r * Math.sin(((line.angle + dr) * Math.PI) / 180); + line.x1 = cx + r * Math.cos((-dr * Math.PI) / 180); + line.y1 = cy + r * Math.sin((-dr * Math.PI) / 180); + } + return line; + } + + // getPole(idx: number): PoleGroupInterface { + + // console.log("defaultPole", defaultPole); + // return defaultPole as PoleGroupInterface; + // } + + handleNumber(m: number) { + const n = 250; + if (m < -n) { + return -n; + } else if (m > n) { + return n; + } else { + return m; + } + } + + onMouseDown = (event: MouseEvent) => { + event.preventDefault(); + this.isDragging = true; + this.startX = event.clientX - this.translateX; + this.startY = event.clientY - this.translateY; + }; + + onMouseUp = () => { + this.isDragging = false; + }; + + onMouseMove = (event: MouseEvent) => { + if (this.isDragging) { + event.preventDefault(); + let x = event.clientX - this.startX; + let y = event.clientY - this.startY; + + this.translateX = this.handleNumber(x); + this.translateY = this.handleNumber(y); + this.modifyTransform(); + } + }; + + dragMove() { + this.wapper.nativeElement.addEventListener("mousedown", this.onMouseDown); + this.box.nativeElement.addEventListener("mousemove", this.onMouseMove); + document.addEventListener("mouseup", this.onMouseUp); + } + + @HostListener("window:resize") + onResize() { + this.setBoxSize(); + } + + onMouseWheel(event: WheelEvent): void { + event.preventDefault(); + const scaleChange = -event.deltaY / 2000; + this.scale += scaleChange; + if (this.scale < this.MIN_SCALE) { + this.scale = this.MIN_SCALE; + } else if (this.scale > this.MAX_SCALE) { + this.scale = this.MAX_SCALE; + } + + this.modifyTransform(); + } + + modifyTransform() { + this.rd2.setStyle( + this.box.nativeElement, + "transform", + `scale(${this.scale}) translate(${this.translateX}px, ${this.translateY}px)` + ); + } + + setBoxSize() { + if (this.wapper.nativeElement) { + setTimeout(() => { + const { width, height } = this.wapper.nativeElement.getBoundingClientRect(); + const min = Math.min(width, height); + const svg = this.box.nativeElement.querySelector("svg"); + this.rd2.setStyle(this.box.nativeElement, "width", width + "px"); + this.rd2.setStyle(this.box.nativeElement, "height", height + "px"); + this.rd2.setStyle(svg, "width", min + "px"); + this.rd2.setStyle(svg, "height", min + "px"); + const scale = min / (225 * 1.35); + this.rd2.setStyle(this.centerImage.nativeElement, "transform", `translate(-50%, -50%) scale(${scale})`); + }, 70); + } + } + + onScale(sc: number) { + this.scale = this.scale + sc; + } + + onScroll(event: any) { + event.preventDefault(); + const delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail)); + const zoom = delta > 0 ? 1.1 : 0.9; // 缩放系数 + this.scale *= zoom; + } +} diff --git a/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.html b/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.html new file mode 100644 index 0000000..96ee28b --- /dev/null +++ b/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.html @@ -0,0 +1,4 @@ + + {{value.value}} + +- \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.less b/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.ts b/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.ts new file mode 100644 index 0000000..59eaad0 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/detection-value/detection-value.component.ts @@ -0,0 +1,12 @@ +import { Component, Input } from "@angular/core"; + +@Component({ + selector: "app-detection-value", + templateUrl: "./detection-value.component.html", + styleUrls: ["./detection-value.component.less"], +}) +export class DetectionValueComponent { + constructor() {} + + @Input() value?: { alarm: boolean; value: number }; +} diff --git a/projects/client/src/app/feature/detection/components/device-table/device-table.component.html b/projects/client/src/app/feature/detection/components/device-table/device-table.component.html new file mode 100644 index 0000000..ad1033a --- /dev/null +++ b/projects/client/src/app/feature/detection/components/device-table/device-table.component.html @@ -0,0 +1,47 @@ +
+
+ + + + + + + + +
+
+ + + + +
+
+ + + + + + + 机组/检测点/设备 + + + + + + + + {{currentSelectedGroupName}}/{{currentSelectedPoint?.name}}/{{data.name}} + + + + \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/device-table/device-table.component.less b/projects/client/src/app/feature/detection/components/device-table/device-table.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/device-table/device-table.component.ts b/projects/client/src/app/feature/detection/components/device-table/device-table.component.ts new file mode 100644 index 0000000..626e226 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/device-table/device-table.component.ts @@ -0,0 +1,133 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { AnyObject } from "@cdk/types"; +import { DetectionApiService } from "@client/app/core/services"; +import { PointDTO, PointGroupDTO, DeviceDTO } from "@client/dtos"; +import { NzMessageService } from "ng-zorro-antd/message"; + +@Component({ + selector: "app-device-table", + templateUrl: "./device-table.component.html", + styleUrls: ["./device-table.component.less"], +}) +export class DeviceTableComponent implements OnInit { + constructor(private api: DetectionApiService, private msg: NzMessageService) {} + + @Input() currentSelected: { id: string; name: string }[] = []; + + @Input() otherSelected: { id: string; name: string }[] = []; + + checked = false; + + loading = false; + + indeterminate = false; + + groups: PointGroupDTO[] = []; + + gid: string = ""; + + pid: string = ""; + + points: PointDTO[] = []; + + currentPointList: PointDTO[] = []; + + listOfData: DeviceDTO[] = []; + + listOfCurrentPageData: readonly any[] = []; + + setOfCheckedId = new Set(); + + setOfDataFromServer: AnyObject[] = []; + + public get selectedDevice(): AnyObject[] { + return this.setOfDataFromServer.filter((f) => this.setOfCheckedId.has(f["id"])); + } + + public get currentSelectedGroupName(): string { + return this.groups.find((f) => f.motorGroupId === this.gid)?.name ?? ""; + } + + public get currentSelectedPoint(): PointDTO | undefined { + return this.points.find((f) => f.pointId === this.pid); + } + + ngOnInit(): void { + this.currentSelected?.forEach((p) => { + this.updateCheckedSet(p.id, true); + }); + this.api.getFlatPoints().subscribe(({ points, groups }) => { + this.groups = groups; + this.points = points; + }); + } + + onReset() { + this.gid = ""; + this.onSearch(); + } + + onSearch() { + if (!this.pid) { + this.msg.error("请选择检测点"); + return; + } + + this.api.getDeviceListByPointId(this.pid).subscribe((res) => { + console.log("this.otherSelected", this.otherSelected); + if (Array.isArray(res.body)) { + this.listOfData = res.body.map((i) => { + return { + ...i, + id: i.deviceId, + disabled: !!this.otherSelected.find((f) => f.id === i.deviceId), + }; + }); + } else { + this.listOfData = []; + } + this.listOfData.forEach((i) => { + if (!this.setOfDataFromServer.some((s) => s["id"] === i["id"])) { + this.setOfDataFromServer.push(i); + } + }); + this.refreshCheckedStatus(); + }); + } + + onGroupChange(gid: string) { + this.currentPointList = this.groups.find((f) => f.motorGroupId === gid)?.pointList ?? []; + this.pid = ""; + } + + updateCheckedSet(id: string, checked: boolean): void { + if (checked) { + this.setOfCheckedId.add(id); + } else { + this.setOfCheckedId.delete(id); + } + } + + onCurrentPageDataChange(listOfCurrentPageData: readonly any[]): void { + this.listOfCurrentPageData = listOfCurrentPageData; + this.refreshCheckedStatus(); + } + + refreshCheckedStatus(): void { + const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled); + this.checked = listOfEnabledData.length > 0 && listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id)); + this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked; + } + + onItemChecked(id: string, checked: boolean): void { + this.updateCheckedSet(id, checked); + this.refreshCheckedStatus(); + } + + onAllChecked(checked: boolean): void { + this.listOfCurrentPageData + .filter(({ disabled }) => !disabled) + .forEach(({ id }) => this.updateCheckedSet(id, checked)); + this.refreshCheckedStatus(); + } +} diff --git a/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.html b/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.html new file mode 100644 index 0000000..a753299 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.html @@ -0,0 +1,4 @@ +
+ +

你没有此页面的访问权限。

+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.less b/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.ts b/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.ts new file mode 100644 index 0000000..3bdfe40 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/forbidden/forbidden.component.ts @@ -0,0 +1,14 @@ +import { ActivatedRoute, Router } from "@angular/router"; +import { Component, OnInit } from "@angular/core"; +import { NgxPermissionsService } from "ngx-permissions"; + +@Component({ + selector: "app-forbidden", + templateUrl: "./forbidden.component.html", + styleUrls: ["./forbidden.component.less"], +}) +export class ForbiddenComponent implements OnInit { + constructor(private perm: NgxPermissionsService, private router: Router, private route: ActivatedRoute) {} + + async ngOnInit() {} +} diff --git a/projects/client/src/app/feature/detection/components/home/home.component.html b/projects/client/src/app/feature/detection/components/home/home.component.html new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/home/home.component.less b/projects/client/src/app/feature/detection/components/home/home.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/home/home.component.ts b/projects/client/src/app/feature/detection/components/home/home.component.ts new file mode 100644 index 0000000..696b12f --- /dev/null +++ b/projects/client/src/app/feature/detection/components/home/home.component.ts @@ -0,0 +1,34 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { NgxPermissionsService } from "ngx-permissions"; + +@Component({ + selector: "app-home", + templateUrl: "./home.component.html", + styleUrls: ["./home.component.less"], +}) +export class HomeComponent { + constructor(private perm: NgxPermissionsService, private router: Router, private route: ActivatedRoute) {} + + async ngOnInit() { + let children = this.route.parent?.routeConfig?.children; + const { from } = this.route.snapshot.queryParams; + if (Array.isArray(children)) { + if (from) { + children = children.find((f) => f.path === from)?.children ?? []; + } + for (const child of children) { + if (child.path === this.route.routeConfig?.path) { + continue; + } + const only = child.data?.["permissions"]?.only; + if (Array.isArray(only)) { + if (await this.perm.hasPermission(only)) { + this.router.navigate(["/detection", from, child.path].filter(Boolean)); + break; + } + } + } + } + } +} diff --git a/projects/client/src/app/feature/detection/components/image-player/_image-player.component.ts b/projects/client/src/app/feature/detection/components/image-player/_image-player.component.ts new file mode 100644 index 0000000..1d85c08 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/image-player/_image-player.component.ts @@ -0,0 +1,129 @@ +// import { environment } from "@client/environments/environment"; +// import { Component, Inject, Input, OnDestroy, OnInit } from "@angular/core"; +// import { BehaviorSubject, forkJoin, interval, lastValueFrom, Subject, Subscription } from "rxjs"; +// import { filter, takeUntil } from "rxjs/operators"; +// import { NzImageService } from "ng-zorro-antd/image"; +// import { UtilsService } from "@client/app/core/services"; + +// export interface ImageObj { +// jobId: string; +// img: string; +// } + +// @Component({ +// selector: "app-image-player", +// templateUrl: "./image-player.component.html", +// styleUrls: ["./image-player.component.less"], +// }) +// export class ImagePlayerComponent implements OnInit, OnDestroy { +// constructor(private img: NzImageService, private util: UtilsService) {} + +// @Input() images$!: BehaviorSubject; + +// images: string[] = []; +// imageObjs: ImageObj[] = []; + +// environment = environment; + +// subs$?: Subscription; + +// currentIndex = 0; + +// played = false; + +// fps: number = 1; + +// ngOnInit(): void { +// this.images$.subscribe(async (imgObjs) => { +// for (let i = 0; i < imgObjs.length; i++) { +// const o = imgObjs[i]; +// // if (i < 10) { +// // const res = await lastValueFrom(this.util.loadImage(o.jobId, o.img)); +// // this.imageObjs.push +// // this.images.push("data:image/png;base64," + res.body); +// // } +// this.imageObjs.push(o); +// } + +// this.initPlayImage(); +// }); +// } + +// ngOnDestroy(): void { +// this.currentIndex = 0; +// this.tempIndex = 0; +// this.played = false; +// this.subs$?.unsubscribe(); +// } + +// jumpTo(idx: number) { +// this.played = false; +// if (idx < 0 || idx > this.images.length - 1) { +// return; +// } +// this.currentIndex = idx; +// this.tempIndex = idx; +// } +// tempIndex = 0; +// initPlayImage() { +// this.subs$?.unsubscribe(); +// this.subs$ = interval(1000 / this.fps) +// .pipe( +// filter(() => { +// // return this.currentIndex === this.tempIndex; +// return true; +// }) +// ) +// .subscribe(async () => { +// if (this.played) { +// // this.tempIndex = this.currentIndex + 1; +// let targetImage = this.images[this.currentIndex]; + +// if (!targetImage) { +// const o = this.imageObjs[this.tempIndex]; +// const base64 = await lastValueFrom(this.util.loadImage(o.jobId, o.img)); +// targetImage = base64; +// this.images.push(base64); +// } + +// this.currentIndex++; + +// console.log("targetImage", targetImage); +// // if (!targetImage) { +// // this.currentIndex = this.images.length - 1; +// // this.tempIndex = this.currentIndex; +// // this.togglePaly(); +// // } else { +// // const bs = await this.util.loadImages(targetImage); +// // this.currentIndex++; +// // this.images[this.currentIndex] = bs; +// // } +// } else { +// this.subs$?.unsubscribe(); +// } +// }); +// } + +// togglePaly() { +// this.played = !this.played; +// if (this.played) { +// if (this.currentIndex === this.images.length - 1) { +// this.currentIndex = 0; +// this.tempIndex = 0; +// } +// this.initPlayImage(); +// } +// } + +// onFpsChange(fps: number) { +// this.fps = fps; +// this.initPlayImage(); +// } + +// showImg() { +// if (this.images.length > 0) { +// const imgRef = this.img.preview(this.images.map((src) => ({ src }))); +// imgRef.switchTo(this.currentIndex); +// } +// } +// } diff --git a/projects/client/src/app/feature/detection/components/image-player/image-player.component.html b/projects/client/src/app/feature/detection/components/image-player/image-player.component.html new file mode 100644 index 0000000..0230101 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/image-player/image-player.component.html @@ -0,0 +1,52 @@ +
+ + + + + +
+
+
+ + + + + + + +
+
+ + +
+
+ + +
    +
  • 1 FPS
  • +
  • 2 FPS
  • +
  • 3 FPS
  • +
  • 5 FPS
  • +
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/image-player/image-player.component.less b/projects/client/src/app/feature/detection/components/image-player/image-player.component.less new file mode 100644 index 0000000..9e162d4 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/image-player/image-player.component.less @@ -0,0 +1,44 @@ +:host { + display: flex; + height: 100%; + background-color: var(--black-10); + position: relative; +} + +.idx { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 60px; + color: #fff; +} + +.controls { + background-color: rgba(0, 0, 0, .25); + color: var(--text-color); + + ::ng-deep { + .ant-space-item { + margin-right: 0; + } + } + + button { + appearance: none; + border: none; + outline: none; + color: var(--text-color); + font-size: 20px; + background-color: transparent; + cursor: pointer; + } + + .fps { + appearance: none; + border: none; + border-radius: 2px; + background-color: var(--white-10); + font-size: 14px; + } +} \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/image-player/image-player.component.ts b/projects/client/src/app/feature/detection/components/image-player/image-player.component.ts new file mode 100644 index 0000000..7433ae3 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/image-player/image-player.component.ts @@ -0,0 +1,176 @@ +import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { AnyObject } from "@cdk/types"; +import { DetectionApiService, UtilsService } from "@client/app/core/services"; +import { NzImageService } from "ng-zorro-antd/image"; +import { + BehaviorSubject, + Subject, + Subscription, + interval, + lastValueFrom, + switchMap, + takeUntil, + takeWhile, + tap, +} from "rxjs"; + +export interface ImageObj { + jobId: string; + img: string; +} + +@Component({ + selector: "app-image-player", + templateUrl: "./image-player.component.html", + styleUrls: ["./image-player.component.less"], +}) +export class ImagePlayerComponent implements OnInit { + constructor(private nzImg: NzImageService, private api: DetectionApiService) {} + + @Input() props$!: BehaviorSubject; + + images: ({ url: string; loaded: boolean } & Partial)[] = []; + + currentIndex = -1; + + autoPlay = false; + + fps = 5; + + private destroy$ = new Subject(); + + private trigger$ = new Subject(); + + private subs$?: Subscription; + + ngOnInit(): void { + const { origin } = window.location; + this.props$.subscribe((imgs) => { + if (imgs.length === 0) { + return; + } + // console.log("imgs", imgs); + this.api.getImageBaseUrl().subscribe((baseUrl) => { + imgs.forEach((item) => { + const url = `${origin}${baseUrl}${item.jobId}/detect/${item.img}`; + this.images.push({ url, loaded: false, ...item }); + }); + if (this.currentIndex < 0 && this.images.length > 0) { + this.jumpTo(0); + } + }); + }); + } + + reset() { + this.images = []; + this.currentIndex = -1; + } + + destroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + ngOnDestroy() { + this.destroy(); + } + + togglePlay() { + this.autoPlay = !this.autoPlay; + if (this.autoPlay && this.currentIndex === this.images.length - 1) { + this.currentIndex = 0; + } + if (this.images.length === 0) { + this.autoPlay = false; + } + + if (this.autoPlay) { + this.subs$?.unsubscribe(); + this.subs$ = this.trigger$ + .pipe( + switchMap(() => interval(1000 / this.fps)), + takeUntil(this.destroy$), + takeWhile(() => this.autoPlay), + tap((i) => { + // console.log(i); + }) + ) + + .subscribe(() => { + this.jumpTo(this.currentIndex + 1); + // console.log("played"); + }); + + this.trigger$.next(); + } + } + + async jumpTo(idx: number) { + // console.log("idx", idx); + if (idx < 0 || idx > this.images.length - 1) { + return; + } + const image = this.images[idx]; + if (!image.loaded) { + // await this.loadBase64(image as ImageObj); + await this.loadImage(image); + } + this.currentIndex = idx; + + if (this.autoPlay && this.currentIndex === this.images.length - 1) { + this.togglePlay(); + } + } + + async loadBase64(item: ImageObj & AnyObject) { + const base64 = await lastValueFrom(this.api.loadImage(item.jobId, item.img)); + item["loaded"] = true; + item["url"] = base64; + } + + loadImage(image: { url: string; loaded: boolean }) { + return new Promise((r, j) => { + if (!image.loaded) { + const img = new Image(); + img.src = image.url; + img.onload = () => { + image.loaded = true; + r(image); + }; + } else { + r(image); + } + }); + } + + onFpsChange(fps: number) { + this.fps = fps; + this.trigger$.next(); + // this.initPlayImage(); + } + + showImg() { + if (this.images.length > 0) { + this.togglePlay(); + const imgRef = this.nzImg.preview(this.images.map((img) => ({ src: img.url }))); + imgRef.switchTo(this.currentIndex); + } + } + + preLoad() { + this.images.forEach((image) => { + if (!image.loaded) { + const img = new Image(); + img.src = image.url; + img.onload = () => { + image.loaded = true; + }; + } + }); + + if (this.currentIndex < 0) { + this.currentIndex = 0; + } + } +} diff --git a/projects/client/src/app/feature/detection/components/index.ts b/projects/client/src/app/feature/detection/components/index.ts new file mode 100644 index 0000000..61979e5 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/index.ts @@ -0,0 +1,10 @@ +export * from "./detection-graphics/detection-graphics.component"; +export * from "./image-player/image-player.component"; +export * from "./point-status/point-status.component"; +export * from "./detection-value/detection-value.component"; +export * from "./point-table/point-table.component"; +export * from "./device-table/device-table.component"; + +export * from "./home/home.component"; +export * from "./forbidden/forbidden.component"; +export * from "./notfound/notfound.component"; diff --git a/projects/client/src/app/feature/detection/components/notfound/notfound.component.html b/projects/client/src/app/feature/detection/components/notfound/notfound.component.html new file mode 100644 index 0000000..df4b62f --- /dev/null +++ b/projects/client/src/app/feature/detection/components/notfound/notfound.component.html @@ -0,0 +1,6 @@ +
+ +

+ 此页面未找到。 +

+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/notfound/notfound.component.less b/projects/client/src/app/feature/detection/components/notfound/notfound.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/notfound/notfound.component.ts b/projects/client/src/app/feature/detection/components/notfound/notfound.component.ts new file mode 100644 index 0000000..0368db3 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/notfound/notfound.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-notfound', + templateUrl: './notfound.component.html', + styleUrls: ['./notfound.component.less'] +}) +export class NotfoundComponent { + +} diff --git a/projects/client/src/app/feature/detection/components/point-status/point-status.component.html b/projects/client/src/app/feature/detection/components/point-status/point-status.component.html new file mode 100644 index 0000000..be40b1e --- /dev/null +++ b/projects/client/src/app/feature/detection/components/point-status/point-status.component.html @@ -0,0 +1,29 @@ + + + + + + +
+ + + 异常 + + + + 掉线 + + + + 正常 + +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/point-status/point-status.component.less b/projects/client/src/app/feature/detection/components/point-status/point-status.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/point-status/point-status.component.ts b/projects/client/src/app/feature/detection/components/point-status/point-status.component.ts new file mode 100644 index 0000000..10437e6 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/point-status/point-status.component.ts @@ -0,0 +1,16 @@ +import { Component, Input, ViewEncapsulation } from "@angular/core"; +import { PointStatusEnum } from "@client/dtos"; + +@Component({ + selector: "app-point-status", + templateUrl: "./point-status.component.html", + styleUrls: ["./point-status.component.less"], + encapsulation: ViewEncapsulation.None, +}) +export class PointStatusComponent { + @Input() status: PointStatusEnum = PointStatusEnum.NORMAL; + + @Input() textVisible: boolean = false; + + PointStatusEnum = PointStatusEnum; +} diff --git a/projects/client/src/app/feature/detection/components/point-table/point-table.component.html b/projects/client/src/app/feature/detection/components/point-table/point-table.component.html new file mode 100644 index 0000000..a092d54 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/point-table/point-table.component.html @@ -0,0 +1,41 @@ +
+
+ + + +
+
+ + + + +
+
+ + + + + + + 机组/检测点 + + + + + + + + {{data.name}} + + + + \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/components/point-table/point-table.component.less b/projects/client/src/app/feature/detection/components/point-table/point-table.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/components/point-table/point-table.component.ts b/projects/client/src/app/feature/detection/components/point-table/point-table.component.ts new file mode 100644 index 0000000..53153c1 --- /dev/null +++ b/projects/client/src/app/feature/detection/components/point-table/point-table.component.ts @@ -0,0 +1,115 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { DetectionApiService } from "@client/app/core/services"; +import { PointDTO, PointGroupDTO } from "@client/dtos"; + +@Component({ + selector: "app-point-table", + templateUrl: "./point-table.component.html", + styleUrls: ["./point-table.component.less"], +}) +export class PointTableComponent implements OnInit { + constructor(private api: DetectionApiService) {} + + @Input() currentSelected: PointDTO[] = []; + + @Input() otherSelected: PointDTO[] = []; + + checked = false; + + loading = false; + + indeterminate = false; + + groups: PointGroupDTO[] = []; + + gid: string = ""; + + points: PointDTO[] = []; + + listOfData: PointDTO[] = []; + + listOfCurrentPageData: readonly any[] = []; + + setOfCheckedId = new Set(); + + arrOfChecked: PointDTO[] = []; + + ngOnInit(): void { + this.currentSelected?.forEach((p) => { + this.updateCheckedSet(p.pointId, true); + }); + this.api.getFlatPoints().subscribe(({ groups, points }) => { + points = points.map((p) => ({ ...p, disabled: this.otherSelected.some((s) => s.pointId === p.pointId) })); + this.points = points; + this.listOfData = points; + this.groups = groups; + this.refreshCheckedStatus(); + }); + // this.api.getAllPoint().subscribe((p) => { + // const groups = p?.[0]?.groupList; + // const points: PointDTO[] = []; + // console.log("this.currentSelected", this.currentSelected, this.otherSelected); + // if (groups) { + // this.groups = groups; + // groups.forEach((g) => { + // points.push( + // ...g.pointList.map((p) => ({ + // ...p, + // gid: g.motorGroupId, + // gname: g.name, + // })) + // ); + // }); + // this.points = points; + // this.listOfData = points; + // this.refreshCheckedStatus(); + // } + // }); + } + + updateCheckedSet(id: string, checked: boolean): void { + if (checked) { + this.setOfCheckedId.add(id); + } else { + this.setOfCheckedId.delete(id); + } + this.arrOfChecked = this.points.filter((f) => this.setOfCheckedId.has(f.pointId)); + } + + onCurrentPageDataChange(listOfCurrentPageData: readonly any[]): void { + this.listOfCurrentPageData = listOfCurrentPageData; + this.refreshCheckedStatus(); + } + + refreshCheckedStatus(): void { + const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled); + this.checked = + listOfEnabledData.length > 0 && listOfEnabledData.every(({ pointId }) => this.setOfCheckedId.has(pointId)); + this.indeterminate = listOfEnabledData.some(({ pointId }) => this.setOfCheckedId.has(pointId)) && !this.checked; + } + + onItemChecked(id: string, checked: boolean): void { + this.updateCheckedSet(id, checked); + this.refreshCheckedStatus(); + } + + onAllChecked(checked: boolean): void { + this.listOfCurrentPageData + .filter(({ disabled }) => !disabled) + .forEach(({ pointId }) => this.updateCheckedSet(pointId, checked)); + this.refreshCheckedStatus(); + } + + onReset() { + this.gid = ""; + this.onSearch(); + } + + onSearch() { + if (this.gid) { + this.listOfData = this.points.filter((f) => f["gid"] === this.gid); + } else { + this.listOfData = this.points; + } + } +} diff --git a/projects/client/src/app/feature/detection/detection-routing.module.ts b/projects/client/src/app/feature/detection/detection-routing.module.ts new file mode 100644 index 0000000..9ac474c --- /dev/null +++ b/projects/client/src/app/feature/detection/detection-routing.module.ts @@ -0,0 +1,156 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { AuthorizationLayoutComponent } from "@client/app/shared/components"; +import { + AnalysisComponent, + DetectionIndexComponent, + HistoryDetailComponent, + HistoryListComponent, + PointSettingComponent, + SettingsLayoutComponent, + AlgorithmSettingComponent, + TemperatureSettingComponent, + SystemSettingComponent, +} from "./pages"; +import { PermissionLoadGuard } from "@client/app/core/gaurd/permisson.guard"; +import { ForbiddenComponent, HomeComponent, NotfoundComponent } from "./components"; +import { NgxPermissionsGuard } from "ngx-permissions"; + +const routes: Routes = [ + { + path: "", + component: AuthorizationLayoutComponent, + canActivateChild: [PermissionLoadGuard], + children: [ + { + path: "", + pathMatch: "full", + redirectTo: "home", + }, + { + path: "home", + component: HomeComponent, + }, + { + path: "index", + component: DetectionIndexComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_pole"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "history", + component: HistoryListComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_history"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "history/:id", + component: HistoryDetailComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_history"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "analysis", + component: AnalysisComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_analysis"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "settings", + component: SettingsLayoutComponent, + canActivateChild: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_settings_show", "role_settings_bolt", "role_settings_temp", "role_settings_sys"], + redirectTo: "/detection/forbidden", + }, + }, + children: [ + { + path: "", + pathMatch: "full", + redirectTo: "/detection/home?from=settings", + }, + { + path: "point", + component: PointSettingComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_settings_show"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "algorithm", + component: AlgorithmSettingComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_settings_bolt"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "temperature", + component: TemperatureSettingComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_settings_temp"], + redirectTo: "/detection/forbidden", + }, + }, + }, + { + path: "system", + component: SystemSettingComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_settings_sys"], + redirectTo: "/detection/forbidden", + }, + }, + }, + ], + }, + { + path: "forbidden", + component: ForbiddenComponent, + }, + { + path: "**", + component: NotfoundComponent, + }, + ], + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class DetectionRoutingModule {} diff --git a/projects/client/src/app/feature/detection/detection.module.ts b/projects/client/src/app/feature/detection/detection.module.ts new file mode 100644 index 0000000..890025b --- /dev/null +++ b/projects/client/src/app/feature/detection/detection.module.ts @@ -0,0 +1,56 @@ +import { FormsModule } from "@angular/forms"; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { DetectionRoutingModule } from "./detection-routing.module"; +import { + DetectionGraphicsComponent, + ImagePlayerComponent, + PointStatusComponent, + DetectionValueComponent, + PointTableComponent, + DeviceTableComponent, + ForbiddenComponent, + NotfoundComponent, + HomeComponent, +} from "./components"; +import { + AnalysisComponent, + DetectionIndexComponent, + HistoryDetailComponent, + HistoryListComponent, + SettingsLayoutComponent, + PointSettingComponent, + AlgorithmSettingComponent, + TemperatureSettingComponent, + SystemSettingComponent, +} from "./pages"; +import { SharedModule } from "../../shared/shared.module"; + +const components = [ + DetectionGraphicsComponent, + ImagePlayerComponent, + PointStatusComponent, + DetectionValueComponent, + PointTableComponent, + DeviceTableComponent, + ForbiddenComponent, + NotfoundComponent, + HomeComponent, +]; +const pages = [ + AnalysisComponent, + DetectionIndexComponent, + HistoryDetailComponent, + HistoryListComponent, + SettingsLayoutComponent, + PointSettingComponent, + AlgorithmSettingComponent, + TemperatureSettingComponent, + SystemSettingComponent, +]; + +@NgModule({ + declarations: [...components, ...pages], + imports: [SharedModule, DetectionRoutingModule], +}) +export class DetectionModule {} diff --git a/projects/client/src/app/feature/detection/pages/analysis/analysis.component.html b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.html new file mode 100644 index 0000000..60a9963 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.html @@ -0,0 +1,94 @@ +
+
+ + +
+ +
+ + + +
+ +
+ + + + +
+ + +
+ + + + + + + +
+
+
+
+ + + + +
+ +
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/analysis/analysis.component.less b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.less new file mode 100644 index 0000000..8f64dc3 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.less @@ -0,0 +1,34 @@ +:host { + display: flex; + height: calc(100% - 1px); + flex-direction: column; + overflow-y: auto; +} + +.visible { + visibility: visible !important; +} +.analysis { + gap: 16px; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(2, 500px); + + & > div { + &:nth-child(1) { + grid-column: 1 / span 1; + grid-row: 1 / span 1; + } + &:nth-child(2) { + grid-column: 2 / span 1; + grid-row: 1 / span 1; + } + &:nth-child(3) { + grid-column: 1 / span 1; + grid-row: 2 / span 1; + } + &:nth-child(4) { + grid-column: 2 / span 1; + grid-row: 2 / span 1; + } + } +} diff --git a/projects/client/src/app/feature/detection/pages/analysis/analysis.component.ts b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.ts new file mode 100644 index 0000000..8eaca5f --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/analysis/analysis.component.ts @@ -0,0 +1,347 @@ +import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from "@angular/core"; +import { AnyObject } from "@cdk/types"; +import { DetectionApiService } from "@client/app/core/services"; +import { PoleItemDTO } from "@client/dtos"; +import { format } from "date-fns"; +import { init, EChartsType } from "echarts"; +import { NzCascaderOption } from "ng-zorro-antd/cascader"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { forkJoin } from "rxjs"; + +type QueryInterface = { + range: string[] | null; + pointId: null | string[]; + features: string[] | null; + zone: number | null; +}; + +const initQuery = { + range: null, + pointId: null, + features: null, + zone: null, +}; + +@Component({ + selector: "app-analysis", + templateUrl: "./analysis.component.html", + styleUrls: ["./analysis.component.less"], +}) +export class AnalysisComponent implements OnInit, AfterViewInit { + constructor(private api: DetectionApiService, private msg: NzMessageService) {} + + points: NzCascaderOption[] = []; + + features: Record = {}; + + query: QueryInterface = JSON.parse(JSON.stringify(initQuery)); + + prevSelectFeatures: string[] = []; + + poles: number[] = []; + + featureChartMap = new Map(); + + @ViewChild("chart1") line!: ElementRef; + + @ViewChild("chart2") bolt!: ElementRef; + + @ViewChild("chart3") pole!: ElementRef; + + @ViewChild("chart4") temperature!: ElementRef; + + echart_line?: EChartsType; + + echart_bolt?: EChartsType; + + echart_pole?: EChartsType; + + echart_temperature?: EChartsType; + + ngOnInit(): void { + this.forkjoinPointAndFeatures(); + } + + ngAfterViewInit(): void { + // if (this.chart1.nativeElement) { + // this.echart1 = this.createChart(this.chart1.nativeElement); + // } + // if (this.chart2.nativeElement) { + // this.echart2 = this.createChart(this.chart2.nativeElement); + // } + // if (this.chart3.nativeElement) { + // this.echart3 = this.createChart(this.chart3.nativeElement); + // } + // if (this.chart4.nativeElement) { + // this.echart4 = this.createChart(this.chart4.nativeElement); + // } + } + + onPointChange(point: Array) { + let poleNumbers = 0; + if (Array.isArray(point) && point.length === 2) { + const selectPoint = this.points.find((f) => f.value === point[0])?.children?.find((f) => f.value === point[1]); + poleNumbers = selectPoint?.["poleNum"] ?? 0; + + const pid = selectPoint?.["pointId"]; + if (pid) { + this.api.getFeatures(pid).subscribe((featureRes) => { + this.features = featureRes.body; + this.query.features = Object.keys(this.features); + setTimeout(() => { + this.getData(); + }, 70); + }); + } + } + this.poles = Array.from({ length: poleNumbers }, (_, idx) => idx + 1); + } + + forkjoinPointAndFeatures() { + forkJoin([this.api.getAllPoint()]).subscribe(([pointData]) => { + const stationGroups = pointData[0]; + this.points = stationGroups.groupList.map((g) => { + return { + label: g.name, + value: g.motorGroupId, + children: g.pointList.map((p) => { + return { + label: p.name, + value: p.pointId, + isLeaf: true, + ...p, + }; + }), + }; + }); + + this.query.pointId = [this.points[0].value, this.points[0]?.children?.[0]?.value]; + this.onPointChange(this.query.pointId); + this.query.zone = 1; + }); + } + + ngModelChange(v: any) {} + + getData() { + const { query } = this; + const q = Object.create(null); + Object.entries(query).forEach(([k, v]) => { + q[k] = v; + if (k === "range" && Array.isArray(v) && v.length === 2) { + const startTime = typeof v[0] === "string" ? v[0] : format(v[0], "yyyy-MM-dd"); + const endTime = typeof v[1] === "string" ? v[1] : format(v[1], "yyyy-MM-dd"); + q.startTime = startTime; + q.endTime = endTime; + } + if (k === "pointId" && Array.isArray(v) && v.length === 2) { + q.pointId = v[1]; + } + }); + if (!q.pointId) { + this.msg.error("请选择机组/监测点"); + return; + } + if (!q.features) { + this.msg.error("请选特征量"); + return; + } + this.prevSelectFeatures = q.features; + this.featureChartMap.clear(); + this.api.getAnalysisChartData(q).subscribe((res) => { + Object.entries(res.body).forEach(([category, data]) => { + let echartDataSet: AnyObject[] = []; + data.forEach((item) => { + let time = echartDataSet.find((f) => f["time"] === item["time"]); + if (time) { + time[item["position"]] = item.value; + } else { + echartDataSet.push({ time: item["time"], [item["position"]]: item.value }); + } + }); + this.featureChartMap.set(category, true); + this.createChart(category, echartDataSet); + }); + }); + } + + search() { + this.getData(); + } + + reset() { + this.query = JSON.parse(JSON.stringify(initQuery)); + } + + echartTitleMap = new Map([ + ["line", { left: "最高变化量:#-@mm", right: `最高变化量产生日期:@` }], + ["bolt", { left: "最大转动角度:#-@°", right: `最大转动角度产生日期:@` }], + ["pole", { left: "开匝磁极:#", right: `最多开匝磁极产生日期:@` }], + ["temperature", { left: "最高变化量:@℃", right: `最高变化量产生日期:@` }], + ]); + + findMaxValue(arr: AnyObject[]) { + arr.forEach((obj) => { + Object.entries(obj).forEach(([k, v], idx) => { + if (idx === 0) { + obj["value"] = v; + obj["valueIdx"] = k; + } + if (k !== "value" && v > obj["value"]) { + obj["value"] = v; + obj["valueIdx"] = k; + } + }); + + // obj["value"] = Math.max(...Object.values(obj).filter((f) => typeof f === "number")); + }); + return arr.reduce((max, current) => { + return current["value"] > max["value"] ? current : max; + }); + } + + createChart(category: string, data: AnyObject[]) { + console.log("category", category, data); + //@ts-expect-error + const el = this[category]; + const echartRef = "echart_" + category; + + if (el && el?.nativeElement) { + const div = el.nativeElement as HTMLDivElement; + //@ts-expect-error + const old: EChartsType = this[echartRef]; + if (old) { + old.dispose(); + } + + const echart = init(el.nativeElement, "dark"); + const dimensions = Object.keys(data[0]).filter((f) => f !== "time"); + //@ts-expect-error + this[echartRef] = echart; + + const txt = this.echartTitleMap.get(category)!; + const max = this.findMaxValue(data); + // console.log("max", max); + let text = [ + `{a|${txt.left.replace("#", "#" + max["valueIdx"]).replace("@", max["value"])}}`, + `{b|${txt.right.replace("@", max["time"])}}`, + ].join(""); + + echart.setOption({ + title: { + text, + show: !!max, + textStyle: { + width: div.clientWidth - 20, + fontWeight: "normal", + rich: { + a: { + fontSize: 14, + color: "#fff", + align: "left", + }, + b: { + align: "right", + color: "#fff", + fontSize: 14, + }, + }, + }, + }, + + backgroundColor: "transparent", + + tooltip: { + trigger: "axis", + axisPointer: { + type: "cross", + label: { + backgroundColor: "#6a7985", + }, + }, + }, + + legend: { + bottom: 0, + left: 0, + formatter: "{name} #", + }, + + dataset: { + dimensions: ["time", ...dimensions], + source: data, + }, + + grid: { + top: "12%", + left: "35", + right: "35", + bottom: "10%", + containLabel: true, + }, + + xAxis: [ + { + type: "category", + boundaryGap: false, + }, + ], + yAxis: [ + { + type: "value", + splitLine: { + show: true, + lineStyle: { + color: "rgba(255, 255, 255, 0.1)", + }, + }, + }, + ], + series: dimensions.reduce((a, c) => { + return a.concat({ + name: c, + type: "line", + areaStyle: { + opacity: "0.2", + }, + emphasis: { + focus: "series", + }, + }); + }, [] as AnyObject[]), + }); + } + } + + downloadChart(type: string) { + const echart = (this[`echart_${type}` as keyof this]); + console.log("type", type, echart); + if (!echart) { + return; + } + const base64String = echart.getDataURL(); + const filename = `image_${type}.png`; + const byteString = atob(base64String.split(",")[1]); + const mimeString = base64String.split(",")[0].split(":")[1].split(";")[0]; + const ab = new ArrayBuffer(byteString.length); + const ia = new Uint8Array(ab); + + for (let i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + const blob = new Blob([ab], { type: mimeString }); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.download = filename; + document.body.appendChild(link); + link.click(); + + setTimeout(() => { + document.body.removeChild(link); + URL.revokeObjectURL(url); + }, 0); + } +} diff --git a/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.html b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.html new file mode 100644 index 0000000..c81ca23 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.html @@ -0,0 +1,279 @@ + + + +
+
+ + + + +
+
+ + + + + + + + +
+
+ +
+
+

+ 监测点温度 +

+
+ + {{temperature ? (temperature + '℃') :'-'}} + +
+
+
+

+ 引出线变形 +

+
+
+ 最高变化量 +
+
+ {{maxLine.zone}}# - {{maxLine.value}}mm +
+
+
+
+

+ 螺栓松动 +

+
+
+ 最大转动角度 +
+
+ {{maxBolt.zone}}# - {{maxBolt.value}}° +
+
+
+
+

+ 磁极开匝 +

+
+
+ 最大磁极开匝 +
+
+ {{maxPole.zone}}# - {{maxPole.value}} +
+
+
+
+
+
+
+ +
+
+
+ 引出线变形 +
+ + + + + + + + + + + + + + + +
+ 编号 + + #1 + + #2 +
+ 偏移量(mm) + + + + +
+
+
+
+ 螺栓松动 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 编号 + + #1 + + #2 + + #3 + + #4 + + #5 + + #6 + + #7 + + #8 +
+ 偏移量(°) + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+ {{selectedZone?.zone}}#磁极 + + 磁极线圈{{selectedZone?.pole?.alarm ? '异常' : '正常'}} +
+
+
+
+ + + + + + + + + + + + + + + + +
+ 引出线变形 + + 检测正常 + + {{line}}#引出线异常 + +
+ 螺栓松动 + + 检测正常 + + + {{line}}#螺栓异常 + +
+ 磁极开匝 + + 检测正常 + + + {{line}}#磁极异常 + +
+
+
+
+ + + +
    +
  • +
    + + +
    + {{ group.name }} +
    +
    + +
    +
    +
      +
    • +
      + {{item.name}} +
      +
      + +
      +
    • +
    +
  • +
+ + +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.less b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.less new file mode 100644 index 0000000..ad72587 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.less @@ -0,0 +1,120 @@ +:host { + display: block; + height: 100%; +} + +.switch-btn { + position: absolute; + top: 28px; + right: 130px; +} + +.device-group { + user-select: none; + + .group-title, + .group-child>li { + cursor: pointer; + + &:hover, + &.active { + background-color: var(--white-10); + } + } +} + + + +.grid { + gap: 16px; + grid-template-columns: repeat(30, 1fr); + grid-template-rows: 44vh 174px auto; + + .pictures { + grid-column: 1 / span 15; + grid-row: 1 / span 1; + } + + .graphics { + grid-column: 16 / span 15; + grid-row: 1 / span 2; + + ::ng-deep { + .ant-card-body { + padding: 12px; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.032) 0%, rgba(255, 255, 255, 0.016) 100%); + overflow: hidden; + } + } + } + + .total { + grid-column: 1 / span 15; + grid-row: 2 / span 1; + + b { + font-size: 24px; + font-weight: 400; + } + } + + .selected { + grid-column: 1 / span 15; + grid-row: 3 / span 1; + + table { + display: table; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + + th { + color: var(--purple); + } + + td, + th { + @apply p-2; + border: 1px solid var(--border-color); + + &:first-child { + width: 120px; + } + } + } + } + + .result { + grid-column: 16 / span 15; + grid-row: 3 / span 1; + + &-table { + td { + @apply text-base py-2; + + &:first-child { + width: 120px; + color: var(--purple); + } + } + } + } + + ::ng-deep { + nz-card { + height: 100%; + display: flex; + flex-direction: column; + + .ant-card-body { + flex: 1; + } + } + } +} + +.result-table { + td { + vertical-align: top; + } +} \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.ts b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.ts new file mode 100644 index 0000000..ad103f6 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/detection-index/detection-index.component.ts @@ -0,0 +1,459 @@ +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + OnInit, + Renderer2, + TemplateRef, + ViewChild, +} from "@angular/core"; +import { BehaviorSubject, lastValueFrom, Subject, takeUntil } from "rxjs"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { DetectionApiService, WebsocketApiService } from "@client/app/core/services"; +import { PointDTO, PointStatusEnum, PoleItemDTO, PoleQueryDTO, PowerStationDTO } from "@client/dtos"; +import { DecText } from "@cdk/types"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { PoleGroupInterface } from "../../components"; +import { ImageObj, ImagePlayerComponent } from "../../components/image-player/image-player.component"; +import { WebSocketSubject } from "rxjs/webSocket"; + +function createDefaultData(len: number): PoleQueryDTO { + let res: PoleQueryDTO = {}; + Array.from({ length: len }, (_, idx) => { + let zone = idx + 1; + res[zone] = [ + { + type: "bolt", + zone: zone, + position: 1, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 2, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 3, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 4, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 5, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 6, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 7, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "bolt", + zone: zone, + position: 8, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "line", + zone: zone, + position: 1, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "line", + zone: zone, + position: 2, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "pole", + zone: zone, + position: 1, + img: "img1.jpg", + value: 0, + alarm: false, + }, + { + type: "temperature", + zone: zone, + position: 1, + img: "-", + value: 0, + alarm: false, + }, + ]; + }); + + return res; +} + +@Component({ + selector: "app-detection-index", + templateUrl: "./detection-index.component.html", + styleUrls: ["./detection-index.component.less"], +}) +export class DetectionIndexComponent implements OnInit, OnDestroy { + constructor( + private msg: NzMessageService, + private modal: NzModalService, + private api: DetectionApiService, + private ws: WebsocketApiService + ) {} + + unsubscribe$ = new Subject(); + + graphicsProps$ = new BehaviorSubject<{ poles: Array }>({ poles: [] }); + + ws$?: WebSocketSubject; + + images$ = new BehaviorSubject([]); + + @ViewChild(ImagePlayerComponent) imgplayerRef!: ImagePlayerComponent; + + PointStatusEnum = PointStatusEnum; + + allPoint: PowerStationDTO[] = []; + + tempSelectedPoint: PointDTO | null = null; + + selectedPoint: PointDTO | null = null; + + selectedZone?: PoleGroupInterface; + + images: { [PoleZone: number]: ImageObj[] } = {}; + + currentImage: string = ""; + + temperature: string = "-"; + + originaPoleQueryData: PoleQueryDTO = {}; + + poles: PoleGroupInterface[] = []; + + jobId?: string; + + maxLine: { zone: number; value: number } = { zone: 1, value: 0 }; + + maxBolt: { zone: number; value: number } = { zone: 1, value: 0 }; + + maxPole: { zone: number; value: number } = { zone: 1, value: 0 }; + + lineAlarmZones: number[] = []; + + boltAlarmZones: number[] = []; + + poleAlarmZones: number[] = []; + + ngOnInit(): void { + this.connectWs(); + this.getAllPoint(); + } + + ngOnDestroy(): void { + this.unsubscribe$.next(); + this.unsubscribe$.complete(); + } + + connectWs() { + this.ws$ = this.ws.connect("/websocket/amind"); + this.ws$.pipe(takeUntil(this.unsubscribe$)).subscribe((r) => { + if (r && r.title) { + if (r.title === "img") { + if (!this.jobId) { + this.msg.error("没有找到jobId"); + return; + } + const imgs: { zone: number; data: string }[] = r.imgs; + imgs.forEach((item) => { + const imgObj = { jobId: this.jobId!, img: item.data }; + if (Array.isArray(this.images[r.zone])) { + this.images[item.zone].push(imgObj); + } else { + this.images[item.zone] = [imgObj]; + } + if (item.zone === this.selectedZone?.zone) { + this.parsePoleImage(); + } + }); + } + if (r.title === "temperature") { + const temperatureNumber = Number(r.data); + if (!isNaN(temperatureNumber)) { + this.temperature = temperatureNumber.toFixed(1); + } + } + if (r.title === "detect") { + const detectData: PoleItemDTO[] = r.data; + + detectData.forEach((detect) => { + const oldData = this.originaPoleQueryData[detect.zone] ?? []; + this.originaPoleQueryData[detect.zone] = oldData.map((i) => { + if (i.type === detect.type && i.position === detect.position) { + const item = { ...detect, alarm: !!detect.alarm }; + return { + ...i, + ...item, + }; + } + return i; + }); + }); + + this.parsePoleData(this.originaPoleQueryData); + + // const type = r.data.type; + // if (type) { + // const arr = this.originaPoleQueryData[r.zone] ?? []; + // this.originaPoleQueryData[r.zone] = arr.map((i) => { + // if (i.type === r.data?.type && i.position === r.data?.position) { + // return { + // ...i, + // ...r.data, + // }; + // } + // return i; + // }); + + // } + } + } + }); + } + + getImageBase64(imgNames: string[]) {} + + getJobIdByPointId(pointId: DecText) { + this.originaPoleQueryData = createDefaultData(this.selectedPoint!.poleNum); + this.parsePoleData(this.originaPoleQueryData); + this.api.getRealtimeJob(pointId).subscribe((res) => { + const jobId = res.body?.["jobId"]; + this.jobId = jobId; + if (jobId) { + this.getImageByJobId(jobId); + this.getGraphicsDataByJobId(jobId); + } else { + this.msg.error("jobId不存在"); + } + }); + } + + getImageByJobId(jobId: string) { + this.api.getImg(jobId).subscribe((res) => { + Object.entries(res.body).forEach(([zone, imgs]) => { + const zoneNum = Number(zone); + this.images[zoneNum] = imgs.map((img) => ({ img, jobId })); + }); + this.parsePoleImage(); + }); + } + + getGraphicsDataByJobId(jobId: string) { + this.api.getQuery(jobId).subscribe((r) => { + // 根据 query的数据 替换 默认数据 扇区 有可能没有,里面的每一项也有可能没有 + Object.entries(r.body).forEach(([k, v]) => { + const zone = k as any; + // 查找扇区 + const defaultItem = this.originaPoleQueryData[zone]; + if (defaultItem) { + // console.log('this.originaPoleQueryData[zone]', this.originaPoleQueryData[zone], zone) + this.originaPoleQueryData[zone] = defaultItem.map((i) => { + // 查找扇区中的 的 转子 & 线 以及位置 + const queryItem = v.find((f) => f.position === i.position && i.type === f.type); + return queryItem || i; + }); + } + }); + + this.parsePoleData(this.originaPoleQueryData); + }); + } + + parsePoleData(poleDataFromServer: PoleQueryDTO) { + let lineAlarms: number[] = []; + let boltAlarms: number[] = []; + let poleAlarms: number[] = []; + let maxPole = { zone: 0, value: 0 }; + let maxLine = { zone: 0, value: 0 }; + let maxBolt = { zone: 0, value: 0 }; + + const formatedPoles = Object.values(poleDataFromServer).reduce((a, poles, idx) => { + // 获取扇区编号 + const zone = poles[0].zone; + + let bolt: PoleItemDTO[] = []; + let line: PoleItemDTO[] = []; + let pole!: PoleItemDTO; + + poles.forEach((item) => { + if (item.type === "bolt") { + bolt.push(item); + if (item.value > maxBolt.value) { + maxBolt = item; + } + if (item.alarm) { + boltAlarms.push(zone); + } + } + if (item.type === "line") { + line.push(item); + if (item.value > maxLine.value) { + maxLine = item; + } + if (item.alarm) { + lineAlarms.push(zone); + } + } + if (item.type === "pole") { + pole = item; + if (item.alarm) { + poleAlarms.push(zone); + } + if (item.value > maxPole.value) { + maxPole = item; + } + } + }); + + return a.concat({ + bolt, + line, + zone, + pole, + }); + }, [] as PoleGroupInterface[]); + this.poles = formatedPoles; + + if (formatedPoles[0] && !this.selectedZone) { + this.onZoneSelect(formatedPoles[0].zone); + } + + this.maxBolt = maxBolt; + this.maxPole = maxPole; + this.maxLine = maxLine; + + this.lineAlarmZones = [...new Set(lineAlarms)]; + this.boltAlarmZones = [...new Set(boltAlarms)]; + this.poleAlarmZones = [...new Set(poleAlarms)]; + + this.graphicsProps$.next({ poles: formatedPoles }); + } + + getAllPoint() { + this.api.getAllPoint().subscribe((r) => { + this.allPoint = r; + const firstPoint = r?.[0]?.groupList?.[0]?.pointList?.[0]; + if (firstPoint) { + this.selectedPoint = firstPoint; + this.ws$?.next({ status: true, pointId: firstPoint.pointId }); + + this.getJobIdByPointId(firstPoint.pointId); + } + }); + } + + onZoneSelect(zone: number) { + this.selectedZone = this.poles.find((f) => f.zone === zone); + // let maxLine = { zone: 0, value: 0 }; + // let maxBolt = { zone: 0, value: 0 }; + // this.selectedZone?.bolt.forEach((bolt) => { + // if (bolt.value > maxBolt.value) { + // maxBolt = bolt; + // } + // }); + // this.selectedZone?.line.forEach((line) => { + // if (line.value > maxLine.value) { + // maxLine = line; + // } + // }); + // this.maxBolt = maxBolt; + // this.maxLine = maxLine; + if (this.imgplayerRef) { + this.imgplayerRef.reset(); + } + + this.parsePoleImage(); + } + + parsePoleImage() { + let zoneImages: ImageObj[] = []; + if (this.selectedZone) { + zoneImages = this.images[this.selectedZone.zone] ?? []; + } + this.images$.next(zoneImages); + } + + switchDevice(nzContent: TemplateRef<{}>) { + const stationName = this.allPoint[0].name; + this.tempSelectedPoint = this.selectedPoint; + this.modal.create({ + nzTitle: `设备切换-${stationName}`, + nzContent, + nzOnOk: () => { + if (this.tempSelectedPoint) { + this.selectedPoint = this.tempSelectedPoint; + this.ws$?.next({ status: true, pointId: this.selectedPoint.pointId }); + this.getJobIdByPointId(this.selectedPoint.pointId); + this.tempSelectedPoint = null; + this.msg.success(`已选择监测点:${this.selectedPoint!.name}`); + } else { + this.msg.error(`请选择监测点`); + } + }, + }); + } + + handleManualDetection() { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要手动检测?", + nzOnOk: async () => { + const res = await lastValueFrom(this.api.manualDetection(this.selectedPoint!.pointId)); + if (res.success) { + this.msg.success(res.desc); + this.getJobIdByPointId(this.selectedPoint!.pointId); + return true; + } + return false; + }, + }); + } +} diff --git a/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.html b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.html new file mode 100644 index 0000000..384f3f1 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.html @@ -0,0 +1,182 @@ +
+ +
+
+
+ +

机组/检测点

+

{{point || ''}}

+
+
+
+ +

检测时间

+

{{gmtCreate}}

+
+
+
+ +

检测类型

+

{{type}}

+
+
+
+ +

检测结果

+

+ +

+
+
+
+
+
+ + + + +
+
+ + + + + + + + + + + + + + + + + +
+ + 引出线变形 + + + 检测正常 + + {{line}}#磁极异常 + +
+ + 螺栓松动 + + + 检测正常 + + {{line}}#磁极异常 + +
+ + 磁极开匝 + + + 检测正常 + + {{line}}#磁极异常 + +
+
+
+
+ + + + + + 磁极 + + + 引出线变形(mm) + + + 螺栓松动(°) + + + + + #1 + + + #2 + + + #1 + + + #2 + + + #3 + + + #4 + + + #5 + + + #6 + + + #7 + + + #8 + + + + + + + + {{item.zone}}# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.less b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.less new file mode 100644 index 0000000..4ee631d --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.less @@ -0,0 +1,83 @@ +:host { + display: flex; + height: 100%; + flex-direction: column; +} + +.auto { + gap: 16px; + grid-template-rows: calc(70% - 16px) 30%; + grid-template-columns: repeat(2, 1fr); + + padding-top: 14px; + flex: 1; + + .images-player-wrapper { + grid-row: 1 / span 1; + grid-column: 1 / span 1; + } + + .result { + grid-row: 2 / span 1; + grid-column: 1 / span 1; + } + + ::ng-deep { + nz-card { + height: 100%; + display: flex; + flex-direction: column; + .ant-card-body { + flex: 1; + } + } + } + + table { + display: table; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + th { + color: var(--purple); + } + td, + th { + padding: 6px 0; + // border: 1px solid var(--border-color); + &:first-child { + width: 120px; + } + } + } + .detail-table { + grid-row: 1 / span 2; + grid-column: 2 / span 1; + ::ng-deep { + table { + display: table; + border-collapse: collapse; + border-spacing: 0; + } + th:not(:last-child) { + border-right: 1px solid var(--border-color); + } + td { + border-bottom: none !important; + &:not(:last-child) { + border-right: 1px solid var(--border-color); + } + } + thead { + tr:last-child th { + border-top: 1px solid var(--border-color); + } + } + tbody { + tr:last-child { + border-bottom: 1px solid var(--border-color); + } + } + } + } +} diff --git a/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.ts b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.ts new file mode 100644 index 0000000..b4eaffd --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-detail/history-detail.component.ts @@ -0,0 +1,133 @@ +import { Component, OnInit, ViewEncapsulation } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import { DetectionApiService, UtilsService } from "@client/app/core/services"; +import { PointStatusEnum, PoleItemDTO, PoleQueryDTO } from "@client/dtos"; +import { BehaviorSubject, forkJoin } from "rxjs"; +import { PoleGroupInterface } from "../../../components"; +import { ImageObj } from "../../../components/image-player/image-player.component"; + +@Component({ + selector: "app-history-detail", + templateUrl: "./history-detail.component.html", + styleUrls: ["./history-detail.component.less"], + // encapsulation: ViewEncapsulation.None, +}) +export class HistoryDetailComponent implements OnInit { + constructor(private api: DetectionApiService, private route: ActivatedRoute, private util: UtilsService) {} + + public PointStatusEnum = PointStatusEnum; + + public point: string = ""; + + public gmtCreate: string = ""; + + public type: string = ""; + + public status: PointStatusEnum = PointStatusEnum.NORMAL; + + public data: PoleGroupInterface[] = []; + + public images$ = new BehaviorSubject([]); + + lineAlarmZones: number[] = []; + + boltAlarmZones: number[] = []; + + ngOnInit(): void { + const id = this.route.snapshot.paramMap.get("id")!; + const { queryParams } = this.route.snapshot; + this.point = (queryParams["motorGroup"] ?? "") + "/" + (queryParams["point"] ?? ""); + this.gmtCreate = queryParams["gmtCreate"]; + this.type = queryParams["type"]; + this.status = Number(queryParams["status"]); + + this.getImageByJobId(id); + + // this.api.getFlatPoints().subscribe(r=> { + + // }) + + this.api.getHistoryDetail(id).subscribe((r: PoleQueryDTO) => { + let lineAlarms: number[] = []; + let boltAlarms: number[] = []; + const poles = Object.values(r).reduce((a, poles, idx) => { + let temperature: PoleItemDTO | null; + // console.log("pole", pole); + if (idx === 0 && poles?.[0]?.type === "temperature") { + temperature = poles[0]; + return a; + } + + const zone = poles[0].zone; + let bolt: PoleItemDTO[] = []; + let line: PoleItemDTO[] = []; + let pole!: PoleItemDTO; + + poles.forEach((item) => { + if (item.type === "temperature") { + temperature = item; + } + if (item.type === "bolt") { + bolt.push(item); + if (item.alarm) { + boltAlarms.push(zone); + } + } + if (item.type === "line") { + line.push(item); + if (item.alarm) { + lineAlarms.push(zone); + } + } + if (item.type === "pole") { + pole = item; + } + }); + + return a.concat({ + bolt, + line, + zone, + pole, + }); + }, [] as PoleGroupInterface[]); + + this.data = poles; + + this.lineAlarmZones = [...new Set(lineAlarms)]; + this.boltAlarmZones = [...new Set(boltAlarms)]; + }); + } + + getImageByJobId(jobId: string) { + this.api.getImg(jobId).subscribe((res) => { + let images: ImageObj[] = []; + Object.values(res.body).forEach((imgs) => { + images = images.concat(imgs.map((img) => ({ jobId, img }))); + }); + console.log("images", images); + this.images$.next(images); + }); + } + getImageByJobId1(jobId: string) { + this.api.getImg(jobId).subscribe(async (imgobj) => { + const images: string[] = []; + Object.values(imgobj).forEach((imgs) => { + images.push(...(imgs)); + }); + + // console.log("images", images); + + // console.time("img to base64"); + // const base64Imgs = await this.util.loadImages(images); + // console.timeEnd("img to base64"); + // console.log("base64Imgs", base64Imgs); + // console.time("bas64"); + // forkJoin([this.api.getBase64Image({ jobID: jobId, img: images[0] })]).subscribe((rr) => { + // console.timeEnd("bas64"); + // }); + // 1111 + // this.images$.next(images); + }); + } +} diff --git a/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.html b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.html new file mode 100644 index 0000000..17b4739 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.html @@ -0,0 +1,91 @@ + +
+
+ + +
+
+ + + + +
+
+ +
+ +
+ + + + + + +
    +
  • 导出筛选报告
  • +
  • 导出筛选数据
  • +
  • 导出选中报告
  • +
  • 导出选中数据
  • +
+
+ + + + +
+
+
+
+ + + + + + + {{row.motorGroup}}/{{row.point}} + + + + + + {{data}} + + + + - + + + + + + + + + + {{data}} + + + +
+ + +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.less b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.less new file mode 100644 index 0000000..8030782 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.less @@ -0,0 +1,3 @@ +nz-card { + height: 100%; +} diff --git a/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.ts b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.ts new file mode 100644 index 0000000..fc67ff1 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/history/history-list/history-list.component.ts @@ -0,0 +1,164 @@ +import { AfterViewInit, ViewChild } from "@angular/core"; +import { subDays, format } from "date-fns"; +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { TableListComponent, TableListOption } from "@cdk/public-api"; +import { AnyObject } from "@cdk/types"; +import { DetectionApiService } from "@client/app/core/services"; +import { PointStatusEnum } from "@client/dtos"; +import { NzCascaderOption } from "ng-zorro-antd/cascader"; +import { HttpResponse } from "@angular/common/http"; +import { finalize } from "rxjs"; + +type QueryInterface = { + range: string[] | null; + pointId: null | string[]; + status: number | null; +}; + +const initQuery = { + range: null, + pointId: null, + status: null, +}; + +@Component({ + selector: "app-history-list", + templateUrl: "./history-list.component.html", + styleUrls: ["./history-list.component.less"], +}) +export class HistoryListComponent implements OnInit, AfterViewInit { + constructor(private api: DetectionApiService, private router: Router) {} + + @ViewChild("tableListRef") public tableListRef!: TableListComponent; + + public tableList = new TableListOption(this.fetchData.bind(this), { + frontPagination: false, + selectable: true, + rowKey: "jobId", + }); + + PointStatusEnum = PointStatusEnum; + + points: NzCascaderOption[] = []; + + query: QueryInterface = JSON.parse(JSON.stringify(initQuery)); + + selectedKeys: string[] = []; + + ngOnInit(): void { + this.initTableList(); + this.parsePoint(); + } + + ngAfterViewInit(): void { + this.tableListRef.props.getState$.subscribe((selected) => { + this.selectedKeys = selected.selectedKeys; + }); + } + + parsePoint() { + this.api.getAllPoint().subscribe((r) => { + const stationGroups = r[0]; + this.points = stationGroups.groupList.map((g) => { + return { + label: g.name, + value: g.motorGroupId, + children: g.pointList.map((p) => { + return { + label: p.name, + value: p.pointId, + isLeaf: true, + }; + }), + }; + }); + }); + } + + fetchData(pager: AnyObject) { + const q = this.formatQuery(); + return this.api.getDetcttionHistoryPage(pager, q); + } + + formatQuery() { + const q = Object.create(null); + Object.entries(this.query).forEach(([k, v]) => { + q[k] = v; + if (k === "range" && Array.isArray(v) && v.length === 2) { + const startTime = typeof v[0] === "string" ? v[0] : format(v[0], "yyyy-MM-dd"); + const endTime = typeof v[1] === "string" ? v[1] : format(v[1], "yyyy-MM-dd"); + q.startTime = startTime; + q.endTime = endTime; + } + if (k === "pointId" && Array.isArray(v) && v.length === 2) { + q.pointId = v[1]; + } + }); + + return q; + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "jobId", title: "序号" }, + { key: "point", title: "机组/监测点" }, + { key: "gmtCreate", title: "检测时间" }, + { key: "type", title: "检测类型" }, + { key: "status", title: "检测状态" }, + { key: "info", title: "异常信息" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "查看详情", + premissions: [], + onClick: (v) => { + const { info, jobId, ...queryParams } = v; + this.router.navigate(["/", "detection", "history", v.jobId], { queryParams }); + }, + }, + ]); + } + + search() { + this.tableListRef.doQuery(); + } + + reset() { + this.query = JSON.parse(JSON.stringify(initQuery)); + // this.tableListRef.reset(); + } + + exportLoading = false; + + export(type: number) { + this.exportLoading = true; + const q = this.formatQuery(); + const method = type % 2 === 0 ? "exportExcel" : "exportWord"; + const query = type <= 2 ? q : { jobs: this.selectedKeys }; + this.api[method](query) + .pipe( + finalize(() => { + this.exportLoading = false; + }) + ) + .subscribe((response) => { + this.downLoadFile(response); + }); + } + downLoadFile(response: HttpResponse) { + const fileNameFromHeader = response.headers.get("Content-Disposition"); + if (fileNameFromHeader) { + const fileName = fileNameFromHeader.split(";")[1].trim().split("=")[1].replace(/"/g, ""); + const blob = new Blob([response.body as any], { type: "application/zip" }); + const downloadLink = document.createElement("a"); + downloadLink.href = URL.createObjectURL(blob); + downloadLink.download = decodeURIComponent(fileName); + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + } + } +} diff --git a/projects/client/src/app/feature/detection/pages/index.ts b/projects/client/src/app/feature/detection/pages/index.ts new file mode 100644 index 0000000..b9642ab --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/index.ts @@ -0,0 +1,9 @@ +export * from "./analysis/analysis.component"; +export * from "./detection-index/detection-index.component"; +export * from "./history/history-detail/history-detail.component"; +export * from "./history/history-list/history-list.component"; +export * from "./settings/point-setting/point-setting.component"; +export * from "./settings/settings-layout/settings-layout.component"; +export * from "./settings/system-setting/system-setting.component"; +export * from "./settings/algorithm-setting/algorithm-setting.component"; +export * from "./settings/temperature-setting/temperature-setting.component"; diff --git a/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.html b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.html new file mode 100644 index 0000000..15070a0 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.html @@ -0,0 +1,151 @@ + + + + +
+ + + + + +

检测算法设置

+ + + 螺栓转动角度阈值 + + + + + + + + + + + 引出线变量阈值 + + + + + + + + +

检测设置

+ + + 每日自动检测时间 + + + + + + {{time}} + + + + + + +
+ +
+
+
+
+ + + 延时检测设置 + + + + + + + + + + + 应用机组/检测点 + + + +
+ + + {{p['gname']}}/{{p.name}} + + + +
+
+ + + +
+
+
+
+
+ +
+
+
+ + + +
+ + + 每日自动检测时间 + + + + + + +
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.less b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.less new file mode 100644 index 0000000..d4dc61b --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.less @@ -0,0 +1,34 @@ +.btn-group { + border: 1px solid var(--border-color); + + li { + &:not(:last-child) { + a:after { + content: ""; + width: 1px; + height: 70%; + background-color: var(--border-color); + position: absolute; + top: 15%; + right: 0; + } + } + } + + a { + display: flex; + align-items: center; + justify-content: center; + padding: 6px 16px; + position: relative; + color: var(--text-color); + } +} + +.delayDetect { + display: none; + + &.show { + display: inline-block; + } +} \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.ts b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.ts new file mode 100644 index 0000000..7059c34 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/algorithm-setting/algorithm-setting.component.ts @@ -0,0 +1,200 @@ +import { Component, OnInit, TemplateRef } from "@angular/core"; +import { FormArray, FormGroup, FormBuilder } from "@angular/forms"; +import { AnyObject } from "@cdk/types"; +import { Utils } from "@cdk/utils"; +import { DetectionApiService } from "@client/app/core/services"; +import { AlgorithmDTO, PointDTO } from "@client/dtos"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { finalize } from "rxjs"; +import { PointTableComponent } from "../../../components"; + +@Component({ + selector: "app-algorithm-setting", + templateUrl: "./algorithm-setting.component.html", + styleUrls: ["./algorithm-setting.component.less"], +}) +export class AlgorithmSettingComponent implements OnInit { + constructor( + private modal: NzModalService, + private api: DetectionApiService, + private fb: FormBuilder, + private msg: NzMessageService + ) {} + + formGroup!: FormGroup; + + submitLoading: boolean = false; + + flatPoints: PointDTO[] = []; + + tempTime: Date = new Date(); + + public get algorithmArray(): FormArray { + return this.formGroup.get("algorithm") as FormArray; + } + + ngOnInit(): void { + this.formGroup = this.fb.group({ + algorithm: this.fb.array([]), + }); + this.api.getFlatPoints().subscribe(({ points }) => { + this.flatPoints = points; + }); + this.api.getAlgorithm().subscribe((r) => { + if (r.success) { + if (Array.isArray(r.body)) { + r.body.forEach((item) => { + this.createAlgorithm(item); + }); + } + } + }); + } + + createAlgorithm(v?: AlgorithmDTO) { + let pointIdList: PointDTO[] = []; + if (v?.pointIdList && Array.isArray(v.pointIdList)) { + pointIdList = v.pointIdList.map((i) => this.flatPoints.find((f) => f.pointId === i)!); + } + this.algorithmArray.push( + this.fb.group({ + algorithmConfigId: [v?.algorithmConfigId], + name: [v?.name ?? "检测算法参数" + this.algorithmArray.length], + boltThreshold: [v?.boltThreshold ?? 0], + lineThreshold: [v?.lineThreshold ?? 0], + dailyAutoDetectionTime: [v?.dailyAutoDetectionTime ?? []], + delayDetect: [v?.delayDetect ?? 0], + pointIdList: [pointIdList], + }) + ); + } + + deletItem(i: number) { + this.algorithmArray.removeAt(i); + } + + quickTime(n: number, idx: number) { + const dailyAutoDetectionTime = this.algorithmArray.at(idx).get("dailyAutoDetectionTime"); + const timeArray = this.getTimeArray(n); + dailyAutoDetectionTime?.patchValue([...new Set(timeArray.concat(dailyAutoDetectionTime.value))]); + } + + getTimeArray(n: number) { + let result = []; + let hour = 0; + let minute = 0; + while (hour < 24) { + let timeString = `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}`; + result.push(timeString); + minute += n; + if (minute >= 60) { + hour += Math.floor(minute / 60); + minute = minute % 60; + } + if (hour >= 24) { + break; + } + } + return result; + } + + removeTime(arrIndex: number, timeIndex: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该时间?", + nzOnOk: () => { + const dailyAutoDetectionTime = this.algorithmArray.at(arrIndex).get("dailyAutoDetectionTime"); + const value = (dailyAutoDetectionTime?.value as string[]).filter((_, idx) => idx !== timeIndex); + dailyAutoDetectionTime?.patchValue(value); + }, + }); + } + + removePoint(arrIndex: number, pIndex: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要取消选择该监测点?", + nzOnOk: () => { + const pointIdList = this.algorithmArray.at(arrIndex).get("pointIdList"); + const value = (pointIdList?.value as string[]).filter((_, idx) => idx !== pIndex); + pointIdList?.patchValue(value); + }, + }); + } + + selectTime(nzContent: TemplateRef<{}>, idx: number) { + this.modal.create({ + nzTitle: "添加每日自动检测时间", + nzWidth: 480, + nzContent, + nzOnOk: async () => { + if (this.tempTime) { + const dailyAutoDetectionTime = this.algorithmArray.at(idx).get("dailyAutoDetectionTime"); + const value = (dailyAutoDetectionTime?.value as string[]).concat(format(this.tempTime, "HH:mm")); + dailyAutoDetectionTime?.patchValue(value); + this.tempTime = new Date(); + } + }, + }); + } + + onDelayDetectClose(checked: boolean, i: number) { + this.algorithmArray + .at(i) + .get("delayDetect") + ?.patchValue(checked ? null : 0); + } + + onSave() { + if (Utils.validateFormGroup(this.formGroup)) { + let { algorithm } = this.formGroup.value; + if (Array.isArray(algorithm) && algorithm.some((s) => s?.pointIdList?.length === 0)) { + this.msg.error("请添加应用机组/检测点"); + return; + } + algorithm = algorithm.map((i: AnyObject) => ({ + ...i, + pointIdList: i["pointIdList"].map((p: PointDTO) => p.pointId), + })); + this.submitLoading = true; + this.api + .saveAlgorithm(algorithm) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe((res) => { + this.msg.success(res.desc); + }); + } + } + + selectPoint(idx: number) { + const pointIdList = this.algorithmArray.at(idx).get("pointIdList"); + + const otherSelected: PointDTO[] = []; + + Array.from({ length: this.algorithmArray.length }, (_, index) => { + if (index !== idx) { + otherSelected.push(...this.algorithmArray.at(index).get("pointIdList")?.value); + } + }); + + this.modal.create({ + nzTitle: "添加监测点", + nzWidth: 640, + nzContent: PointTableComponent, + nzComponentParams: { + currentSelected: pointIdList?.value, + otherSelected, + }, + nzOnOk: async (e: PointTableComponent) => { + const v = e.arrOfChecked; + pointIdList?.patchValue(v); + }, + }); + } +} diff --git a/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.html b/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.html new file mode 100644 index 0000000..ea0b4cf --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.html @@ -0,0 +1,31 @@ + + + + + + + + 检测设备 + + + + + + + + + 数据复位 + + + + + + + + + \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.less b/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.ts b/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.ts new file mode 100644 index 0000000..b29326f --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/point-setting/point-setting.component.ts @@ -0,0 +1,73 @@ +import { NzMessageService } from "ng-zorro-antd/message"; +import { Component, OnInit, TemplateRef } from "@angular/core"; +import { DetectionApiService } from "@client/app/core/services"; +import { PointDTO, PointGroupDTO } from "@client/dtos"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { finalize, lastValueFrom } from "rxjs"; + +@Component({ + selector: "app-point-setting", + templateUrl: "./point-setting.component.html", + styleUrls: ["./point-setting.component.less"], +}) +export class PointSettingComponent implements OnInit { + constructor(private api: DetectionApiService, private modal: NzModalService, private msg: NzMessageService) {} + + points: PointDTO[] = []; + + resetLoading = false; + + saveLoading = false; + + ngOnInit(): void { + this.parsePoint(); + } + + parsePoint(force?: boolean) { + this.api.getAllPoint(force).subscribe((r) => { + const stationGroups = r[0]; + const ps: PointDTO[] = []; + stationGroups.groupList.forEach((g) => { + ps.push(...g.pointList.map((p) => ({ ...p, gname: g.name, enableDetectBool: p.enableDetect === 0 }))); + }); + this.points = ps; + }); + } + + onReset(pid: string) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要复位数据?", + nzOnOk: async () => { + this.resetLoading = true; + const res = await lastValueFrom( + this.api.resetPointData(pid).pipe( + finalize(() => { + this.resetLoading = false; + }) + ) + ); + if (res.success) { + this.msg.success(res.desc); + this.parsePoint(true); + } + }, + }); + } + + async onSave() { + this.saveLoading = true; + const p = this.points.map((p) => ({ pointId: p.pointId, enableDetect: p["enableDetectBool"] ? 0 : 1 })); + const res = await lastValueFrom( + this.api.savePointEnable(p).pipe( + finalize(() => { + this.saveLoading = false; + }) + ) + ); + if (res.success) { + this.msg.success(res.desc); + this.parsePoint(true); + } + } +} diff --git a/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.html b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.html new file mode 100644 index 0000000..0cab495 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.html @@ -0,0 +1,29 @@ + +
+ +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.less b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.less new file mode 100644 index 0000000..b871213 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.less @@ -0,0 +1,25 @@ +:host { + display: flex; + height: 100%; +} + +.menu { + flex-basis: 200px; + + a { + display: block; + padding: 16px 24px; + color: var(--text-color); + border-right: 2px solid transparent; + + &:hover { + color: var(--p); + } + + &.active { + background: var(--blue3-10); + border-right-color: var(--p); + color: var(--p); + } + } +} \ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.ts b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.ts new file mode 100644 index 0000000..bbd9664 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/settings-layout/settings-layout.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "app-settings", + templateUrl: "./settings-layout.component.html", + styleUrls: ["./settings-layout.component.less"], +}) +export class SettingsLayoutComponent {} diff --git a/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.html b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.html new file mode 100644 index 0000000..96a8e25 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.html @@ -0,0 +1,43 @@ + +
+ 系统版本 +
+
+ {{version}} +
+
+
+
+ + + + + + + 自动导出报告设置 + + +
+ + + + + +
+
+
+ + + 导出文件保存位置 + + +
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.less b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.less new file mode 100644 index 0000000..b4bebaa --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.less @@ -0,0 +1,5 @@ +:host { + display: flex; + flex-direction: column; + height: 100%; +} diff --git a/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.ts b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.ts new file mode 100644 index 0000000..7285016 --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/system-setting/system-setting.component.ts @@ -0,0 +1,46 @@ +import { Component, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; +import { DetectionApiService } from "@client/app/core/services"; +import { NzMessageService } from "ng-zorro-antd/message"; + +@Component({ + selector: "app-system-setting", + templateUrl: "./system-setting.component.html", + styleUrls: ["./system-setting.component.less"], +}) +export class SystemSettingComponent implements OnInit { + constructor(private api: DetectionApiService, private msg: NzMessageService) {} + + version: string = ""; + + formGroup = new FormGroup({ + report_auto_export_time: new FormControl(["30"]), + report_auto_export_dir: new FormControl([""]), + }); + + ngOnInit(): void { + this.api.getVersion().subscribe((r) => { + this.version = r.body?.version; + }); + this.getExportConfig("report_auto_export_time"); + this.getExportConfig("report_auto_export_dir"); + } + + getExportConfig(configId: string) { + this.api.getExportConfig({ configId }).subscribe((r) => { + this.formGroup.patchValue({ [configId]: r.body?.value }); + }); + } + + saveConfig() { + if (Utils.validateFormGroup(this.formGroup)) { + const { value } = this.formGroup; + Object.entries(value).forEach(([k, v]) => { + this.api.updateExportConfig({ configId: k, value: v }).subscribe((r) => { + this.msg.success(r.desc); + }); + }); + } + } +} diff --git a/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.html b/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.html new file mode 100644 index 0000000..577f32b --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.html @@ -0,0 +1,72 @@ + + + + +
+ + + + + + + + + + + 检测点温度检测阈值 + + + + + + + + + + + + 应用设备 + + + +
+ + + {{d['gname']}}/{{d.name}} + + + + +
+ +
+ + + + +
+
+
+
+
+ +
+
+ +
\ No newline at end of file diff --git a/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.less b/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.ts b/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.ts new file mode 100644 index 0000000..92df56a --- /dev/null +++ b/projects/client/src/app/feature/detection/pages/settings/temperature-setting/temperature-setting.component.ts @@ -0,0 +1,129 @@ +import { Component, TemplateRef } from "@angular/core"; +import { DetectionApiService } from "@client/app/core/services"; +import { FormArray, FormGroup, FormBuilder } from "@angular/forms"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { DeviceDTO, PointDTO, TemperatureSettingDTO } from "@client/dtos"; +import { DeviceTableComponent } from "../../../components"; +import { Utils } from "@cdk/utils"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { AnyObject } from "@cdk/types"; +import { finalize } from "rxjs"; + +@Component({ + selector: "app-temperature-setting", + templateUrl: "./temperature-setting.component.html", + styleUrls: ["./temperature-setting.component.less"], +}) +export class TemperatureSettingComponent { + constructor( + private modal: NzModalService, + private fb: FormBuilder, + private api: DetectionApiService, + private msg: NzMessageService + ) {} + + formGroup!: FormGroup; + + submitLoading: boolean = false; + + flatPoints: PointDTO[] = []; + + public get settingArray(): FormArray { + return this.formGroup.get("temperature") as FormArray; + } + + ngOnInit(): void { + this.formGroup = this.fb.group({ + temperature: this.fb.array([]), + }); + this.api.getFlatPoints().subscribe(({ points }) => { + this.flatPoints = points; + }); + this.api.getTemperatureSettings().subscribe((r) => { + if (r.success) { + if (Array.isArray(r.body)) { + r.body.forEach((item) => { + this.createAlgorithm(item); + }); + } + } + }); + } + + createAlgorithm(v?: TemperatureSettingDTO) { + this.settingArray.push( + this.fb.group({ + tempThresholdId: [v?.tempThresholdId], + name: [v?.name ?? "检测点温度检测参数" + this.settingArray.length], + tempThreshold: [v?.tempThreshold ?? 0], + deviceIdList: [v?.deviceIdList ?? []], + }) + ); + } + + deletItem(i: number) { + this.settingArray.removeAt(i); + } + + removeDevice(arrIndex: number, deviceIndex: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要取消选择该设备?", + nzOnOk: () => { + const deviceIdList = this.settingArray.at(arrIndex).get("deviceIdList"); + const value = (deviceIdList?.value as string[]).filter((_, idx) => idx !== deviceIndex); + deviceIdList?.patchValue(value); + }, + }); + } + + selectPoint(idx: number) { + const deviceIdList = this.settingArray.at(idx).get("deviceIdList"); + const otherSelected: any[] = []; + + Array.from({ length: this.settingArray.length }, (_, index) => { + if (index !== idx) { + console.log(" ", index); + otherSelected.push(...this.settingArray.at(index).get("deviceIdList")?.value); + } + }); + console.log("otherSelected", otherSelected); + this.modal.create({ + nzTitle: "添加设备", + nzWidth: 640, + nzContent: DeviceTableComponent, + nzComponentParams: { + otherSelected, + }, + nzOnOk: async (e) => { + const newVals = e.selectedDevice.concat(deviceIdList?.value); + deviceIdList?.setValue(newVals); + }, + }); + } + + onSave() { + if (Utils.validateFormGroup(this.formGroup)) { + let { temperature } = this.formGroup.value; + if (Array.isArray(temperature) && temperature.some((s) => s?.deviceIdList?.length === 0)) { + this.msg.error("请添加应用设备"); + return; + } + // temperature = temperature.map((i: AnyObject) => ({ + // ...i, + // pointIdList: i["pointIdList"].map((p: PointDTO) => p.pointId), + // })); + this.submitLoading = true; + this.api + .saveTemperatureSetting(temperature) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe((res) => { + this.msg.success(res.desc); + }); + } + } +} diff --git a/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.html b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.html new file mode 100644 index 0000000..46135a6 --- /dev/null +++ b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.html @@ -0,0 +1,80 @@ +
+ +
+ + +
+ + + +
    + +
  • + +
    +
    {{item.content}}
    +
    {{item.gmtCreate}}
    + +
    +
  • +
    +
+
+ + +
+
+
+
+ +
+
\ No newline at end of file diff --git a/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.less b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.less new file mode 100644 index 0000000..4699846 --- /dev/null +++ b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.less @@ -0,0 +1,144 @@ +:host { + display: block; + width: 100vw; + height: 100vh; + overflow: hidden; + background-color: var(--bg-color); +} + +@header-height: 60px; + +.header { + margin-top: 8px; + + height: @header-height; + + .title { + color: var(--title-color); + } + + .dec-logo { + position: absolute; + top: 24px; + left: 32px; + + b { + font-size: 1.5rem; + } + + span { + margin-top: -3px; + margin-left: 4px; + transform: scale(1.05); + font-size: 1.25rem; + } + + a { + display: flex; + align-items: center; + height: 34px; + + img { + display: block; + height: 34px; + margin-right: 12px; + } + + ::ng-deep { + .ant-divider-vertical { + border-left-color: var(--title-color) + } + } + + &:hover { + color: var(--title-color); + } + } + + ::ng-deep { + .ant-divider-vertical { + height: 1.2em; + } + } + } + + .main-nav { + width: 510px; + margin: 1px auto 0; + height: 50px; + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); + // background-color: rgba(255, 255, 255, 0.2); + + // &::after { + // content: ""; + // position: absolute; + // top: 0; + // left: -40px; + // width: calc(100% + 80px); + // height: 0px; + // border-width: 55px; + // border-style: solid; + // border-color: rgba(255, 255, 255, 0.15) transparent transparent transparent; + // } + + .nav-item { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + color: var(--text-color); + font-size: 16px; + position: relative; + + &:hover { + color: var(--p); + } + + &.active { + color: var(--p); + font-weight: bold; + + &::after { + content: ""; + width: 40px; + height: 3px; + background-color: var(--p); + position: absolute; + bottom: -9px; + left: 50%; + transform: translateX(-50%); + } + } + } + } +} + +.right { + position: absolute; + top: 20px; + right: 32px; + + button { + padding-left: 12px; + padding-right: 12px; + } +} + +.app-container { + margin: 16px 32px 32px; +} + +.alert { + .time { + color: var(--gray-2); + } + + nz-divider { + margin: 12px 0 0; + } +} \ No newline at end of file diff --git a/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.ts b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.ts new file mode 100644 index 0000000..c7c72c1 --- /dev/null +++ b/projects/client/src/app/shared/components/authorization-layout/authorization-layout.component.ts @@ -0,0 +1,50 @@ +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { Component, Inject, OnInit } from "@angular/core"; +import { AuthService, DetectionApiService } from "@client/app/core/services"; +import { AlarmDTO } from "@client/dtos"; +import { DecConfig, decConfigToken } from "@cdk/public-api"; +import { Router } from "@angular/router"; + +@Component({ + selector: "app-authorization-layout", + templateUrl: "./authorization-layout.component.html", + styleUrls: ["./authorization-layout.component.less"], +}) +export class AuthorizationLayoutComponent implements OnInit { + constructor( + private api: DetectionApiService, + private auth: AuthService, + private modal: NzModalService, + private msg: NzMessageService, + @Inject(decConfigToken) private decConfig: Required, + private router: Router + ) {} + + system$ = this.auth.getSystemInfo(); + + notices: AlarmDTO[] = []; + + ngOnInit(): void { + this.getNotice(); + } + + getNotice() { + this.api.getNotice().subscribe((res) => { + this.notices = res.body; + }); + } + + logout() { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要退出登录?", + nzOnOk: () => { + this.msg.success("已退出登录"); + localStorage.removeItem(this.decConfig.localStroageKey); + localStorage.removeItem("auth"); + this.router.navigate([this.decConfig.loginUrl]); + }, + }); + } +} diff --git a/projects/client/src/app/shared/components/bg-border/bg-border.component.html b/projects/client/src/app/shared/components/bg-border/bg-border.component.html new file mode 100644 index 0000000..c45a4ac --- /dev/null +++ b/projects/client/src/app/shared/components/bg-border/bg-border.component.html @@ -0,0 +1,63 @@ +
+ + + + + + +
+
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/projects/client/src/app/shared/components/bg-border/bg-border.component.less b/projects/client/src/app/shared/components/bg-border/bg-border.component.less new file mode 100644 index 0000000..d81891b --- /dev/null +++ b/projects/client/src/app/shared/components/bg-border/bg-border.component.less @@ -0,0 +1,220 @@ +:host { + display: block; + overflow: hidden; + background-color: var(--bg-color); + pointer-events: none; + position: fixed; + inset: 0; +} + +#point-bg circle { + fill: var(--border-color); +} + + + +.dec-border { + position: fixed; + inset: 0; + + svg { + + rect, + polygon { + fill: var(--border-color); + + } + } + + &::before { + content: ""; + width: 1px; + background-color: var(--border-color); + position: absolute; + top: 310px; + left: 20px; + bottom: 310px; + } + + &::after { + content: ""; + width: 1px; + background-color: var(--border-color); + position: absolute; + top: 310px; + right: 20px; + bottom: 310px; + } + + .border-top { + height: 1px; + position: absolute; + top: 78px; + left: 154px; + right: 154px; + + &::before { + content: ""; + width: calc(50vw - 162px - 306px); + height: 1px; + background-color: var(--border-color); + position: absolute; + top: -70px; + left: 0; + } + + &::after { + content: ""; + width: calc(50vw - 162px - 306px); + height: 1px; + background-color: var(--border-color); + position: absolute; + top: -70px; + right: 0; + } + + .nav-polygon { + width: 610px; + height: 52px; + background-color: var(--nav-bg); + + position: absolute; + top: -70px; + left: 50%; + right: 50%; + transform: translateX(-50%); + bottom: 10px; + clip-path: polygon(0px 0px, 610px 0px, 550px 60px, 60px 60px); + } + + .line-center { + width: 510px; + height: 1px; + background-color: var(--border-color); + position: absolute; + left: 50%; + right: 50%; + bottom: 10px; + transform: translateX(-50%); + + &::before { + content: ""; + width: 85px; + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + left: 0; + transform-origin: bottom left; + transform: rotate(225deg); + } + + &::after { + content: ""; + width: 85px; + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + right: 0; + transform-origin: bottom right; + transform: rotate(135deg); + } + } + } + + .border-bottom { + height: 1px; + position: absolute; + left: 154px; + right: 154px; + bottom: 10px; + + &::before { + content: ""; + width: calc(50vw - 162px - 255px); + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + left: 0; + } + + &::after { + content: ""; + width: calc(50vw - 162px - 255px); + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + right: 0; + } + + .line-center { + width: 510px; + height: 1px; + background-color: var(--border-color); + position: absolute; + left: 50%; + right: 50%; + bottom: 10px; + transform: translateX(-50%); + + &::before { + content: ""; + width: 12px; + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + left: 0; + transform-origin: bottom left; + transform: rotate(135deg); + } + + &::after { + content: ""; + width: 12px; + height: 1px; + background-color: var(--border-color); + position: absolute; + top: 0; + right: 0; + transform-origin: bottom right; + transform: rotate(225deg); + } + } + } + + rect, + polygon { + fill: var(--page-corner-bg); + } + + polyline { + stroke: var(--border-color); + stroke-width: 1; + fill: none; + } + + .top-right { + position: fixed; + top: 0; + right: 0; + transform: rotate(90deg); + } + + .bottom-left { + position: fixed; + bottom: 0; + left: 0; + transform: rotate(-90deg); + } + + .bottom-right { + position: fixed; + bottom: 0; + right: 0; + transform: rotate(180deg); + } +} \ No newline at end of file diff --git a/projects/client/src/app/shared/components/bg-border/bg-border.component.ts b/projects/client/src/app/shared/components/bg-border/bg-border.component.ts new file mode 100644 index 0000000..71597f8 --- /dev/null +++ b/projects/client/src/app/shared/components/bg-border/bg-border.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-bg-border', + templateUrl: './bg-border.component.html', + styleUrls: ['./bg-border.component.less'] +}) +export class BgBorderComponent { + +} diff --git a/projects/client/src/app/shared/components/index.ts b/projects/client/src/app/shared/components/index.ts new file mode 100644 index 0000000..7d6ff56 --- /dev/null +++ b/projects/client/src/app/shared/components/index.ts @@ -0,0 +1,2 @@ +export * from "./authorization-layout/authorization-layout.component"; +export * from "./bg-border/bg-border.component"; diff --git a/projects/client/src/app/shared/directives/dec-corner.directive.ts b/projects/client/src/app/shared/directives/dec-corner.directive.ts new file mode 100644 index 0000000..13d9f08 --- /dev/null +++ b/projects/client/src/app/shared/directives/dec-corner.directive.ts @@ -0,0 +1,19 @@ +import { Directive, ElementRef, Renderer2 } from "@angular/core"; + +@Directive({ + selector: "[decCorner]", +}) +export class DecCornerDirective { + constructor(private el: ElementRef, private rd2: Renderer2) {} + + ngOnInit() { + const cornerWapper = this.rd2.createElement("div"); + this.rd2.setAttribute(cornerWapper, "class", "dec-corner"); + Array.from({ length: 4 }, () => { + const el = this.rd2.createElement("div"); + this.rd2.appendChild(cornerWapper, el); + }); + this.rd2.appendChild(this.el.nativeElement, cornerWapper); + this.rd2.addClass(this.el.nativeElement, "has-corner"); + } +} diff --git a/projects/client/src/app/shared/directives/index.ts b/projects/client/src/app/shared/directives/index.ts new file mode 100644 index 0000000..bf2b63f --- /dev/null +++ b/projects/client/src/app/shared/directives/index.ts @@ -0,0 +1 @@ +export * from "./dec-corner.directive"; diff --git a/projects/client/src/app/shared/ng-zorro.ts b/projects/client/src/app/shared/ng-zorro.ts new file mode 100644 index 0000000..5fd3cf7 --- /dev/null +++ b/projects/client/src/app/shared/ng-zorro.ts @@ -0,0 +1,96 @@ +import { NzGridModule } from "ng-zorro-antd/grid"; +import { NzCardModule } from "ng-zorro-antd/card"; +import { NzStatisticModule } from "ng-zorro-antd/statistic"; +import { NzIconModule } from "ng-zorro-antd/icon"; +import { NzToolTipModule } from "ng-zorro-antd/tooltip"; +import { NzTableModule } from "ng-zorro-antd/table"; +import { NzSegmentedModule } from "ng-zorro-antd/segmented"; +import { NzSpaceModule } from "ng-zorro-antd/space"; +import { NzDatePickerModule } from "ng-zorro-antd/date-picker"; +import { NzListModule } from "ng-zorro-antd/list"; +import { NzInputModule } from "ng-zorro-antd/input"; +import { NzButtonModule } from "ng-zorro-antd/button"; +import { NzTagModule } from "ng-zorro-antd/tag"; +import { NzBadgeModule } from "ng-zorro-antd/badge"; +import { NzPaginationModule } from "ng-zorro-antd/pagination"; +import { NzDividerModule } from "ng-zorro-antd/divider"; +import { NzSelectModule } from "ng-zorro-antd/select"; +import { NzModalModule } from "ng-zorro-antd/modal"; +import { NzMessageModule } from "ng-zorro-antd/message"; +import { NzDrawerModule } from "ng-zorro-antd/drawer"; +import { NzFormModule } from "ng-zorro-antd/form"; +import { NzDescriptionsModule } from "ng-zorro-antd/descriptions"; +import { NzTabsModule } from "ng-zorro-antd/tabs"; +import { NzProgressModule } from "ng-zorro-antd/progress"; +import { NzAvatarModule } from "ng-zorro-antd/avatar"; +import { NzMenuModule } from "ng-zorro-antd/menu"; +import { NzDropDownModule } from "ng-zorro-antd/dropdown"; +import { NzTreeSelectModule } from "ng-zorro-antd/tree-select"; +import { NzRadioModule } from "ng-zorro-antd/radio"; +import { NzCheckboxModule } from "ng-zorro-antd/checkbox"; +import { NzCalendarModule } from "ng-zorro-antd/calendar"; +import { NzSkeletonModule } from "ng-zorro-antd/skeleton"; +import { NzTimelineModule } from "ng-zorro-antd/timeline"; +import { NzEmptyModule } from "ng-zorro-antd/empty"; +import { NzSpinModule } from "ng-zorro-antd/spin"; +import { NzResultModule } from "ng-zorro-antd/result"; +import { NzCascaderModule } from "ng-zorro-antd/cascader"; +import { NzAutocompleteModule } from "ng-zorro-antd/auto-complete"; +import { NzPopoverModule } from "ng-zorro-antd/popover"; +import { NzPageHeaderModule } from "ng-zorro-antd/page-header"; +import { NzTreeModule } from "ng-zorro-antd/tree"; +import { NzSwitchModule } from "ng-zorro-antd/switch"; +import { NzCarouselModule } from "ng-zorro-antd/carousel"; +import { NzTimePickerModule } from "ng-zorro-antd/time-picker"; +import { NzImageModule } from "ng-zorro-antd/image"; +import { NzInputNumberModule } from "ng-zorro-antd/input-number"; + +export const ngZorroModules = [ + NzInputNumberModule, + NzImageModule, + NzTimePickerModule, + NzCarouselModule, + NzSwitchModule, + NzTreeModule, + NzPageHeaderModule, + NzPopoverModule, + NzAutocompleteModule, + NzCascaderModule, + NzResultModule, + NzSpinModule, + NzGridModule, + NzCardModule, + NzStatisticModule, + NzIconModule, + NzToolTipModule, + NzTableModule, + NzSegmentedModule, + NzSpaceModule, + NzDatePickerModule, + NzListModule, + NzInputModule, + NzButtonModule, + NzTagModule, + NzBadgeModule, + NzPaginationModule, + NzDividerModule, + NzSelectModule, + NzSelectModule, + NzModalModule, + NzMessageModule, + NzDrawerModule, + NzFormModule, + NzDescriptionsModule, + NzTabsModule, + NzProgressModule, + NzAvatarModule, + NzMenuModule, + NzDropDownModule, + NzTreeSelectModule, + NzRadioModule, + NzCalendarModule, + NzCheckboxModule, + NzSkeletonModule, + NzTimelineModule, + NzEmptyModule, +]; diff --git a/projects/client/src/app/shared/shared.module.ts b/projects/client/src/app/shared/shared.module.ts new file mode 100644 index 0000000..f0644cd --- /dev/null +++ b/projects/client/src/app/shared/shared.module.ts @@ -0,0 +1,49 @@ +import { RouterModule } from "@angular/router"; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { ngZorroModules } from "./ng-zorro"; +import { AuthorizationLayoutComponent, BgBorderComponent } from "./components"; +import { DecCornerDirective } from "./directives"; +import { + DecModule, + FormErrorTipsComponent, + InputSpaceErrorDirective, + PublicPathPipe, + TableListModule, + StorageModule, + QuickDateRangeComponent, +} from "@cdk/public-api"; +import { HttpClientModule } from "@angular/common/http"; +import { environment } from "@client/environments/environment"; +import { NgxPermissionsModule } from "ngx-permissions"; + +const ngModules = [CommonModule, HttpClientModule, FormsModule, RouterModule, ReactiveFormsModule]; +const components = [AuthorizationLayoutComponent, BgBorderComponent]; +const directives = [DecCornerDirective]; +const cdks = [ + FormErrorTipsComponent, + InputSpaceErrorDirective, + PublicPathPipe, + TableListModule, + StorageModule, + QuickDateRangeComponent, +]; + +@NgModule({ + declarations: [...components, ...directives], + imports: [ + DecModule.forRoot({ + environment, + isClient: true, + localStroageKey: "clinet_token", + loginUrl: "/auth/login", + }), + NgxPermissionsModule.forChild(), + ...ngZorroModules, + ...ngModules, + ...cdks, + ], + exports: [...ngZorroModules, ...ngModules, ...components, ...directives, ...cdks, NgxPermissionsModule], +}) +export class SharedModule {} diff --git a/projects/client/src/assets/.gitkeep b/projects/client/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/projects/client/src/assets/icons/alert.svg b/projects/client/src/assets/icons/alert.svg new file mode 100644 index 0000000..2cd4da4 --- /dev/null +++ b/projects/client/src/assets/icons/alert.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/bell.svg b/projects/client/src/assets/icons/bell.svg new file mode 100644 index 0000000..9aa95ed --- /dev/null +++ b/projects/client/src/assets/icons/bell.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/disconnect.svg b/projects/client/src/assets/icons/disconnect.svg new file mode 100644 index 0000000..9484f8b --- /dev/null +++ b/projects/client/src/assets/icons/disconnect.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/folder.svg b/projects/client/src/assets/icons/folder.svg new file mode 100644 index 0000000..80ad456 --- /dev/null +++ b/projects/client/src/assets/icons/folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/fullscreen.svg b/projects/client/src/assets/icons/fullscreen.svg new file mode 100644 index 0000000..8bcd879 --- /dev/null +++ b/projects/client/src/assets/icons/fullscreen.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/projects/client/src/assets/icons/light.svg b/projects/client/src/assets/icons/light.svg new file mode 100644 index 0000000..0d4a474 --- /dev/null +++ b/projects/client/src/assets/icons/light.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/projects/client/src/assets/icons/lock.svg b/projects/client/src/assets/icons/lock.svg new file mode 100644 index 0000000..f01201b --- /dev/null +++ b/projects/client/src/assets/icons/lock.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/moon.svg b/projects/client/src/assets/icons/moon.svg new file mode 100644 index 0000000..6f87259 --- /dev/null +++ b/projects/client/src/assets/icons/moon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/projects/client/src/assets/icons/no-image-white.png b/projects/client/src/assets/icons/no-image-white.png new file mode 100644 index 0000000000000000000000000000000000000000..86ec11885c7729c77fd27325ebe7630c847fb260 GIT binary patch literal 471 zcmV;|0Vw{7P)jNB9`9AWhHlopU~?Rla1klI{A%a;?|{ zfah33EELPru=OP9G}}g}*~QhM(~`iBZk?M)Pj(lp5Naj|LNqRS7mEZb@N6H301eyO z{fh)lV4kpqPW1%iNWj?+aQGvZz?iQ9VTWeu!i0^p>QDr?MswrGkGojjxB*4rmT2bp z4zYY@#*%|up_$(zEJOuvfrc__ur(UX`7i-nqLI&utFH!Ip)>toa`mgg7HFp5{ZjpE z@LF_f{3hTv=x*RzbXRZ`c*_=brC zH@PD#gld+@v@yXi0r~4&F8igrX?C<%GU)ORea|px8nzz%?_xi@%NGPgplJPfS1$kn N002ovPDHLkV1hiN$Ws6S literal 0 HcmV?d00001 diff --git a/projects/client/src/assets/icons/no-image.png b/projects/client/src/assets/icons/no-image.png new file mode 100644 index 0000000000000000000000000000000000000000..d12688d176199b5dc773ce992ad955553b88e31b GIT binary patch literal 678 zcmV;X0$KfuP)`xDsj1-i#QU^vxN(MI2O5MGhV|lKVoD+W}QeVl6 z6JH!Z@%ijHL>J{%QD#o3(;Xk4I2|}`ilX?S0cdRGXX+ej&OkH-h>?+>SY>n7E4`Kp zuy&O99-=T$RAc83yH#J^sjx2$4We*e^noy<*O<~Ml@DkT)_CWb2^&1fO1fthBWs=$TQzNh6fUqYz4{omOrJ>xp zQW%jyo?{}o_!;mHyug1RLgX>{JjO&YalP;aG}eAe+C#jeM@k5;?}`u4oUZHaL@s11 zp*t<8q4AJ60F($~DluvW03{yS`>KN008k=`9Y1GTRoHn65P4v)`TqAhgCJ{|NDxcD zZ{K9p$%RaXb|*>Wp&p~+|Lpa4*6h~NNFN{A=`P*(`Hxgmj~0YIJ*N9%l{R-v_u z3IKUP>>M_;CWw&VvXzp|6Pz~6#%?emDi?Lpd!Ur0Cjh~RH#&Ex+p2n#0YE~CPd>bo z@H;yx03?LK-VhdWUrqHT2Y@^wY8P`^03ad6ffKfEHkOTcuOv~ZO43!Vicr{2xu?Gm z`mL^`%rx!GM3CMC?Xsbq&4tK+2hb@K;7I9pC^Ky#>_0Rq_c+n`t$Cphg!BJEZuyLf zUIIW;h~5G~5{R5ps8KazLhnxZ8UU(*(9tXFOe~c#V?U5J6JL~Dzs4L%y6TN%oB#j- M07*qoM6N<$f}$%Os{jB1 literal 0 HcmV?d00001 diff --git a/projects/client/src/assets/icons/no-image.svg b/projects/client/src/assets/icons/no-image.svg new file mode 100644 index 0000000..dadaa1a --- /dev/null +++ b/projects/client/src/assets/icons/no-image.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/pie-center.svg b/projects/client/src/assets/icons/pie-center.svg new file mode 100644 index 0000000..49d4ad0 --- /dev/null +++ b/projects/client/src/assets/icons/pie-center.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/client/src/assets/icons/power.svg b/projects/client/src/assets/icons/power.svg new file mode 100644 index 0000000..b31c16f --- /dev/null +++ b/projects/client/src/assets/icons/power.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/success.svg b/projects/client/src/assets/icons/success.svg new file mode 100644 index 0000000..bf58abe --- /dev/null +++ b/projects/client/src/assets/icons/success.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/icons/user.svg b/projects/client/src/assets/icons/user.svg new file mode 100644 index 0000000..92fad76 --- /dev/null +++ b/projects/client/src/assets/icons/user.svg @@ -0,0 +1,3 @@ + + + diff --git a/projects/client/src/assets/imgs/logo.png b/projects/client/src/assets/imgs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..926913b643c0c392e6c78f6de7f8f82dc13202ff GIT binary patch literal 5380 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 i_%`WHE&U!+A>l91J^7N4B%ZDS0000; diff --git a/projects/client/src/dtos/auth.dto.ts b/projects/client/src/dtos/auth.dto.ts new file mode 100644 index 0000000..cece8b7 --- /dev/null +++ b/projects/client/src/dtos/auth.dto.ts @@ -0,0 +1,14 @@ +export type AuthDTO = { + userId: string; + userName: string; + role: string; + permissionList: PermissionDTO[]; +}; + +export type PermissionDTO = { + roleId: string; + name: string; + value: string; + scope: number; + type: number; +}; diff --git a/projects/client/src/dtos/index.ts b/projects/client/src/dtos/index.ts new file mode 100644 index 0000000..7e1f259 --- /dev/null +++ b/projects/client/src/dtos/index.ts @@ -0,0 +1,5 @@ +export * from "./alarm.dto"; +export * from "./algorithm.dto"; +export * from "./auth.dto"; +export * from "./point.dto"; +export * from "./temperature.dto"; diff --git a/projects/client/src/dtos/point.dto.ts b/projects/client/src/dtos/point.dto.ts new file mode 100644 index 0000000..7230ec9 --- /dev/null +++ b/projects/client/src/dtos/point.dto.ts @@ -0,0 +1,71 @@ +import { Augmented } from "@cdk/types"; + +export type PowerStationDTO = Augmented<{ + bizId: string; //电站id + name: string; //电站名称 + address: string; + contact: string; + phone: string; + introduction: string; + groupList: PointGroupDTO[]; +}>; + +export type PointGroupDTO = Augmented<{ + contact: string; + gmtCreate: string; + motorGroupId: string; + name: string; + phone: string; + status: PointStatusEnum; + powerStation: string; + pointList: PointDTO[]; +}>; + +export type PointDTO = Augmented<{ + pointId: string; //检测点id + name: string; //检测点名称 + poleNum: number; //磁极数量 + manualTime: number; + automaticTime: number; + enableDetect: number; + powerStation: string; + motorGroup: string; + boltDetect: number; + lineDetect: number; + poleOpenDetect: number; + pointTempDetect: number; + status: number; //检测点状态0-检测正常,1-检测异常,2-设备掉线 + gmtReset: number; +}>; + +export enum PointStatusEnum { + NORMAL, // 检测正常1 + ABNORMAL, // 检测异常 + DISCONNECT, //设备掉线 +} + +export type PoleItemDTO = { + alarm: boolean; + img: string; + position: number; + type: "bolt" | "line" | "temperature" | "pole"; + value: number; + zone: number; +}; + +export type PoleQueryDTO = { + [k: number]: PoleItemDTO[]; +}; + +export type DeviceDTO = Augmented<{ + gmtCreate: string; + deviceId: string; + type: string; + name: string; + powerStationId: string; + product: string; + motorGroupId: string; + pointId: string; + status: number; //设备状态:0-停用,1-正常,2-离线 + vender: string; +}>; diff --git a/projects/client/src/dtos/temperature.dto.ts b/projects/client/src/dtos/temperature.dto.ts new file mode 100644 index 0000000..1b7bd58 --- /dev/null +++ b/projects/client/src/dtos/temperature.dto.ts @@ -0,0 +1,8 @@ +import { Augmented } from "@cdk/types"; + +export type TemperatureSettingDTO = Augmented<{ + tempThresholdId: string; + name: string; + tempThreshold: number; + deviceIdList: string[]; +}>; diff --git a/projects/client/src/environments/environment.prod.ts b/projects/client/src/environments/environment.prod.ts new file mode 100644 index 0000000..744b0c6 --- /dev/null +++ b/projects/client/src/environments/environment.prod.ts @@ -0,0 +1,6 @@ +export const environment = { + production: true, + clientVersion: "1.0.0", + clientType: "web", + host: "http://47.109.27.8", +}; diff --git a/projects/client/src/environments/environment.ts b/projects/client/src/environments/environment.ts new file mode 100644 index 0000000..811b876 --- /dev/null +++ b/projects/client/src/environments/environment.ts @@ -0,0 +1,19 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false, + clientVersion: "1.0.0", + clientType: "web", + host: "http://47.109.27.8", +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/projects/client/src/favicon.ico b/projects/client/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b25db3a67f8ecbdb34d14305bb17368aaab901ec GIT binary patch literal 2525 zcmbu;c~FyQ9tZF@1mut_AcrD?s00uYP=ux-8C0NzDu)WlVG4)=0z`_DC?Of85H*T} zD2N9%B1Av|IYccckOMr{B1Z&64LMdTBJ#!~ybC!tZg;vf``6C)_ssLx^LxHCpXbm` z>ZE`*E<7?EfWZI&rXPS#3!t~hg@x{kjzhT;4*298$|SfR@%Qy}^&l5!=M!8baS^V# zn6L=fBU=MJy860~`mDcJUqk*{f_}HIA3&G@u7E2X<^~ub zU~mLXCjeaZN~1rrfqxgw0B&fs%-F=#Y`MOn#~Ltz!Qlpma3do_Lw$FNejPAG7}>1# z4_#&(n`Z1*up;1iCCg;pwmSoMaU$NmuVkQcP8+xPGUhe$3rWjVW6Y8)IW&Op~~36$-a#(6r`#MN@#kS`u1`~ zy-Wu<>?BD`@bY1SZBS`DI{S#k39PHRm17^9f`{6f^aECt-IR@Tq>wJYqBRTE0Y(6H zqTXyhsOCBlpi1SioWOU0GLg&=qhtJ}@O|RBsk~XGY4swrEljYA6Vl|hkPD*|} z)JtEAojHPW9{KX^{0b@tVm1Yp1r8Lmr&4n|q2XjvcjRY9Nuva{gjCzvN{0uB#U!o0 z@tHnnuux%$F@Wx8EN#?2eQ_+l7Mu{Gde8MmfKvnb?gLyGt*<&;NjmX)&UWtv+D_VT zDkQL=i~*EG#bKh=O5(%jCw5f)E<1Aiv)!nijZddafO3Ce9?UOtB&}Gist$(*L z{p01tzRn7#&6Gt5cWLoUVTw;K-@jp3^`<4vS+m0}vW@~iuaEsvxE;OJj@;#6Fw7)N2+DZ)?L6a4vG8Zsz z9`fM6A8_D3wB>O;lw0a;X+F@$;r=8{ts-^%zEL!yWfp5m&&HQmCPEy(;K2}se9bAe z^!rauF9M04TZrFm=&RcpsacS2nqw-T%1A=4k=k6-gid2oY2YS-Gm*F70*shLveeGX z-uFtS6Msz*R7Q|9r^_*p8WzWpGKA~s8uQkAaZ9PO4HUSX#Ah&h3w7&9u0JPFn`iBw z-Rdy(NC)JEVCDN8+oy9HEO&B=W9x|W=g5+|jTB1j*V zHO$ljuq{?*>LBIqwwi3k{Bm{7sJGUQ;v|?hp{=8)i)i-4t*Qprlf5C;LOD#`L>7h@_4N@GJhK!8Vl@cu#RAJBT1H+u8};mW8$R#4c= zZ0m@&z3_sCvs}TxFK+tIDgCcvRHN7~$zi!W)B z3{|8KIMGD)9dGLk1UGBVZp*l*#O^gj0y$6071yY!AfBlvvSx}#_YXAwHp{g^yWD(9 z;R@Ep<)Ks_fgyO@or({|%jdg{Df!!|8@2m)q@-W<||^V<8>ct+9)r!Zeq-QnvQn z@dM8}n{~iIjM`IrJ2+`7l_)`IYOx1N<%?Elnnvb-f6!b0=IM|Qu*p|vv_Pr(O! z9U>pJ3;KLYQp(AExHuZIL|2hCS1_j9;TIBb7t1y>eI>MzGM<;K^`<664E^7h(+BZR zL~-Vgg!m&|>%QXlRLSfvab|V1ouo<@Y*{7aT8iIYQDbGV+$Unvu%8~w=vLZMydhWG zR*mt49?R>UDcgDbG0>cxsPVN(mb1^1tD#abW6-7Bc&ZvdKzH z;RHfE$poo0c7TTG=fPv2Q=^N2hEQ;M9(~^;L1Fwp@@Lv3Y|jvXdMa5SA&9nAZ-b(g za22nFI8-fW_gfJ6LABsgJjA>X%_cwv@?`F*B!>#>cY(}QTSdq@o(^EpR(Flj5LuPk z55jw88q{F2X*b0;zw=qZ%-*X3i?u3)Yu>b2b3UB$=pNm)jCEPTdKPpsddY3Y+S9j9 z + + + + + + + + + + + + +
+
+
+ +
+

+ 加载中... +

+
+
+ + + + + + + \ No newline at end of file diff --git a/projects/client/src/main.ts b/projects/client/src/main.ts new file mode 100644 index 0000000..c58dc05 --- /dev/null +++ b/projects/client/src/main.ts @@ -0,0 +1,7 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/projects/client/src/styles.less b/projects/client/src/styles.less new file mode 100644 index 0000000..962649b --- /dev/null +++ b/projects/client/src/styles.less @@ -0,0 +1,568 @@ +/* You can add global styles to this file, and also import other style files */ +@import "../../../node_modules/ng-zorro-antd/ng-zorro-antd.less"; + +@tailwind utilities; + +@import "./theme.less"; + +body { + color: #333; + font-size: 16px; + // background: var(--bg-color); +} + +ul, +li { + list-style: none; + margin: 0; + padding: 0; +} + +/* 屏幕分辨率放大为 150 */ +@media (-webkit-min-device-pixel-ratio: 1.5), +(min-resolution: 120dpi) { + html { + font-size: 10px; + } +} + +/* 屏幕分辨率放大为 125 */ +@media (-webkit-min-device-pixel-ratio: 1.25) { + html { + font-size: 12px; + } +} + +a { + color: var(--p); +} + +.txt { + color: var(--text-color); +} + +input { + caret-color: #fff; +} + +::-webkit-scrollbar { + width: 8px; + height: 8px; + background-color: transparent; +} + +::-webkit-scrollbar-track { + border-radius: 8px; + background-color: transparent; +} + +::-webkit-scrollbar-thumb { + border-radius: 8px; + background-color: var(--white-10); +} + +/*************reset antd style start*************/ + +.ant-input { + color: var(--input-color); + + &:hover { + border-color: var(--p); + } +} + +nz-input-number { + color: var(--input-color) !important; +} + +.ant-image-preview-operations { + color: var(--text-color) !important; +} + +.ant-checkbox-checked .ant-checkbox-inner { + background-color: var(--p); +} + +.ant-input-group-addon { + color: var(--text-color) !important; +} + +.ant-switch-checked .ant-switch-inner { + color: var(--primary-btn-color) !important; +} + +.ant-btn { + &-primary { + background-color: var(--p); + border-color: var(--p); + color: var(--primary-btn-color); + + &:hover, + &:focus, + &:active { + color: var(--primary-btn-color); + background-color: var(--p); + } + + + } + + + + &-background-ghost { + border-color: var(--border-color) !important; + color: var(--text-color) !important; + + &:hover, + &:focus, + &:active { + border-color: var(--border-color) !important; + } + } + + &-sm { + display: flex; + // flex-direction: column; + align-items: center; + justify-content: center; + height: 26px; + padding: 4px 16px; + } +} + +.ant-card { + background: transparent; + font-size: var(--text-base); + + &:not(.auto-h-card) { + height: 100%; + display: flex; + flex-direction: column; + + .ant-card-body { + flex: 1; + } + } + + &.has-corner { + color: #fff; + } + + &-bordered { + border-color: var(--border-color); + } + + &-head { + min-height: 36px; + padding: 0 16px; + background-color: var(--card-hd-bg-color); + color: var(--card-text-color); + border: none; + font-size: 16px; + font-weight: bold; + } + + &-body { + flex: 1; + padding: 16px; + overflow: auto; + } +} + +.ant-switch-checked .ant-switch-inner { + color: var(--black); +} + +.ant-input-group-addon { + background-color: transparent; + color: #fff; +} + +.ant-image { + &-preview-operations { + background-color: var(--white-40); + color: var(--black); + } + + &-preview { + + .ant-image-preview-switch-left, + .ant-image-preview-switch-right { + background-color: var(--white-40); + color: var(--black); + } + } +} + +.ant-modal { + &-mask { + background-color: rgba(7, 17, 27, 0.65); + backdrop-filter: blur(5px); + } + + &-confirm-title, + &-confirm-content { + color: #fff !important; + } + + &-close { + top: 7px; + right: 16px; + + &-icon { + padding: 2px; + border: 1px solid #fff; + color: #fff; + font-size: 12px; + } + } + + &-header { + background-color: var(--white-6); + // border-bottom-color: var(--border-color); + border: none; + } + + &-title { + color: #fff; + } + + &-footer { + border-top-color: rgba(255, 255, 255, 0.3); + + .ant-btn:not(.ant-btn-primary) { + background-color: transparent; + color: #fff; + } + } + + &-content { + border: 1px solid var(--corner-color); + background: linear-gradient(180deg, rgba(255, 255, 255, 0.16) 0%, rgba(255, 255, 255, 0.08) 100%); + // background-color: rgba(255, 255, 255, 0.2); + backdrop-filter: blur(5px); + color: #fff; + @border-cover-color: #777b9d; // 不能用rgba + + &::before { + content: ""; + position: absolute; + top: -1px; + bottom: -1px; + left: var(--corner-size); + width: calc(100% - var(--corner-size) * 2); + border-top: 1px solid @border-cover-color; + border-bottom: 1px solid @border-cover-color; + z-index: 0; + pointer-events: none; + } + + &::after { + content: ""; + position: absolute; + top: var(--corner-size); + right: -1px; + left: -1px; + height: calc(100% - var(--corner-size) * 2); + border-right: 1px solid @border-cover-color; + border-left: 1px solid @border-cover-color; + z-index: 0; + pointer-events: none; + } + } +} + +.ant-divider { + &-vertical { + border-left-color: var(--fade-white); + } +} + +.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled) { + background-color: var(--p); + border-color: var(--p); + color: var(--primary-btn-color) !important; + + &::before { + content: none; + } +} + +.ant-radio-button-wrapper:hover { + color: var(--text-color); +} + +.ant-radio-button-wrapper { + background-color: transparent; + color: var(--text-color); + + &:not(:last-child) { + border-right-color: transparent; + } + + &:not(:first-child)::before { + height: calc(100% - 12px); + top: 6px; + bottom: 6px; + } +} + +.ant-select { + color: var(--text-color); + + &-dropdown { + background-color: #fff; + } + + &-arrow { + color: var(--text-color); + } + + &-multiple { + .ant-select-selection-item { + color: var(--black); + } + } + + &-clear { + color: var(--text-color); + + &:hover { + color: var(--text-color); + } + + &:active { + color: var(--text-color); + } + } +} + +.ant-picker-separator, +.ant-picker-suffix { + color: var(--text-color) !important; +} + +.ant-picker-input>input { + color: var(--text-color); +} + +.ant-table { + color: var(--table-color); + + .ant-table-tbody>tr.ant-table-placeholder:hover>td { + background-color: transparent; + } + + .ant-table-thead>tr>th:not(:last-child):not(.ant-table-selection-column):not(.ant-table-row-expand-icon-cell):not([colspan])::before { + content: none; + } + + .ant-empty-description { + color: var(--text-color); + } +} + + +.ant-switch-checked { + background-color: var(--p); +} + +.ant-table-thead>tr>th { + border-bottom: none; + padding-top: 8px; + padding-bottom: 8px; + background-color: var(--card-hd-bg-color); +} + +.ant-pagination { + button { + background-color: transparent !important; + color: var(--text-color) !important; + } + + &-options-quick-jumper { + color: var(--text-color); + } + + &-prev, + &-next, + &-jump-prev, + &-jump-next { + color: var(--text-color); + } + + &-item-ellipsis { + color: var(--text-color) !important; + } + + &-item { + background-color: transparent; + border-color: var(--border-color); + color: var(--text-color); + + &:hover { + border-color: var(--border-color); + } + + a { + color: var(--text-color); + + &:hover { + color: var(--text-color); + } + } + + &-active { + background-color: var(--p); + border-color: var(--p); + + a { + color: var(--primary-btn-color) !important; + } + } + + + } +} + +.ant-picker-ranges { + display: flex; + align-items: center; + justify-content: space-between; + + button { + color: var(--text-color); + + &:hover { + color: var(--text-color); + } + } +} + +.ant-tag { + margin-right: 8px; + padding: 7px 12px; + border-radius: 2px; + background-color: var(--tag-bg); + border: none; + color: var(--tag-color); + + &-close-icon { + margin-left: 8px; + color: var(--tag-color); + font-size: 12px; + + &:hover { + color: var(--tag-color); + } + } +} + +.ant-form { + &-item-label>label { + color: var(--text-color); + } + + &-item-explain, + &-item-extra { + color: var(--desc-color); + } + + &-item-extra { + margin-top: 8px; + } +} + +.ant-checkbox { + &-inner { + background-color: transparent; + } +} + +.ant-tree { + &-node-content-wrapper { + // padding: 8px 12px !important; + color: #fff !important; + } +} + +.ant-tooltip { + &-inner { + background-color: #fff; + color: var(--black); + } + + .ant-tooltip-arrow-content::before { + background: #fff; + } +} + +/*************reset antd style end*************/ + +.text-label { + color: var(--purple); +} + +.dec-corner { + @corner-size: var(--corner-size); + + div { + position: absolute; + display: block; + width: @corner-size; + height: @corner-size; + z-index: 10; + + &::before, + &::after { + content: ""; + position: absolute; + background-color: var(--corner-color); + transform-origin: top left; + } + + &::before { + width: 100%; + height: 1px; + } + + &::after { + width: 1px; + height: 100%; + } + + &:nth-child(even) { + &::after { + right: 0; + } + } + + &:nth-child(1) { + top: 0; + left: 0; + } + + &:nth-child(2) { + top: 0; + right: 0; + } + + &:nth-child(3) { + bottom: 0; + left: 0; + + &::before { + bottom: 0; + } + } + + &:nth-child(4) { + bottom: 0; + right: 0; + + &::before { + bottom: 0; + } + } + } +} \ No newline at end of file diff --git a/projects/client/src/theme.less b/projects/client/src/theme.less new file mode 100644 index 0000000..cde47bc --- /dev/null +++ b/projects/client/src/theme.less @@ -0,0 +1,207 @@ +:root { + + + // --primary: rgb(94, 183, 232); + --primary: rgb(94, 183, 232); + + + --p: var(--primary); + + --p-rgb: 0, 57, 144; + + --primary-10: rgba(var(--p-rgb), 0.1); + + --primary-20: rgba(var(--p-rgb), 0.2); + + // 背景色 + --bg-color: #003990; + + // 边框色 #e8e8e8 + --border-color: #e8e8e8; + // --border-color: rgba(255, 255, 255, 0.2); + + + + // 顶部菜单背景 + --nav-bg: #e8e8e8; + + //文字颜色 + --text-color: #333; + + --thead-color: var(--text-color); + + --table-color: var(--text-color); + + --input-color: var(--text-color); + + // 标题颜色 + --title-color: var(--p); + + --desc-color: #898989; + + --thead-bg: var(--black-10); + + --tag-bg: #d1e7f4; + + --tag-color: #008cd6; + + --primary-btn-color: #fff; + + + --card-text-color: #fff; + + --card-text-color: #333; + + + --card-hd-bg-color: #e0e7f1; + + --corner-color: #003990; + + + + // ------------ + + + + + // --theme: #003990; + + // --theme-rgb: 0, 57, 144; + + // --theme-30: rgba(var(--theme-rgb), 0.3); + + // --theme-20: rgba(var(--theme-rgb), 0.2); + + // --theme-10: rgba(var(--theme-rgb), 0.1); + + // --theme-6: rgba(var(--theme-rgb), 0.06); + + + --bg-jianbian: linear-gradient(90deg, #003990 0%, #008cd6 100%); + + --blue-1: #0050a4; + + --blue-2: #008cd6; + + --blue-3: #5eb7e8; + + --blue3-rgb: 94, 183, 232; + + --blue3-10: rgba(var(--blue3-rgb), 0.1); + + --blue3-20: rgba(var(--blue3-rgb), 0.2); + + --blue-4: #9fd9f6; + + --green-1: #009944; + + --green-2: #a5d4ad; + + --red-1: #e60012; + + --red-2: #c8161d; + + --yellow: #f6ad3c; + + --dark-blue: #252166; + + --purple: #80abed; + + --black: #2c2c35; + + --black-10: rgba(0, 0, 0, 0.1); + + --gray-1: #898989; + --gray-2: #b2b3b3; + --gray-3: #cfd0d0; + --gray-4: #d9dada; + --gray-5: #e2e3e3; + --gray-6: #f7f8f8; + + --white: #ffffff; + + --white-6: rgba(255, 255, 255, 0.06); + --white-10: rgba(255, 255, 255, 0.1); + --white-20: rgba(255, 255, 255, 0.2); + --white-30: rgba(255, 255, 255, 0.3); + --white-40: rgba(255, 255, 255, 0.4); + --white-70: rgba(255, 255, 255, 0.7); + + --text-base: 16px; + + --cornerColor: red; + + + + --page-corner-bg: var(--white-30); + + --fade-white: rgba(255, 255, 255, 0.6); + + --corner-size: 6px; + + + + --btn-primary-hover-bg: var(--blue-2); + --btn-ghost-hover-border-color: var(--blue-3); +} + +@border-color-base: var(--border-color); + +// @component-background: transparent; + +@input-bg: transparent; + +@select-background: transparent; + +@picker-bg: transparent; + +@height-base: 36px; + +@primary-color: #003990; + + + +@btn-padding-horizontal-base: 16px; + +@card-head-padding: 6px; + +@radio-button-bg: #1e3571; + +@radio-button-color: #fff; + +@radio-solid-checked-color: #fff; + +@dropdown-menu-bg: #fff; + +@table-bg: transparent; + +@table-header-bg: var(--white-10); + +@table-header-color: var(--table-color); + +@table-row-hover-bg: transparent; + +// @table-border-color: var(--border-color); +@table-border-color: rgba(255, 255, 255, 0.2); + +@table-padding-vertical: 12px; + +@modal-header-padding: 7px 16px; + +@modal-header-close-size: 16px; + +@modal-body-padding: 16px; + +@tree-bg: transparent; + +@tree-title-height: 40px; + +.c-red { + color: var(--red-1); +} + +.c-green { + color: var(--green-1); +} + +// @card-head-padding-sm: 10px; \ No newline at end of file diff --git a/projects/client/tsconfig.app.json b/projects/client/tsconfig.app.json new file mode 100644 index 0000000..e4e0762 --- /dev/null +++ b/projects/client/tsconfig.app.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/projects/client/tsconfig.spec.json b/projects/client/tsconfig.spec.json new file mode 100644 index 0000000..4ac6c85 --- /dev/null +++ b/projects/client/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} \ No newline at end of file diff --git a/projects/manage/proxy.conf.json b/projects/manage/proxy.conf.json new file mode 100644 index 0000000..4b1b430 --- /dev/null +++ b/projects/manage/proxy.conf.json @@ -0,0 +1,15 @@ +{ + "/api": { + "target": "http://47.109.27.8:8081", + "secure": false + }, + "/record": { + "target": "http://47.109.27.8", + "secure": false + }, + "/websocket": { + "target": "http://47.109.27.8:8081", + "secure": false, + "ws": true + } +} diff --git a/projects/manage/src/app/app-routing.module.ts b/projects/manage/src/app/app-routing.module.ts new file mode 100644 index 0000000..f191ace --- /dev/null +++ b/projects/manage/src/app/app-routing.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from "@angular/core"; +import { Routes, RouterModule } from "@angular/router"; +import { authGuard } from "./core/gaurd/auth.guard"; + +const routes: Routes = [ + { + path: "auth", + loadChildren: () => import("./feature/auth/auth.module").then((m) => m.AuthModule), + }, + { + path: "manage", + loadChildren: () => import("./feature/manage/manage.module").then((m) => m.ManageModule), + canActivateChild: [authGuard], + }, + + { + path: "**", + redirectTo: "manage", + }, +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/projects/manage/src/app/app.component.html b/projects/manage/src/app/app.component.html new file mode 100644 index 0000000..90c6b64 --- /dev/null +++ b/projects/manage/src/app/app.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/projects/manage/src/app/app.component.less b/projects/manage/src/app/app.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/app.component.ts b/projects/manage/src/app/app.component.ts new file mode 100644 index 0000000..6870cb1 --- /dev/null +++ b/projects/manage/src/app/app.component.ts @@ -0,0 +1,35 @@ +import { Component } from "@angular/core"; +import { AuthInterface } from "@cdk/types"; +import { NgxPermissionsService } from "ngx-permissions"; + +@Component({ + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.less"], +}) +export class AppComponent { + constructor(private permissionsService: NgxPermissionsService) {} + + isCollapsed = false; + + ngOnInit() { + // const auth = localStorage.getItem("auth"); + // if (auth) { + // try { + // const authData = JSON.parse(auth) as AuthInterface; + // if (Array.isArray(authData.permissionList)) { + // const permissionList = authData.permissionList; + // const permissions = permissionList.reduce((a, c) => { + // if (c.scope === 1 && c.value === "true") { + // return a.concat(c.roleId); + // } + // return a; + // }, [] as string[]); + // this.permissionsService.loadPermissions(permissions); + // } + // } catch (error) {} + // } + } + + async getUserInfo(id: number) {} +} diff --git a/projects/manage/src/app/app.module.ts b/projects/manage/src/app/app.module.ts new file mode 100644 index 0000000..1d67ee5 --- /dev/null +++ b/projects/manage/src/app/app.module.ts @@ -0,0 +1,46 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA, APP_INITIALIZER } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; + +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { NZ_I18N } from "ng-zorro-antd/i18n"; +import { zh_CN } from "ng-zorro-antd/i18n"; +import { HashLocationStrategy, LocationStrategy, registerLocaleData } from "@angular/common"; +import zh from "@angular/common/locales/zh"; + +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; + +import { SharedModule } from "./shared/shared.module"; +import { NgxPermissionsModule, NgxPermissionsService } from "ngx-permissions"; +import { AuthInterface, DecModule } from "@cdk/public-api"; +import { environment } from "@manage/environments/environment"; +import { HttpClient, HttpClientModule } from "@angular/common/http"; + +registerLocaleData(zh); + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + BrowserAnimationsModule, + HttpClientModule, + // SharedModule, + AppRoutingModule, + DecModule.forRoot({ + environment, + localStroageKey: "manage_token", + loginUrl: "/auth/login", + }), + NgxPermissionsModule.forRoot(), + ], + providers: [ + { provide: NZ_I18N, useValue: zh_CN }, + { + provide: LocationStrategy, + useClass: HashLocationStrategy, + }, + ], + bootstrap: [AppComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], +}) +export class AppModule {} diff --git a/projects/manage/src/app/core/gaurd/auth.guard.ts b/projects/manage/src/app/core/gaurd/auth.guard.ts new file mode 100644 index 0000000..a01d0fb --- /dev/null +++ b/projects/manage/src/app/core/gaurd/auth.guard.ts @@ -0,0 +1,50 @@ +import { inject } from "@angular/core"; +import { Router } from "@angular/router"; +import { AuthInterface, decConfigToken } from "@cdk/public-api"; +import { map } from "rxjs"; +import { ManageApiService } from "../services"; +import { NgxPermissionsService } from "ngx-permissions"; + +export const authGuard = () => { + const api = inject(ManageApiService); + const router = inject(Router); + const decConfig = inject(decConfigToken); + const token = localStorage.getItem(decConfig.localStroageKey); + + if (!token) { + router.navigate([decConfig.loginUrl]); + return false; + } + + return api.getAllPoint().pipe( + map((res) => { + if (res) { + return true; + } else { + router.navigate([decConfig.loginUrl]); + return false; + } + }) + ); + + // const permissionsService = inject(NgxPermissionsService); + // const auth = localStorage.getItem("auth"); + // if (auth) { + // try { + // const authData = JSON.parse(auth) as AuthInterface; + + // if (Array.isArray(authData.permissionList)) { + // const permissionList = authData.permissionList; + // const permissions = permissionList.reduce((a, c) => { + // if (c.scope === 1 && c.value === "true") { + // return a.concat(c.roleId); + // } + // return a; + // }, [] as string[]); + // permissionsService.loadPermissions(permissions); + // console.log("this.permissionsService.getPermissions()", permissionsService.getPermissions()); + // } + // } catch (error) {} + // } + return true; +}; diff --git a/projects/manage/src/app/core/gaurd/permisson.guard.ts b/projects/manage/src/app/core/gaurd/permisson.guard.ts new file mode 100644 index 0000000..5781d5b --- /dev/null +++ b/projects/manage/src/app/core/gaurd/permisson.guard.ts @@ -0,0 +1,65 @@ +import { inject } from "@angular/core"; +import { + ActivatedRoute, + ActivatedRouteSnapshot, + CanActivateChildFn, + CanActivateFn, + Route, + Router, + RouterStateSnapshot, +} from "@angular/router"; +import { AuthInterface, decConfigToken } from "@cdk/public-api"; +import { map } from "rxjs"; +import { ManageApiService } from "../services"; +import { NgxPermissionsService } from "ngx-permissions"; + +export const PermissionLoadGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const router = inject(Router); + const permissionsService = inject(NgxPermissionsService); + + const auth = localStorage.getItem("auth"); + const children = route.parent!.routeConfig!.children; + let availableRedirect: Route = children?.find((f) => f.path === "forbidden")!; + if (auth) { + try { + const authData = JSON.parse(auth) as AuthInterface; + if (Array.isArray(authData.permissionList)) { + const permissionList = authData.permissionList; + const permissions = permissionList.reduce((a, c) => { + if (c.scope === 1 && c.value === "true") { + return a.concat(c.roleId); + } + return a; + }, [] as string[]); + permissionsService.loadPermissions(permissions); + } + } catch (error) {} + } + return true; +}; +export const PermissionGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + const router = inject(Router); + const permissionsService = inject(NgxPermissionsService); + console.log("permissionsService.getPermissions()", state); + const currentOnly = route.data["permissions"]?.only; + if (Array.isArray(currentOnly)) { + const allow = await permissionsService.hasPermission(currentOnly); + if (state.url === "/manage/station" && !allow) { + const routers = route.parent?.routeConfig?.children; + if (Array.isArray(routers)) { + for (let child of routers) { + const only = child.data?.["permissions"]?.only; + if (Array.isArray(only) && (await permissionsService.hasPermission(only))) { + router.navigate(["/manage/", child.path]); + + break; + } + console.log("child", child); + } + } + // router + } + return allow; + } + return true; +}; diff --git a/projects/manage/src/app/core/services/auth-api.service.ts b/projects/manage/src/app/core/services/auth-api.service.ts new file mode 100644 index 0000000..755ac9e --- /dev/null +++ b/projects/manage/src/app/core/services/auth-api.service.ts @@ -0,0 +1,9 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthApiService { + + constructor() { } +} diff --git a/projects/manage/src/app/core/services/index.ts b/projects/manage/src/app/core/services/index.ts new file mode 100644 index 0000000..0fbe332 --- /dev/null +++ b/projects/manage/src/app/core/services/index.ts @@ -0,0 +1,2 @@ +export * from "./auth-api.service"; +export * from "./manage-api.service"; diff --git a/projects/manage/src/app/core/services/manage-api.service.ts b/projects/manage/src/app/core/services/manage-api.service.ts new file mode 100644 index 0000000..9aa79fd --- /dev/null +++ b/projects/manage/src/app/core/services/manage-api.service.ts @@ -0,0 +1,330 @@ +import { map, of, tap } from "rxjs"; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { AnyObject, Augmented, DecText, PageResult, ResponseType } from "@cdk/types"; +import { OptionItemInterface, UserDTO, UserRoleDTO } from "@manage/dtos"; +import { PermissionItmeInterface } from "@manage/app/feature/manage/pages"; + +@Injectable({ + providedIn: "root", +}) +export class ManageApiService { + constructor(private http: HttpClient) {} + + getRoleList() { + return this.http.post>("/api/user/selectRole", null); + } + + saveRole(data: Partial) { + const url = data["roleId"] ? "/api/user/updateRole" : "/api/user/addRole"; + return this.http.post(url, data); + } + + deleteRole(roleId: DecText) { + return this.http.post("/api/user/deleteRole", { roleId }); + } + + deleteUser(uid: DecText) { + return this.http.post("/api/user/deleteUser", { uid }); + } + + saveUser(data: AnyObject) { + const url = data["id"] ? "/api/user/updateUser" : "/api/user/addUser"; + return this.http.post(url, data); + } + + getUserPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post>("/api/user/selectUser", q).pipe( + map((t) => { + return { + total: t.body.length, + content: t.body, + }; + }) + ); + } + + uploadLogo(f: FormData) { + return this.http.post("/api/config/upload", f); + } + + getSystemInfo() { + return this.http.post("/api/config/selectSystemInfo", {}); + } + + getSystemThemes() { + return this.http.post>("/api/config/selectTheme", {}); + } + + deleteOneofTheme(themeId: string) { + return this.http.post("/api/config/deleteTheme", { themeId }); + } + + saveSyetemTheme(data: {}) { + return this.http.post("/api/config/updateTheme", data); + } + + saveSyetemInfo(data: {}) { + return this.http.post("/api/config/updateSystemInfo", data); + } + + deleteOneofSystemInfo(systemInfoId: string) { + return this.http.post("/api/config/deleteSystemInfo", { systemInfoId }); + } + + getStationPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/powerStation/select", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getRolePermissions(roleId: string) { + return this.http.post>("/api/user/selectPermission", { roleId }); + } + + updateRolePermission(roleId: string, permissionList: AnyObject[]) { + return this.http.post("/api/user/updatePermission", { roleId, permissionList }); + } + + getAllStation() { + return this.http.post>("/api/powerStation/dropDownBox", {}).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + ...i, + label: i["powerStationName"], + value: i["powerStationId"], + })); + } + return []; + }) + ); + } + + saveStation(data: AnyObject) { + const url = data["powerStationId"] ? "/api/powerStation/update" : "/api/powerStation/add"; + return this.http.post(url, data); + } + + delStation(data: AnyObject) { + return this.http.post("/api/powerStation/del", data); + } + + getGroupPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/motorGroup/select", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getAllGroup() { + return this.http.post("/api/motorGroup/dropDownBox", {}).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + ...i, + label: i["motorGroupName"], + value: i["motorGroupId"], + })); + } + return []; + }) + ); + } + + saveGroup(data: AnyObject) { + const url = data["motorGroupId"] ? "/api/motorGroup/update" : "/api/motorGroup/add"; + return this.http.post(url, data); + } + + delGroup(data: AnyObject) { + return this.http.post("/api/motorGroup/del", data); + } + + getPointPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/point/select", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getAllPoint(powerStationId?: string) { + return this.http.post("/api/point/dropDownBox", { powerStationId }).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + ...i, + label: i["name"], + value: i["pointId"], + })); + } + return []; + }) + ); + } + + savePoint(data: AnyObject) { + const url = data["pointId"] ? "/api/point/update" : "/api/point/add"; + return this.http.post(url, data); + } + + delPoint(data: AnyObject) { + return this.http.post("/api/point/del", data); + } + + updatePointDetectStatus(data: AnyObject) { + return this.http.post("/api/point/updateDetect", data); + } + + getAlgorithmPage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/algorithm/select", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getAlgorithmSource() { + return this.http.post("/api/algorithm/source", {}).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + label: i, + value: i, + })); + } + return []; + }) + ); + } + + getAlgorithmNameBySource(source: string) { + return this.http.post("/api/algorithm/name", { source }).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + label: i, + value: i, + })); + } + return []; + }) + ); + } + + uploadAlgorithmFile(data: FormData) { + return this.http.post("/api/algorithm/upload", data); + } + + saveAlgorithm(data: AnyObject) { + const url = data["algorithmId"] ? "/api/algorithm/update" : "/api/algorithm/add"; + return this.http.post(url, data); + } + + getAlgorithmPoints(data: AnyObject) { + return this.http.post("/api/algorithm/selectPoints", data); + } + + getAlgorithmDetail(data: AnyObject) { + return this.http.post("/api/algorithm/selectDetail", data); + } + + delAlgorithm(data: AnyObject) { + return this.http.post("/api/algorithm/del", data); + } + + getDevicePage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/device/query", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getTemperatureDevicePage(page: {}, query: {}) { + const q = Object.assign({}, page, query); + return this.http.post("/api/device/selectTempSensor", q).pipe( + map((t) => { + return { + ...t.body, + content: t.body.data, + }; + }) + ); + } + + getTemperatureDeviceTypes() { + return this.http.post("/api/device/getSensorTypes", {}).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + label: i["type"], + value: i["typeId"], + })); + } + return []; + }) + ); + } + + updateDeviceStatus(data: AnyObject) { + return this.http.post("/api/device/deactivate", data); + } + + deleteDevice(data: AnyObject) { + return this.http.post("/api/device/del", data); + } + + saveDevice(data: AnyObject) { + const url = data["deviceId"] ? "/api/device/update" : "/api/device/add"; + return this.http.post(url, data); + } + + getDeviceTypes() { + return this.http.post("/api/device/getTypes", {}).pipe( + map((res) => { + if (Array.isArray(res.body)) { + return res.body.map((i) => ({ + label: i["vender"], + value: i["venderId"], + })); + } + return []; + }) + ); + } + + saveTemperatureDevice(data: AnyObject) { + const url = data["deviceId"] ? "/api/device/updateTempSensor" : "/api/device/addTempSensor"; + return this.http.post(url, data); + } + + deleteTemperatureDevice(data: AnyObject) { + return this.http.post("/api/device/deleteTempSensor", data); + } +} diff --git a/projects/manage/src/app/feature/auth/auth-routing.module.ts b/projects/manage/src/app/feature/auth/auth-routing.module.ts new file mode 100644 index 0000000..80cd35a --- /dev/null +++ b/projects/manage/src/app/feature/auth/auth-routing.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { LoginComponent } from "./pages"; + +const routes: Routes = [ + { + path: "login", + component: LoginComponent, + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class AuthRoutingModule {} diff --git a/projects/manage/src/app/feature/auth/auth.module.ts b/projects/manage/src/app/feature/auth/auth.module.ts new file mode 100644 index 0000000..c899f84 --- /dev/null +++ b/projects/manage/src/app/feature/auth/auth.module.ts @@ -0,0 +1,11 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { SharedModule } from "@manage/app/shared/shared.module"; +import { LoginComponent } from "./pages"; +import { AuthRoutingModule } from "./auth-routing.module"; + +@NgModule({ + declarations: [LoginComponent], + imports: [AuthRoutingModule, SharedModule], +}) +export class AuthModule {} diff --git a/projects/manage/src/app/feature/auth/pages/index.ts b/projects/manage/src/app/feature/auth/pages/index.ts new file mode 100644 index 0000000..97961b0 --- /dev/null +++ b/projects/manage/src/app/feature/auth/pages/index.ts @@ -0,0 +1 @@ +export * from "./login/login.component"; diff --git a/projects/manage/src/app/feature/auth/pages/login/login.component.html b/projects/manage/src/app/feature/auth/pages/login/login.component.html new file mode 100644 index 0000000..daf1f0e --- /dev/null +++ b/projects/manage/src/app/feature/auth/pages/login/login.component.html @@ -0,0 +1,59 @@ +
+ +
+ + +
+ +
+
\ No newline at end of file diff --git a/projects/manage/src/app/feature/auth/pages/login/login.component.less b/projects/manage/src/app/feature/auth/pages/login/login.component.less new file mode 100644 index 0000000..9126753 --- /dev/null +++ b/projects/manage/src/app/feature/auth/pages/login/login.component.less @@ -0,0 +1,49 @@ +:host { + display: block; + width: 100vw; + height: 100vh; + position: relative; + background-image: url(../../../../../assets/imgs/bg.jpg); + background-repeat: no-repeat; + background-size: cover; + &::after { + content: ""; + position: absolute; + inset: 0; + background-color: rgba(0, 0, 0, 0.3); + } +} + +.login { + position: relative; + z-index: 1; + h1 { + margin-bottom: 24px; + font-size: 24px; + font-weight: 400; + color: #fff; + } + + .logo { + display: inline-block; + height: 36px; + } + + .form { + width: 400px; + margin: 0 auto; + background-color: #fff; + border-radius: 6px; + } + + p { + font-size: 16px; + line-height: 24px; + letter-spacing: 0.23em; + text-shadow: 0px 8px 20px rgba(0, 0, 0, 0.1); + } + + .btn { + margin-top: 16px; + } +} diff --git a/projects/manage/src/app/feature/auth/pages/login/login.component.ts b/projects/manage/src/app/feature/auth/pages/login/login.component.ts new file mode 100644 index 0000000..3f2e2a1 --- /dev/null +++ b/projects/manage/src/app/feature/auth/pages/login/login.component.ts @@ -0,0 +1,48 @@ +import { Router } from "@angular/router"; +import { Component, Inject, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; +import { DecValidators } from "@cdk/validators"; +import { PUBLIC_PATH } from "@cdk/dec-module/base-href"; +import { AuthService } from "@client/app/core/services"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { finalize, lastValueFrom, tap } from "rxjs"; + +@Component({ + selector: "app-login", + templateUrl: "./login.component.html", + styleUrls: ["./login.component.less"], +}) +export class LoginComponent implements OnInit { + constructor( + @Inject(PUBLIC_PATH) public baseHref: string, + private msg: NzMessageService, + private api: AuthService, + private router: Router + ) {} + + public loginForm = new FormGroup({ + uid: new FormControl("", [DecValidators.required("请输入账户")]), + password: new FormControl("", [DecValidators.required("请输入密码")]), + }); + + public loading: boolean = false; + + ngOnInit(): void {} + + async onLogin() { + if (Utils.validateFormGroup(this.loginForm)) { + const { value } = this.loginForm; + this.loading = true; + const res = await lastValueFrom( + this.api.login(value).pipe( + finalize(() => { + this.loading = false; + }) + ) + ); + this.msg.success(res.desc); + this.router.navigate(["/"]); + } + } +} diff --git a/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.html b/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.html new file mode 100644 index 0000000..f2f6faa --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.html @@ -0,0 +1,67 @@ +
+ + + 电站 + + + + + + + + + 机组 + + + + + + + + + + + + + + + + +
+
+ + + + + + 机组/监测点 + 所属电站 + + + + + + {{ data['motorGroup'] }}/ {{data['point']}} + {{ data['powerStation'] }} + + + +
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.less b/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.ts b/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.ts new file mode 100644 index 0000000..51448e6 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/algorithm-point-select/algorithm-point-select.component.ts @@ -0,0 +1,118 @@ +import { Component, inject, OnInit } from "@angular/core"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { NZ_MODAL_DATA } from "ng-zorro-antd/modal"; + +@Component({ + selector: "app-algorithm-point-select", + templateUrl: "./algorithm-point-select.component.html", + styleUrls: ["./algorithm-point-select.component.less"], +}) +export class AlgorithmPointSelectComponent implements OnInit { + constructor(private api: ManageApiService) {} + + query = { + powerStationId: "", + motorGroupId: "", + }; + + props = inject(NZ_MODAL_DATA); + + currentGroups = []; + + checked = false; + + loading = false; + + indeterminate = false; + + listOfData: readonly AnyObject[] = []; + + listOfCurrentPageData: readonly AnyObject[] = []; + + setOfCheckedId = new Set(); + + setOfDataFromServer: AnyObject[] = []; + + public get selectedPoint(): AnyObject[] { + return this.setOfDataFromServer.filter((f) => this.setOfCheckedId.has(f["id"])); + } + + ngOnInit(): void { + this.props["val"]?.forEach((p: AnyObject) => { + this.setOfCheckedId.add(p["pointId"]); + }); + this.onSearch(); + } + + onStationChange(powerStationId: string) { + this.currentGroups = this.props["groups"].filter((f: AnyObject) => f["powerStationId"] === powerStationId); + } + + onSearch() { + this.api + .getAlgorithmPoints({ + algorithmId: this.props["algorithmId"] ?? "", + ...this.query, + }) + .subscribe((res) => { + if (Array.isArray(res.body)) { + this.listOfData = res.body.map((i) => { + return { + ...i, + id: i.pointId, + disabled: i.flag === 2, + }; + }); + } else { + this.listOfData = []; + } + this.listOfData.forEach((i) => { + if (!this.setOfDataFromServer.some((s) => s["id"] === i["id"])) { + this.setOfDataFromServer.push(i); + } + }); + // this.setOfCheckedId.clear(); + this.refreshCheckedStatus(); + }); + } + + onReset() { + this.query = { + powerStationId: "", + motorGroupId: "", + }; + this.onSearch(); + } + + updateCheckedSet(id: number, checked: boolean): void { + if (checked) { + this.setOfCheckedId.add(id); + } else { + this.setOfCheckedId.delete(id); + } + } + + onCurrentPageDataChange(listOfCurrentPageData: readonly AnyObject[]): void { + this.listOfCurrentPageData = listOfCurrentPageData; + this.refreshCheckedStatus(); + } + + refreshCheckedStatus(): void { + const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled); + this.checked = listOfEnabledData?.length > 0 && listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id)); + this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked; + } + + onItemChecked(id: number, checked: boolean): void { + this.updateCheckedSet(id, checked); + this.refreshCheckedStatus(); + } + + onAllChecked(checked: boolean): void { + this.listOfCurrentPageData + .filter(({ disabled }) => !disabled) + .forEach(({ id }) => this.updateCheckedSet(id, checked)); + this.refreshCheckedStatus(); + } +} diff --git a/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.html b/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.html new file mode 100644 index 0000000..142ff36 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.html @@ -0,0 +1,91 @@ +
+ + + 电站 + + + + + + + + + + 机组/检测点 + + + + + + + + + + 相机型号 + + + + + + + + + + 相机SN码 + + + + + + + + 相机名称 + + + + + + + + 帧率 + + + + + + + + + + 曝光时间 + + + + + + + + + + PLC-IP + + + + + + + + PLC延时参数 + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.less b/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.ts b/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.ts new file mode 100644 index 0000000..139c29c --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/camera-form/camera-form.component.ts @@ -0,0 +1,70 @@ +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-camera-form", + templateUrl: "./camera-form.component.html", + styleUrls: ["./camera-form.component.less"], +}) +export class CameraFormComponent { + constructor(private api: ManageApiService) {} + + @Input() public value?: any; + + @Input() public deviceTypes: OptionItemInterface[] = []; + + @Input() public stations: OptionItemInterface[] = []; + + groupAndPoint: OptionItemInterface[] = []; + + public formGroup = new FormGroup({ + deviceId: new FormControl(), + powerStationId: new FormControl("", [DecValidators.required("请选择电站")]), + motorGroupId: new FormControl(""), + pointId: new FormControl("", [DecValidators.required("请选择机组/检测点")]), + name: new FormControl("", [DecValidators.required("请输入相机名称"), DecValidators.maxLength(50)]), + vender: new FormControl("", [DecValidators.required("请输入相机型号")]), + sn: new FormControl("", [DecValidators.required("请输入相机SN码"), DecValidators.maxLength(50)]), + fps: new FormControl("", [DecValidators.required("请输入帧率"), DecValidators.maxLength(50)]), + exposureTime: new FormControl("", [DecValidators.required("请输入曝光时间"), DecValidators.maxLength(50)]), + plcIp: new FormControl("", [DecValidators.required("请输入PLC-IP"), DecValidators.maxLength(50)]), + plcDelay: new FormControl("", [DecValidators.required("请输入PLC延时参数"), DecValidators.maxLength(50)]), + }); + + public ngOnInit(): void { + this.formGroup.get("powerStationId")?.valueChanges.subscribe((sid) => { + this.formGroup.patchValue({ + pointId: null, + motorGroupId: null, + }); + if (sid) { + this.api.getAllPoint(sid).subscribe((res) => { + this.groupAndPoint = res; + }); + } + }); + // this.formGroup.get("pointId")?.valueChanges.subscribe((pid) => { + // const item = this.groupAndPoint.find((f) => f.value === pid); + // this.formGroup.get("motorGroupId")?.setValue(item?.["motorGroupId"]); + // }); + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + const { pointId } = this.formGroup.value; + const item = this.groupAndPoint.find((f) => f.value === pointId); + + this.formGroup.value["motorGroupId"] = item!["motorGroupId"]; + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.html b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.html new file mode 100644 index 0000000..ba41001 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.html @@ -0,0 +1,19 @@ +
+
+
+ +
+ +
+ + {{_color}} + +
+ + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.less b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.less new file mode 100644 index 0000000..8d76c9e --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.less @@ -0,0 +1,20 @@ +:host { + display: block; + width: 100%; + height: 100%; +} +.form-control { + padding: 4px 12px; + border-radius: 4px; + border: 1px solid var(--border-color); +} + +.trigger { + padding: 4px; + border: 1px solid var(--border-color); + cursor: pointer; +} + +.color-picker { + box-shadow: none; +} diff --git a/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.ts b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.ts new file mode 100644 index 0000000..a0e2815 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/color-picker/color-picker.component.ts @@ -0,0 +1,60 @@ +import { Component, EventEmitter, HostBinding, HostListener, Input, OnInit, Output } from "@angular/core"; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; +import { Color, ColorPickerControl } from "@iplab/ngx-color-picker"; + +@Component({ + selector: "app-color-picker", + templateUrl: "./color-picker.component.html", + styleUrls: ["./color-picker.component.less"], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: ColorPickerComponent, + }, + ], +}) +export class ColorPickerComponent implements OnInit, ControlValueAccessor { + constructor() {} + + @Input() mode: "simple" | "elaborate" = "elaborate"; + + @Input() public set color(color: string) { + this.colorControl.setValueFrom(color); + this._color = color; + } + + @Output() public colorChange: EventEmitter = new EventEmitter(); + + public colorControl = new ColorPickerControl(); + + public _color: string = " "; + + public ngOnInit() { + this.colorControl.valueChanges.subscribe((value: Color) => { + const color = value.toRgbaString(); + this._color = color; + this.onChange(color); + this.colorChange.emit(color); + }); + } + + onChange(v: string) {} + + onTouch(v: string) {} + + writeValue(obj: string): void { + this.colorControl.setValueFrom(obj); + this._color = obj; + } + + registerOnChange(fn: any): void { + this.onChange = fn; + } + + registerOnTouched(fn: any): void { + this.onTouch = fn; + } + + setDisabledState?(isDisabled: boolean): void {} +} diff --git a/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.html b/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.html new file mode 100644 index 0000000..a753299 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.html @@ -0,0 +1,4 @@ +
+ +

你没有此页面的访问权限。

+
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.less b/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.ts b/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.ts new file mode 100644 index 0000000..3bdfe40 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/forbidden/forbidden.component.ts @@ -0,0 +1,14 @@ +import { ActivatedRoute, Router } from "@angular/router"; +import { Component, OnInit } from "@angular/core"; +import { NgxPermissionsService } from "ngx-permissions"; + +@Component({ + selector: "app-forbidden", + templateUrl: "./forbidden.component.html", + styleUrls: ["./forbidden.component.less"], +}) +export class ForbiddenComponent implements OnInit { + constructor(private perm: NgxPermissionsService, private router: Router, private route: ActivatedRoute) {} + + async ngOnInit() {} +} diff --git a/projects/manage/src/app/feature/manage/components/home/home.component.html b/projects/manage/src/app/feature/manage/components/home/home.component.html new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/home/home.component.less b/projects/manage/src/app/feature/manage/components/home/home.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/home/home.component.ts b/projects/manage/src/app/feature/manage/components/home/home.component.ts new file mode 100644 index 0000000..ed7d59e --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/home/home.component.ts @@ -0,0 +1,30 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { NgxPermissionsService } from "ngx-permissions"; + +@Component({ + selector: "app-home", + templateUrl: "./home.component.html", + styleUrls: ["./home.component.less"], +}) +export class HomeComponent { + constructor(private perm: NgxPermissionsService, private router: Router, private route: ActivatedRoute) {} + + async ngOnInit() { + const children = this.route.parent?.routeConfig?.children; + if (Array.isArray(children)) { + for (const child of children) { + if (child.path === this.route.routeConfig?.path) { + continue; + } + const only = child.data?.["permissions"]?.only; + if (Array.isArray(only)) { + if (await this.perm.hasPermission(only)) { + this.router.navigate(["/manage", child.path]); + break; + } + } + } + } + } +} diff --git a/projects/manage/src/app/feature/manage/components/index.ts b/projects/manage/src/app/feature/manage/components/index.ts new file mode 100644 index 0000000..70422c5 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/index.ts @@ -0,0 +1,15 @@ +export * from "./layout/layout.component"; +export * from "./page/page.component"; +export * from "./station-form/station-form.component"; +export * from "./machine-form/machine-form.component"; +export * from "./point-form/point-form.component"; +export * from "./system-user-layout/system-user-layout.component"; +export * from "./user-form/user-form.component"; +export * from "./camera-form/camera-form.component"; +export * from "./temperature-form/temperature-form.component"; +export * from "./color-picker/color-picker.component"; +export * from "./algorithm-point-select/algorithm-point-select.component"; + +export * from "./forbidden/forbidden.component"; +export * from "./notfound/notfound.component"; +export * from "./home/home.component"; diff --git a/projects/manage/src/app/feature/manage/components/layout/layout.component.html b/projects/manage/src/app/feature/manage/components/layout/layout.component.html new file mode 100644 index 0000000..f9142ef --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/layout/layout.component.html @@ -0,0 +1,138 @@ + + +
+ +
+ +
+
+
+ + +
+ + + +
+ + + + + + +
    +
  • 退出登录
  • +
+
+
+
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/layout/layout.component.less b/projects/manage/src/app/feature/manage/components/layout/layout.component.less new file mode 100644 index 0000000..41bc9ea --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/layout/layout.component.less @@ -0,0 +1,84 @@ +:host { + display: flex; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +@height: 48px; + +.app-layout { + height: 100vh; +} + +.menu-sidebar { + position: relative; + z-index: 10; + height: 100%; + box-shadow: 2px 0 6px rgba(0, 21, 41, 0.35); +} + +.header-trigger { + display: inline-flex; + align-items: center; + height: @height; + padding: 0 24px; + font-size: 18px; + cursor: pointer; + transition: all 0.3s, padding 0s; +} + +.trigger:hover { + color: #1890ff; +} + +.sidebar-logo { + position: relative; + height: @height; + margin: 12px 0; + padding-left: 12px; + overflow: hidden; + line-height: @height; + background: #001529; + transition: all 0.3s; +} + +.sidebar-logo img { + display: inline-block; + // width: 32px; + height: 32px; + vertical-align: middle; +} + +.sidebar-logo h1 { + display: inline-block; + margin: 0 0 0 6px; + color: #fff; + font-weight: 600; + font-size: 16px; + font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; + vertical-align: middle; +} + +nz-header { + padding: 0; + width: 100%; + height: @height; + z-index: 2; +} + +.app-header { + position: relative; + height: @height; + padding: 0; + background: #fff; + box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); +} + +// nz-content { +// margin: 16px; +// } + +.inner-content { + height: 100%; +} diff --git a/projects/manage/src/app/feature/manage/components/layout/layout.component.ts b/projects/manage/src/app/feature/manage/components/layout/layout.component.ts new file mode 100644 index 0000000..2e791bb --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/layout/layout.component.ts @@ -0,0 +1,74 @@ +import { Component } from "@angular/core"; +import { NavigationEnd, Router } from "@angular/router"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { NgxPermissionsService } from "ngx-permissions"; +import { filter, Subject, takeUntil } from "rxjs"; +import { PermissionItmeInterface } from "../../pages"; +import { AuthInterface } from "@cdk/types"; + +@Component({ + selector: "app-layout", + templateUrl: "./layout.component.html", + styleUrls: ["./layout.component.less"], +}) +export class LayoutComponent { + constructor( + private router: Router, + private modal: NzModalService, + private msg: NzMessageService, + private permissionsService: NgxPermissionsService + ) { + this.router.events + .pipe( + takeUntil(this.unSubscribe$), + filter((e): e is NavigationEnd => e instanceof NavigationEnd) + ) + .subscribe((e) => { + this.currentUrl = e.url; + }); + } + + unSubscribe$ = new Subject(); + + isCollapsed = false; + + currentUrl: string = ""; + + userName = ""; + + ngOnInit() { + const auth = localStorage.getItem("auth"); + + if (auth) { + try { + const authData = JSON.parse(auth) as AuthInterface; + if (authData.userName) { + this.userName = authData.userName; + } + if (Array.isArray(authData.permissionList)) { + const permissionList = authData.permissionList; + const permissions = permissionList.reduce((a, c) => { + if (c.scope === 1 && c.value === "true") { + return a.concat(c.roleId); + } + return a; + }, [] as string[]); + this.permissionsService.loadPermissions(permissions); + } + } catch (error) {} + } + } + + louout() { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要退出登录?", + nzOnOk: () => { + localStorage.clear(); + this.msg.success("已退出登录"); + this.router.navigate(["/auth/login"]); + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.html b/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.html new file mode 100644 index 0000000..85e0b94 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.html @@ -0,0 +1,40 @@ +
+ + + 电站 + + + + + + + + 机组编号 + + + + + + + + + + 联系人 + + + + + + + + 联系电话 + + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.less b/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.ts b/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.ts new file mode 100644 index 0000000..a34c574 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/machine-form/machine-form.component.ts @@ -0,0 +1,40 @@ +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-machine-form", + templateUrl: "./machine-form.component.html", + styleUrls: ["./machine-form.component.less"], +}) +export class MachineFormComponent { + constructor() {} + + @Input() public value?: any; + + @Input() public stations: OptionItemInterface[] = []; + + public formGroup = new FormGroup({ + motorGroupId: new FormControl(), + number: new FormControl("", [DecValidators.required("请输入编号"), DecValidators.maxLength(50)]), + powerStationId: new FormControl("", [DecValidators.required("请选择电站")]), + contact: new FormControl("", [DecValidators.maxLength(50)]), + phone: new FormControl("", [DecValidators.maxLength(50)]), + }); + + public ngOnInit(): void { + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/components/notfound/notfound.component.html b/projects/manage/src/app/feature/manage/components/notfound/notfound.component.html new file mode 100644 index 0000000..df4b62f --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/notfound/notfound.component.html @@ -0,0 +1,6 @@ +
+ +

+ 此页面未找到。 +

+
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/notfound/notfound.component.less b/projects/manage/src/app/feature/manage/components/notfound/notfound.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/notfound/notfound.component.ts b/projects/manage/src/app/feature/manage/components/notfound/notfound.component.ts new file mode 100644 index 0000000..0368db3 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/notfound/notfound.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-notfound', + templateUrl: './notfound.component.html', + styleUrls: ['./notfound.component.less'] +}) +export class NotfoundComponent { + +} diff --git a/projects/manage/src/app/feature/manage/components/page/page.component.html b/projects/manage/src/app/feature/manage/components/page/page.component.html new file mode 100644 index 0000000..d5b26fd --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/page/page.component.html @@ -0,0 +1,12 @@ + + + +
+ +
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/page/page.component.less b/projects/manage/src/app/feature/manage/components/page/page.component.less new file mode 100644 index 0000000..b4bebaa --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/page/page.component.less @@ -0,0 +1,5 @@ +:host { + display: flex; + flex-direction: column; + height: 100%; +} diff --git a/projects/manage/src/app/feature/manage/components/page/page.component.ts b/projects/manage/src/app/feature/manage/components/page/page.component.ts new file mode 100644 index 0000000..99ab104 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/page/page.component.ts @@ -0,0 +1,13 @@ +import { Component, Input, ViewEncapsulation } from "@angular/core"; + +@Component({ + selector: "app-page", + templateUrl: "./page.component.html", + styleUrls: ["./page.component.less"], + // encapsulation: ViewEncapsulation.None, +}) +export class PageComponent { + constructor() {} + + @Input() pageTitle: string = ""; +} diff --git a/projects/manage/src/app/feature/manage/components/point-form/point-form.component.html b/projects/manage/src/app/feature/manage/components/point-form/point-form.component.html new file mode 100644 index 0000000..2821983 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/point-form/point-form.component.html @@ -0,0 +1,63 @@ +
+ + + 电站 + + + + + + + + 机组 + + + + + + + + 检测点 + + + + + + + + 磁极数量 + + + + + + + + + + + 手动检测时长 + + + + + + + + + + + 自动检测时长 + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/point-form/point-form.component.less b/projects/manage/src/app/feature/manage/components/point-form/point-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/point-form/point-form.component.ts b/projects/manage/src/app/feature/manage/components/point-form/point-form.component.ts new file mode 100644 index 0000000..a98766f --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/point-form/point-form.component.ts @@ -0,0 +1,65 @@ +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-point-form", + templateUrl: "./point-form.component.html", + styleUrls: ["./point-form.component.less"], +}) +export class PointFormComponent { + constructor() {} + + @Input() public value?: any; + + @Input() public stations: OptionItemInterface[] = []; + + @Input() public groups: OptionItemInterface[] = []; + + currentGroups: OptionItemInterface[] = []; + + public formGroup = new FormGroup({ + pointId: new FormControl(), + name: new FormControl("", [DecValidators.required("请输入检测点"), DecValidators.maxLength(50)]), + powerStationId: new FormControl("", [DecValidators.required("请选择电站")]), + motorGroupId: new FormControl("", [DecValidators.required("请选择机组")]), + poleNum: new FormControl("", [ + DecValidators.required("请输入磁极数量"), + DecValidators.min(1), + DecValidators.max(999), + ]), + manualTime: new FormControl("", [ + DecValidators.required("请输入手动检测时长"), + DecValidators.min(0), + DecValidators.max(600), + ]), + automaticTime: new FormControl("", [ + DecValidators.required("请输入自动检测时长"), + DecValidators.min(0), + DecValidators.max(600), + ]), + }); + + public ngOnInit(): void { + this.formGroup.get("powerStationId")?.valueChanges.subscribe((powerStationId) => { + this.currentGroups = this.groups.filter((f) => f["powerStationId"] === powerStationId); + const motorGroupId = this.formGroup.get("motorGroupId"); + if (!this.currentGroups.some((s) => s.value === motorGroupId?.value)) { + motorGroupId?.setValue(null); + } + }); + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/components/station-form/station-form.component.html b/projects/manage/src/app/feature/manage/components/station-form/station-form.component.html new file mode 100644 index 0000000..5e4869c --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/station-form/station-form.component.html @@ -0,0 +1,45 @@ +
+ + + 电站名称 + + + + + + + + 地址 + + + + + + + + 联系人 + + + + + + + + 联系电话 + + + + + + + + 电站简介 + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/station-form/station-form.component.less b/projects/manage/src/app/feature/manage/components/station-form/station-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/station-form/station-form.component.ts b/projects/manage/src/app/feature/manage/components/station-form/station-form.component.ts new file mode 100644 index 0000000..7732ac4 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/station-form/station-form.component.ts @@ -0,0 +1,39 @@ +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-station-form", + templateUrl: "./station-form.component.html", + styleUrls: ["./station-form.component.less"], +}) +export class StationFormComponent { + constructor() {} + + @Input() public value?: any; + + public formGroup = new FormGroup({ + powerStationId: new FormControl(), + name: new FormControl("", [DecValidators.required("请输入名称"), DecValidators.maxLength(50)]), + address: new FormControl("", [DecValidators.maxLength(50)]), + contact: new FormControl("", [DecValidators.maxLength(50)]), + phone: new FormControl("", [DecValidators.maxLength(50)]), + introduction: new FormControl("", [DecValidators.maxLength(200)]), + }); + + public ngOnInit(): void { + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.html b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.html new file mode 100644 index 0000000..a8228fd --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.html @@ -0,0 +1,77 @@ + +
+
+ +
+
    +
  • +
    + + {{role.roleName}} + +
    + + +
    +
    +
  • + + +
+
+ +
+
+
+
+
+ + + + + + + + + + + + + + +
+
+
+ + +
+ + + 角色名称 + + + + + +
+
+ + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.less b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.less new file mode 100644 index 0000000..4951830 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.less @@ -0,0 +1,10 @@ +.role-item { + .actions { + display: none; + } + &:hover { + .actions { + display: block; + } + } +} diff --git a/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.ts b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.ts new file mode 100644 index 0000000..bd4bc9c --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/system-user-layout/system-user-layout.component.ts @@ -0,0 +1,103 @@ +import { lastValueFrom } from "rxjs"; +import { ManageApiService } from "@manage/app/core/services"; +import { Component, OnInit, TemplateRef, ViewEncapsulation } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Utils } from "@cdk/utils"; +import { DecValidators } from "@cdk/validators"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { UserRoleDTO } from "@manage/dtos"; +import { ActivatedRoute, Router } from "@angular/router"; + +@Component({ + selector: "app-system-user-layout", + templateUrl: "./system-user-layout.component.html", + styleUrls: ["./system-user-layout.component.less"], + encapsulation: ViewEncapsulation.None, +}) +export class SystemUserLayoutComponent implements OnInit { + constructor( + private modal: NzModalService, + private msg: NzMessageService, + private api: ManageApiService, + private router: Router, + private route: ActivatedRoute + ) {} + + tab: string = "0"; + + roles: UserRoleDTO[] = []; + + currentRole!: UserRoleDTO; + + formGroup = new FormGroup({ + roleId: new FormControl(), + roleName: new FormControl("", [DecValidators.required("请输入角色名称"), DecValidators.maxLength(50)]), + }); + + ngOnInit(): void { + this.getRoleList(); + this.route.queryParams.subscribe((res) => { + this.tab = res?.["tab"] ?? "0"; + }); + } + + getRoleList() { + this.api.getRoleList().subscribe((res) => { + this.roles = res.body.sort((a, b) => (a.isRoot === b.isRoot ? 0 : a.isRoot ? -1 : 1)); + if (!this.currentRole) { + this.currentRole = this.roles?.[0]; + } + }); + } + + openForm(nzContent: TemplateRef<{}>, e: Event, v?: UserRoleDTO) { + e.stopPropagation(); + if (v) { + this.formGroup.patchValue(v); + } + this.modal.create({ + nzTitle: v ? "编辑管理员角色" : "添加管理员角色", + nzContent, + nzOnCancel: this.onFormCancel.bind(this), + nzOnOk: async () => { + if (Utils.validateFormGroup(this.formGroup)) { + await lastValueFrom(this.api.saveRole(this.formGroup.value)); + this.msg.success("保存成功"); + this.getRoleList(); + this.onFormCancel(); + return true; + } + return false; + }, + }); + } + + onFormCancel() { + this.formGroup.reset({ + roleName: "", + roleId: void 0, + }); + } + + onDeleteRole(v: UserRoleDTO) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该角色", + nzOnOk: async () => { + await lastValueFrom(this.api.deleteRole(v.roleId!)); + this.msg.success("删除成功"); + this.getRoleList(); + }, + }); + } + + onSelectedIndexChange(idx: number) { + this.router.navigate(["/manage/system/user"], { + queryParams: { + tab: idx, + }, + queryParamsHandling: "merge", + }); + } +} diff --git a/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.html b/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.html new file mode 100644 index 0000000..fa018d8 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.html @@ -0,0 +1,63 @@ +
+ + + 电站 + + + + + + + + + + 机组/检测点 + + + + + + + + + + 关联设备 + + + + + + + + + + 传感器型号 + + + + + + + + + 传感器名称 + + + + + + + + 串口号 + + + + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.less b/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.ts b/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.ts new file mode 100644 index 0000000..0c740b4 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/temperature-form/temperature-form.component.ts @@ -0,0 +1,88 @@ +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { AnyObject, DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { distinctUntilChanged } from "rxjs"; + +@Component({ + selector: "app-temperature-form", + templateUrl: "./temperature-form.component.html", + styleUrls: ["./temperature-form.component.less"], +}) +export class TemperatureFormComponent { + constructor(private api: ManageApiService) {} + + @Input() public value?: any; + + @Input() public stations: OptionItemInterface[] = []; + + @Input() public typeList: OptionItemInterface[] = []; + + groupAndPoint: OptionItemInterface[] = []; + + cameraList: OptionItemInterface[] = []; + + public formGroup = new FormGroup({ + deviceId: new FormControl(), + powerStationId: new FormControl("", [DecValidators.required("请选择电站")]), + motorGroupId: new FormControl(""), + pointId: new FormControl("", [DecValidators.required("请选择机组/检测点")]), + relatedDeviceId: new FormControl("", [DecValidators.required("请选择关联设备")]), + name: new FormControl("", [DecValidators.required("请输入传感器名称"), DecValidators.maxLength(50)]), + typeId: new FormControl("", [DecValidators.required("请输入传感器型号")]), + serialPort: new FormControl(""), + }); + + public ngOnInit(): void { + this.formGroup + .get("powerStationId") + ?.valueChanges.pipe(distinctUntilChanged()) + .subscribe((sid) => { + this.formGroup.get("pointId")?.setValue(null); + if (sid) { + this.api.getAllPoint(sid).subscribe((res) => { + this.groupAndPoint = res; + this.formGroup.get("pointId")?.patchValue(this.formGroup.get("pointId")?.value!); + }); + } + }); + this.formGroup + .get("pointId") + ?.valueChanges.pipe(distinctUntilChanged()) + .subscribe((pid) => { + this.formGroup.patchValue({ + relatedDeviceId: null, + }); + + if (pid) { + this.getCameraListByPointId(pid); + } + }); + + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + getCameraListByPointId(pointId: string) { + this.api.getDevicePage({}, { pointId }).subscribe((res) => { + if (Array.isArray(res["data"])) { + this.cameraList = res.data.map((i: AnyObject) => ({ value: i["deviceId"], label: i["name"] })); + } + }); + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + const { pointId } = this.formGroup.value; + const item = this.groupAndPoint.find((f) => f.value === pointId); + + this.formGroup.value["motorGroupId"] = item!["motorGroupId"]; + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/components/user-form/user-form.component.html b/projects/manage/src/app/feature/manage/components/user-form/user-form.component.html new file mode 100644 index 0000000..67fc5b8 --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/user-form/user-form.component.html @@ -0,0 +1,30 @@ +
+ + + 账号 + + + + + + + + 姓名 + + + + + + + + 密码 + + + + + + +
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/components/user-form/user-form.component.less b/projects/manage/src/app/feature/manage/components/user-form/user-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/components/user-form/user-form.component.ts b/projects/manage/src/app/feature/manage/components/user-form/user-form.component.ts new file mode 100644 index 0000000..61c7fbc --- /dev/null +++ b/projects/manage/src/app/feature/manage/components/user-form/user-form.component.ts @@ -0,0 +1,38 @@ +import { ManageApiService } from "@manage/app/core/services"; +import { Component, Input } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { DecValidators } from "@cdk/public-api"; +import { Utils } from "@cdk/utils"; +import { UserDTO } from "@manage/dtos"; + +@Component({ + selector: "app-user-form", + templateUrl: "./user-form.component.html", + styleUrls: ["./user-form.component.less"], +}) +export class UserFormComponent { + constructor(private api: ManageApiService) {} + + @Input() public value?: UserDTO; + + public formGroup = new FormGroup({ + id: new FormControl(), + uid: new FormControl("", [DecValidators.required("请输入账号"), DecValidators.maxLength(50)]), + userName: new FormControl("", [DecValidators.required("请输入姓名"), DecValidators.maxLength(50)]), + password: new FormControl("", [DecValidators.required("请输入密码"), DecValidators.maxLength(50)]), + }); + + public ngOnInit(): void { + if (this.value) { + this.formGroup.patchValue(this.value); + } + } + + public getValues() { + let values = null; + if (Utils.validateFormGroup(this.formGroup)) { + values = this.formGroup.value; + } + return values; + } +} diff --git a/projects/manage/src/app/feature/manage/manage-routing.module.ts b/projects/manage/src/app/feature/manage/manage-routing.module.ts new file mode 100644 index 0000000..a492af4 --- /dev/null +++ b/projects/manage/src/app/feature/manage/manage-routing.module.ts @@ -0,0 +1,209 @@ +import { PointComponent } from "./pages/point/point.component"; +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { + ForbiddenComponent, + HomeComponent, + LayoutComponent, + NotfoundComponent, + SystemUserLayoutComponent, +} from "./components"; +import { + MachineComponent, + StationComponent, + PermissionComponent, + UserListComponent, + CameraComponent, + TemperatureComponent, + AlgorithmListComponent, + AlgorithmFormComponent, + SystemInfoComponent, + SystemThemeComponent, +} from "./pages"; +import { NgxPermissionsGuard } from "ngx-permissions"; +import { PermissionGuard, PermissionLoadGuard } from "@manage/app/core/gaurd/permisson.guard"; + +const routes: Routes = [ + { + path: "", + component: LayoutComponent, + canActivateChild: [PermissionLoadGuard], + children: [ + { + path: "", + pathMatch: "full", + redirectTo: "home", + }, + { + path: "home", + component: HomeComponent, + }, + { + path: "station", + component: StationComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_powerstation"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "machine", + component: MachineComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_motorgroup"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "point", + component: PointComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_point"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "device", + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_device_camer_plc", "role_device_tempsensor"], + redirectTo: "/manage/forbidden", + }, + }, + children: [ + { + path: "", + pathMatch: "full", + redirectTo: "camera", + }, + { + path: "camera", + component: CameraComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_device_camer_plc"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "temperature", + component: TemperatureComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_device_tempsensor"], + redirectTo: "/manage/forbidden", + }, + }, + }, + ], + }, + { + path: "algorithm", + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_algorithm"], + redirectTo: "/manage/forbidden", + }, + }, + children: [ + { + path: "", + pathMatch: "full", + redirectTo: "list", + }, + { + path: "list", + component: AlgorithmListComponent, + }, + { + path: "form/:id", + component: AlgorithmFormComponent, + }, + ], + }, + { + path: "system", + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_sys_info", "role_sys_theme", "role_sys_user"], + redirectTo: "/manage/forbidden", + }, + }, + children: [ + { + path: "info", + component: SystemInfoComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_sys_info"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "theme", + component: SystemThemeComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_sys_theme"], + redirectTo: "/manage/forbidden", + }, + }, + }, + { + path: "user", + component: SystemUserLayoutComponent, + canActivate: [NgxPermissionsGuard], + data: { + permissions: { + only: ["role_sys_user"], + redirectTo: "/manage/forbidden", + }, + }, + // children: [ + // { + // path: "list", + // component: UserListComponent, + // }, + // { + // path: "role", + // component: RoleComponent, + // }, + // ], + }, + ], + }, + { + path: "forbidden", + component: ForbiddenComponent, + }, + { + path: "**", + component: NotfoundComponent, + }, + ], + }, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class ManageRoutingModule {} diff --git a/projects/manage/src/app/feature/manage/manage.module.ts b/projects/manage/src/app/feature/manage/manage.module.ts new file mode 100644 index 0000000..9eb7774 --- /dev/null +++ b/projects/manage/src/app/feature/manage/manage.module.ts @@ -0,0 +1,67 @@ +import { NgModule } from "@angular/core"; +import { ColorPickerModule } from "@iplab/ngx-color-picker"; +import { ManageRoutingModule } from "./manage-routing.module"; +import { SharedModule } from "@manage/app/shared/shared.module"; + +import { + LayoutComponent, + PageComponent, + StationFormComponent, + MachineFormComponent, + PointFormComponent, + SystemUserLayoutComponent, + UserFormComponent, + CameraFormComponent, + TemperatureFormComponent, + ColorPickerComponent, + AlgorithmPointSelectComponent, + ForbiddenComponent, + NotfoundComponent, + HomeComponent, +} from "./components"; +import { + StationComponent, + MachineComponent, + PointComponent, + UserListComponent, + CameraComponent, + TemperatureComponent, + AlgorithmListComponent, + AlgorithmFormComponent, + SystemInfoComponent, + SystemThemeComponent, + PermissionComponent, +} from "./pages"; +import { NgxPermissionsModule } from "ngx-permissions"; + +@NgModule({ + declarations: [ + LayoutComponent, + PageComponent, + StationComponent, + StationFormComponent, + MachineComponent, + MachineFormComponent, + PointComponent, + PointFormComponent, + SystemUserLayoutComponent, + UserListComponent, + PermissionComponent, + UserFormComponent, + CameraComponent, + TemperatureComponent, + CameraFormComponent, + TemperatureFormComponent, + AlgorithmListComponent, + AlgorithmFormComponent, + SystemInfoComponent, + SystemThemeComponent, + ColorPickerComponent, + AlgorithmPointSelectComponent, + ForbiddenComponent, + NotfoundComponent, + HomeComponent, + ], + imports: [SharedModule, ManageRoutingModule, ColorPickerModule, NgxPermissionsModule.forChild()], +}) +export class ManageModule {} diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.html b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.html new file mode 100644 index 0000000..768b367 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.html @@ -0,0 +1,75 @@ + +
+ + + + 算法来源 + + + + + + + + 算法 + + + + + + + + 算法文件 + + + +
+ {{fileName}} +
+ +
+
+
+ + + + 算法应用机组/检测点 + + + +
+ + {{p['powerStation']}}/{{p['motorGroup']}}/{{p['point']}} + + + + +
+
+
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.less b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.ts b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.ts new file mode 100644 index 0000000..3083772 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-form/algorithm-form.component.ts @@ -0,0 +1,164 @@ +import { AnyObject } from "./../../../../../../../../cdk/src/types/index"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { finalize } from "rxjs"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { DecValidators } from "@cdk/validators"; +import { Utils } from "@cdk/utils"; +import { AlgorithmPointSelectComponent } from "../../../components"; + +@Component({ + selector: "app-algorithm-form", + templateUrl: "./algorithm-form.component.html", + styleUrls: ["./algorithm-form.component.less"], +}) +export class AlgorithmFormComponent implements OnInit { + constructor( + private route: ActivatedRoute, + private router: Router, + private api: ManageApiService, + private fb: FormBuilder, + private msg: NzMessageService, + private modal: NzModalService + ) {} + + id: null | string = null; + + source: OptionItemInterface[] = []; + + algorithms: OptionItemInterface[] = []; + + stations: OptionItemInterface[] = []; + + groups: OptionItemInterface[] = []; + + form!: FormGroup; + + importDataLoading = false; + + submitLoading = false; + + get points() { + return this.form.get("points") as FormControl; + } + + ngOnInit(): void { + const id = this.route.snapshot.paramMap.get("id"); + const query = this.route.snapshot.queryParamMap; + + this.id = id === "create" ? null : id; + + this.initForm(); + + if (this.id) { + this.api.getAlgorithmDetail({ algorithmId: this.id }).subscribe((res) => { + this.form.patchValue({ + ...res.body, + points: res.body?.["ranges"] ?? [], + }); + }); + query.keys.forEach((i) => { + this.form.patchValue({ + [i]: query.get(i), + }); + }); + } + + this.api.getAlgorithmSource().subscribe((source) => { + this.source = source; + }); + + this.api.getAllStation().subscribe((res) => { + this.stations = res; + }); + this.api.getAllGroup().subscribe((res) => { + this.groups = res; + }); + } + + initForm() { + this.form = this.fb.group({ + algorithmName: this.fb.control("", [DecValidators.required()]), + source: this.fb.control("", [DecValidators.required()]), + algorithmFileName: this.fb.control(""), + points: this.fb.control([]), + }); + this.form.get("source")?.valueChanges.subscribe((source) => { + this.form.get("algorithmName")?.setValue(null); + if (source) { + this.api.getAlgorithmNameBySource(source).subscribe((res) => { + this.algorithms = res; + }); + } + }); + } + + onFileChange(e: Event) { + const target = e.target as HTMLInputElement; + const file = target.files![0]; + target.value = ""; + const formData = new FormData(); + formData.append("file", file); + this.importDataLoading = true; + this.api + .uploadAlgorithmFile(formData) + .pipe( + finalize(() => { + this.importDataLoading = false; + }) + ) + .subscribe(() => { + this.msg.success("上传成功"); + this.form.patchValue({ + algorithmFileName: file.name, + }); + }); + } + + showPointSelectModal() { + this.modal.create({ + nzTitle: "添加机组监测点", + nzWidth: 820, + nzData: { + algorithmId: this.id, + stations: this.stations, + groups: this.groups, + val: this.points.value, + }, + nzContent: AlgorithmPointSelectComponent, + nzOnOk: (e) => { + const points = e.selectedPoint; + this.points.setValue(points); + }, + }); + } + + onRemovePoint(idx: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该监测点?", + nzOnOk: () => { + const val = (this.points?.value ?? []) as AnyObject[]; + this.points.setValue(val.filter((_, i) => idx !== i)); + }, + }); + } + + onSubmit() { + if (Utils.validateFormGroup(this.form)) { + this.api + .saveAlgorithm({ + ...this.form.value, + algorithmId: this.id, + }) + .subscribe((res) => { + this.msg.success(res.desc); + this.router.navigate(["/manage/algorithm/list"]); + }); + } + } +} diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.html b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.html new file mode 100644 index 0000000..dcbba18 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.html @@ -0,0 +1,32 @@ + + + + + + + + + + + 算法名称 + + + + + + + + 算法来源 + + + + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.less b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.ts b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.ts new file mode 100644 index 0000000..43c917e --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/algorithm/algorithm-list/algorithm-list.component.ts @@ -0,0 +1,87 @@ +import { lastValueFrom } from "rxjs"; +import { Component, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; + +@Component({ + selector: "app-algorithm-list", + templateUrl: "./algorithm-list.component.html", + styleUrls: ["./algorithm-list.component.less"], +}) +export class AlgorithmListComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + public tableList = new TableListOption(this.fetchData.bind(this)); + + source: OptionItemInterface[] = []; + + public queryForm = new FormGroup({ + algorithmName: new FormControl(""), + source: new FormControl(""), + }); + + ngOnInit(): void { + this.initTableList(); + this.api.getAlgorithmSource().subscribe((source) => { + this.source = source; + }); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getAlgorithmPage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "算法名称" }, + { key: "source", title: "算法来源" }, + { key: "group_point_num", title: "关联机组/监测点数量" }, + { key: "gmtCreate", title: "添加时间" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: (v) => { + this.router.navigate(["/manage/algorithm/form", v["algorithmId"]], { + queryParams: { + algorithmName: v["name"], + source: v["source"], + }, + }); + }, + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该算法?", + nzOnOk: async () => { + await lastValueFrom(this.api.delAlgorithm(v)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.html b/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.html new file mode 100644 index 0000000..9714031 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.html @@ -0,0 +1,80 @@ + + + + + + + + + + + 名称/SN码 + + + + + + + + 电站 + + + + + + + + + 机组/检测点 + + + + + + + + + 状态 + + + + + + + + + + + + + + + + + + + {{data}} + + + + + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.less b/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.ts b/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.ts new file mode 100644 index 0000000..7d7236a --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/device/camera/camera.component.ts @@ -0,0 +1,184 @@ +import { finalize, lastValueFrom } from "rxjs"; +import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; +import { Component, OnInit, TemplateRef, ViewChild } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { CameraFormComponent } from "../../../components"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-camera", + templateUrl: "./camera.component.html", + styleUrls: ["./camera.component.less"], +}) +export class CameraComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private drawer: NzDrawerService, + private msg: NzMessageService + ) {} + + @ViewChild("formFooter") formFooter!: TemplateRef<{}>; + + deviceTypes: OptionItemInterface[] = []; + + stations: OptionItemInterface[] = []; + + groupAndPoint: OptionItemInterface[] = []; + + submitLoading = false; + + public tableList = new TableListOption(this.fetchData.bind(this)); + + public queryForm = new FormGroup({ + name: new FormControl(""), + powerStationId: new FormControl(""), + motorGroupId: new FormControl(""), + pointId: new FormControl(""), + status: new FormControl(""), + }); + + public drawerRef?: NzDrawerRef; + + ngOnInit(): void { + this.initTableList(); + this.queryForm.get("powerStationId")?.valueChanges.subscribe((sid) => { + this.queryForm.get("pointId")?.setValue(null); + if (sid) { + this.api.getAllPoint(sid).subscribe((res) => { + this.groupAndPoint = res; + }); + } + }); + this.queryForm.get("pointId")?.valueChanges.subscribe((pid) => { + const item = this.groupAndPoint.find((f) => f.value === pid); + + this.queryForm.get("motorGroupId")?.setValue(item?.["motorGroupId"]); + }); + this.api.getDeviceTypes().subscribe((deviceTypes) => { + this.deviceTypes = deviceTypes; + }); + this.api.getAllStation().subscribe((stations) => { + this.stations = stations; + }); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getDevicePage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "相机名称" }, + { key: "sn", title: "SN码" }, + { key: "plcIp", title: "PLC-IP" }, + { key: "powerStation", title: "所属电站" }, + { key: "group_Point", title: "机组/检测点" }, + { key: "fps", title: "帧率(fps)" }, + { key: "exposureTime", title: "曝光时间(ms)" }, + { key: "status", title: "工作状态" }, + { key: "gmtCreate", title: "添加日期" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "停用", + premissions: [], + visible: (v) => { + return v["status"] === 1; + }, + onClick: this.updateStatus.bind(this), + }, + { + title: "启用", + premissions: [], + visible: (v) => { + return v["status"] === 0; + }, + onClick: this.updateStatus.bind(this), + }, + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该相机?", + nzOnOk: async () => { + await lastValueFrom(this.api.deleteDevice(v)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } + + updateStatus(v: AnyObject) { + const text = v["status"] === 0 ? "启用" : "停用"; + const status = v["status"] === 0 ? 1 : 0; + this.modal.confirm({ + nzTitle: "警告", + nzContent: `是否要${text}该相机?`, + nzOnOk: async () => { + const res = await lastValueFrom(this.api.updateDeviceStatus({ ...v, status })); + this.tableList.run(); + this.msg.success(res.desc); + }, + }); + } + + openForm(v?: any) { + this.drawerRef = this.drawer.create({ + nzTitle: v ? "编辑相机" : "新增相机", + nzWidth: 660, + nzContent: CameraFormComponent, + nzContentParams: { value: v, deviceTypes: this.deviceTypes, stations: this.stations }, + nzOnCancel: this.onCancel.bind(this), + nzFooter: this.formFooter, + }); + } + + async onCancel() { + this.drawerRef?.close(); + } + + submitForm() { + if (this.drawerRef) { + const form = this.drawerRef.getContentComponent()!; + const value = form.getValues(); + this.submitLoading = true; + if (value) { + this.api + .saveDevice(value) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe(() => { + this.msg.success("保存成功"); + this.onCancel(); + this.tableList.run(); + }); + } + } + } +} diff --git a/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.html b/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.html new file mode 100644 index 0000000..b581f57 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.html @@ -0,0 +1,67 @@ + + + + + + + + + + + 名称/串口 + + + + + + + + 电站 + + + + + + + + 机组/检测点 + + + + + + + + 状态 + + + + + + + + + + + + + + + + + + + {{data}} + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.less b/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.ts b/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.ts new file mode 100644 index 0000000..22b4882 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/device/temperature/temperature.component.ts @@ -0,0 +1,129 @@ +import { NzDrawerRef, NzDrawerService } from "ng-zorro-antd/drawer"; +import { Component, OnInit, TemplateRef, ViewChild } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { TemperatureFormComponent } from "../../../components"; +import { OptionItemInterface } from "@manage/dtos"; +import { lastValueFrom } from "rxjs"; + +@Component({ + selector: "app-temperature", + templateUrl: "./temperature.component.html", + styleUrls: ["./temperature.component.less"], +}) +export class TemperatureComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + @ViewChild("formFooter") formFooter!: TemplateRef<{}>; + + public tableList = new TableListOption(this.fetchData.bind(this)); + + public queryForm = new FormGroup({ + nameOrSerialPort: new FormControl(""), + powerStationId: new FormControl(""), + pointId: new FormControl(""), + status: new FormControl(""), + }); + + deviceTypes: OptionItemInterface[] = []; + + stations: OptionItemInterface[] = []; + + groupAndPoint: OptionItemInterface[] = []; + + typeList: OptionItemInterface[] = []; + + ngOnInit(): void { + this.initTableList(); + + this.queryForm.get("powerStationId")?.valueChanges.subscribe((sid) => { + this.queryForm.get("pointId")?.setValue(null); + if (sid) { + this.api.getAllPoint(sid).subscribe((res) => { + this.groupAndPoint = res; + }); + } + }); + + this.api.getAllStation().subscribe((stations) => { + this.stations = stations; + }); + this.api.getTemperatureDeviceTypes().subscribe((res) => { + this.typeList = res; + }); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getTemperatureDevicePage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "测温传感器名称" }, + { key: "type", title: "传感器类型" }, + { key: "powerStation", title: "所属电站" }, + { key: "group_Point", title: "机组/检测点" }, + { key: "relatedDevice", title: "关联设备" }, + { key: "status", title: "测温传感器状态" }, + { key: "gmtCreate", title: "添加时间" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该传感器?", + + nzOnOk: async () => { + const res = await lastValueFrom(this.api.deleteTemperatureDevice(v)); + this.tableList.run(); + this.msg.success(res.desc); + }, + }); + } + + openForm(v?: any) { + this.modal.create({ + nzTitle: v ? "编辑传感器" : "新增传感器", + nzWidth: 660, + nzContent: TemperatureFormComponent, + nzComponentParams: { value: v, stations: this.stations, typeList: this.typeList }, + nzOnOk: async (e) => { + const value = e.getValues(); + if (value) { + console.log("value", value); + const res = await lastValueFrom(this.api.saveTemperatureDevice(value)); + this.msg.success(res.desc); + this.tableList.run(); + return true; + } + return false; + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/index.ts b/projects/manage/src/app/feature/manage/pages/index.ts new file mode 100644 index 0000000..157bea5 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/index.ts @@ -0,0 +1,14 @@ +export * from "./station/station.component"; +export * from "./machine/machine.component"; +export * from "./point/point.component"; + +export * from "./device/camera/camera.component"; +export * from "./device/temperature/temperature.component"; + +export * from "./system/user/user-list/user-list.component"; +export * from "./system/user/permission/permission.component"; +export * from "./system/system-info/system-info.component"; +export * from "./system/system-theme/system-theme.component"; + +export * from "./algorithm/algorithm-list/algorithm-list.component"; +export * from "./algorithm/algorithm-form/algorithm-form.component"; diff --git a/projects/manage/src/app/feature/manage/pages/machine/machine.component.html b/projects/manage/src/app/feature/manage/pages/machine/machine.component.html new file mode 100644 index 0000000..67cc7ad --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/machine/machine.component.html @@ -0,0 +1,31 @@ + + + + + + + + + + + 机组编号 + + + + + + + + 电站 + + + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/machine/machine.component.less b/projects/manage/src/app/feature/manage/pages/machine/machine.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/machine/machine.component.ts b/projects/manage/src/app/feature/manage/pages/machine/machine.component.ts new file mode 100644 index 0000000..507afb8 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/machine/machine.component.ts @@ -0,0 +1,111 @@ +import { lastValueFrom } from "rxjs"; +import { Component, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { MachineFormComponent } from "../../components"; + +@Component({ + selector: "app-machine", + templateUrl: "./machine.component.html", + styleUrls: ["./machine.component.less"], +}) +export class MachineComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + stations: OptionItemInterface[] = []; + + public tableList = new TableListOption(this.fetchData.bind(this)); + + public queryForm = new FormGroup({ + number: new FormControl(""), + powerStationId: new FormControl(""), + }); + + ngOnInit(): void { + this.initTableList(); + this.api.getAllStation().subscribe((res) => { + this.stations = res; + }); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getGroupPage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "机组编号" }, + { key: "powerStation", title: "所属电站" }, + { key: "pointNum", title: "监测点数量" }, + { key: "contact", title: "联系人" }, + { key: "phone", title: "联系电话" }, + { key: "gmtCreate", title: "添加日期" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "是否要删除该机组?", + nzClassName: "danger-confirm", + nzContent: "警告:删除后将删除该机组及机组下所有检测点信息,且不可恢复。", + nzOkDanger: true, + nzOnOk: async () => { + await lastValueFrom(this.api.delGroup(v)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } + + openForm(v?: any) { + let value = Object.create(null); + if (v) { + value = { + ...v, + number: v["name"]?.split("#")?.[0], + }; + } + this.modal.create({ + nzTitle: v ? "编辑机组" : "新增机组", + nzContent: MachineFormComponent, + nzComponentParams: { value, stations: this.stations }, + nzOnOk: async (e) => { + const value = e.getValues(); + if (value) { + await lastValueFrom(this.api.saveGroup(value)); + this.msg.success("保存成功"); + this.tableList.run(); + return true; + } + + return false; + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/point/point.component.html b/projects/manage/src/app/feature/manage/pages/point/point.component.html new file mode 100644 index 0000000..b8a59e1 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/point/point.component.html @@ -0,0 +1,65 @@ + + + + + + + + + + + 检测点名称 + + + + + + + + 电站 + + + + + + + + + 机组 + + + + + + + + + + + + + + + + + + + + {{data}} + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/point/point.component.less b/projects/manage/src/app/feature/manage/pages/point/point.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/point/point.component.ts b/projects/manage/src/app/feature/manage/pages/point/point.component.ts new file mode 100644 index 0000000..2841848 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/point/point.component.ts @@ -0,0 +1,137 @@ +import { lastValueFrom } from "rxjs"; +import { Component, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { PointFormComponent } from "../../components"; + +@Component({ + selector: "app-point", + templateUrl: "./point.component.html", + styleUrls: ["./point.component.less"], +}) +export class PointComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + public tableList = new TableListOption(this.fetchData.bind(this)); + + stations: OptionItemInterface[] = []; + + groups: OptionItemInterface[] = []; + + currentGroups: OptionItemInterface[] = []; + + public queryForm = new FormGroup({ + id: new FormControl(""), + powerStationId: new FormControl(""), + motorGroupId: new FormControl(""), + name: new FormControl(""), + }); + + ngOnInit(): void { + this.initTableList(); + this.queryForm.get("powerStationId")?.valueChanges.subscribe((powerStationId) => { + this.currentGroups = this.groups.filter((f) => f["powerStationId"] === powerStationId); + this.queryForm.get("motorGroupId")?.setValue(null); + }); + this.api.getAllStation().subscribe((res) => { + this.stations = res; + this.queryForm.get("powerStationId"); + }); + this.api.getAllGroup().subscribe((res) => { + this.groups = res; + }); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getPointPage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "检测点名称" }, + { key: "motorGroup", title: "机组编号" }, + { key: "poleNum", title: "磁极数量" }, + { key: "boltDetect", title: "螺栓松动检测" }, + { key: "lineDetect", title: "引出线变形检测" }, + { key: "poleOpenDetect", title: "磁极开匝检测" }, + { key: "pointTempDetect", title: "检测点温度检测" }, + { key: "gmtCreate", title: "添加日期" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "是否要删除该检测点?", + nzClassName: "danger-confirm", + nzContent: "警告:删除后将删除该检测点信息,且不可恢复。", + nzOkDanger: true, + nzOnOk: async () => { + await lastValueFrom(this.api.delPoint(v)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } + + onDetectChange(k: string, row: AnyObject) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该检测类型?", + nzOnOk: async () => { + await lastValueFrom( + this.api.updatePointDetectStatus({ + ...row, + [k]: !row[k], + }) + ); + this.tableList.run(); + this.msg.success("操作成功"); + }, + }); + } + + openForm(v?: any) { + this.modal.create({ + nzTitle: v ? "编辑检测点" : "新增检测点", + nzContent: PointFormComponent, + nzComponentParams: { value: v, stations: this.stations, groups: this.groups }, + nzOnOk: async (e) => { + const value = e.getValues(); + if (value) { + await lastValueFrom(this.api.savePoint(value)); + this.msg.success("保存成功"); + this.tableList.run(); + return true; + } + + return false; + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/station/station.component.html b/projects/manage/src/app/feature/manage/pages/station/station.component.html new file mode 100644 index 0000000..36bc6a5 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/station/station.component.html @@ -0,0 +1,22 @@ + + + + + + + + + + + 电站名称 + + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/station/station.component.less b/projects/manage/src/app/feature/manage/pages/station/station.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/station/station.component.ts b/projects/manage/src/app/feature/manage/pages/station/station.component.ts new file mode 100644 index 0000000..11073c4 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/station/station.component.ts @@ -0,0 +1,97 @@ +import { lastValueFrom } from "rxjs"; +import { Component, OnInit } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { StationFormComponent } from "../../components"; +import { OptionItemInterface } from "@manage/dtos"; + +@Component({ + selector: "app-station", + templateUrl: "./station.component.html", + styleUrls: ["./station.component.less"], +}) +export class StationComponent implements OnInit { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + public tableList = new TableListOption(this.fetchData.bind(this)); + + public queryForm = new FormGroup({ + name: new FormControl(""), + }); + + ngOnInit(): void { + this.initTableList(); + } + + fetchData(query: AnyObject, pager: AnyObject) { + return this.api.getStationPage(pager, query); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "name", title: "电站名称" }, + { key: "address", title: "地址", width: "40%" }, + { key: "groupNum", title: "机组数量" }, + { key: "contact", title: "联系人" }, + { key: "phone", title: "联系电话" }, + { key: "gmtCreate", title: "添加时间" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "是否要删除该电站?", + nzClassName: "danger-confirm", + nzContent: "警告:删除后将删除该电站及电站下所有机组、检测点信息,且不可恢复。", + nzOkDanger: true, + nzOnOk: async () => { + await lastValueFrom(this.api.delStation(v)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } + + openForm(v?: any) { + this.modal.create({ + nzTitle: v ? "编辑电站" : "新增电站", + nzContent: StationFormComponent, + nzComponentParams: { value: v }, + nzOnOk: async (e) => { + const value = e.getValues(); + if (value) { + await lastValueFrom(this.api.saveStation(value)); + this.msg.success("保存成功"); + this.tableList.run(); + return true; + } + return false; + }, + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.html b/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.html new file mode 100644 index 0000000..08ff020 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.html @@ -0,0 +1,102 @@ + + +
+ + + + + + + + + + 前端检测系统logo + + + +
+ +
+ + +
+
+ +
+ + +
+
+ + + 企业名称 + + + + + + + + 前端检测系统名称 + + + + + + + + 应用电站 + + + + + + +
+ +
+ +
+ +
+ + +
+
+
+ + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.less b/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.ts b/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.ts new file mode 100644 index 0000000..721e563 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/system-info/system-info.component.ts @@ -0,0 +1,158 @@ +import { Component, OnInit } from "@angular/core"; +import { FormArray, FormBuilder, FormGroup } from "@angular/forms"; +import { AnyObject } from "@cdk/types"; +import { Utils } from "@cdk/utils"; +import { DecValidators } from "@cdk/validators"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { finalize, lastValueFrom } from "rxjs"; + +@Component({ + selector: "app-system-info", + templateUrl: "./system-info.component.html", + styleUrls: ["./system-info.component.less"], +}) +export class SystemInfoComponent implements OnInit { + constructor( + private fb: FormBuilder, + private msg: NzMessageService, + private api: ManageApiService, + private modal: NzModalService + ) {} + + formGroup!: FormGroup; + + public get infos(): FormArray { + return this.formGroup.get("infos") as FormArray; + } + + loading = true; + + uploadLoading = false; + + submitLoading = false; + + stations: OptionItemInterface[] = []; + + // currentStations: OptionItemInterface[] = []; + + ngOnInit(): void { + this.api.getAllStation().subscribe((res) => { + this.stations = res; + }); + this.getInfo(); + this.formGroup = this.fb.group({ + infos: this.fb.array([]), + }); + } + + getInfo() { + this.api + .getSystemInfo() + .pipe( + finalize(() => { + this.loading = false; + }) + ) + .subscribe((res) => { + if (Array.isArray(res.body)) { + this.infos.clear(); + res.body.forEach((i) => { + this.newInfo(i); + }); + } + }); + } + + newInfo(value?: AnyObject) { + const powerStations = (value?.["powerStations"] ?? []) as AnyObject[]; + const powerStationsVal = powerStations.map((i) => i["powerStationId"]); + const infoGroup = this.fb.group({ + systemInfoId: this.fb.control(value?.["systemInfoId"]), + systemInfoName: this.fb.control(value?.["systemInfoName"], [DecValidators.required()]), + reservedField: this.fb.control(value?.["reservedField"]), + logoImg: this.fb.control(value?.["logoImg"], [DecValidators.required()]), + logoFileName: this.fb.control(value?.["logoFileName"], [DecValidators.required()]), + powerStations: this.fb.control(powerStationsVal, []), + }); + this.infos.push(infoGroup); + return infoGroup; + } + + onFileChange(e: Event, index: number) { + const target = e.target as HTMLInputElement; + const file = target.files![0]; + target.value = ""; + const formData = new FormData(); + const fileReader = new FileReader(); + fileReader.onload = () => { + const base64 = fileReader.result as string; + this.infos.at(index).get("logoImg")?.setValue(base64.split("base64,")[1]); + }; + formData.append("file", file); + this.uploadLoading = true; + this.api + .uploadLogo(formData) + .pipe( + finalize(() => { + this.uploadLoading = false; + }) + ) + .subscribe((r) => { + this.msg.success(r.desc); + fileReader.readAsDataURL(file); + this.infos.at(index).get("logoFileName")?.setValue(file.name); + }); + } + + deleteItem(idx: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该信息策略?", + nzOnOk: async () => { + const systemInfoId: string = this.infos.at(idx).get("systemInfoId")?.value; + if (systemInfoId) { + await lastValueFrom(this.api.deleteOneofSystemInfo(systemInfoId)); + } + this.infos.removeAt(idx); + this.msg.success("删除成功"); + }, + }); + } + + onSelectOpen(idx: number) { + const currentInfoStations = (this.infos.at(idx).get("powerStations")?.value ?? []) as string[]; + const allStation = this.infos.controls.reduce( + (a, c) => a.concat(c.get("powerStations")?.value ?? []), + [] as string[] + ); + this.stations = this.stations.map((i) => { + i["disabled"] = false; + if (allStation.some((s) => s === i.value)) { + if (!currentInfoStations.some((s) => s === i.value)) { + i["disabled"] = true; + } + } + return i; + }); + } + + onSubmit() { + if (Utils.validateFormGroup(this.formGroup)) { + this.submitLoading = true; + this.api + .saveSyetemInfo(this.formGroup.value.infos) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe((res) => { + this.msg.success(res.desc); + this.getInfo(); + }); + } + } +} diff --git a/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.html b/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.html new file mode 100644 index 0000000..3516a87 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.html @@ -0,0 +1,182 @@ + + +
+ + + + + + + + + + 应用电站 + + + + + + + + + + + 主题色 + + + + + + + + + 主题色文字颜色 + + + + + + + + + 背景颜色 + + + + + + + + + 边框颜色 + + + + + + + + + 顶部菜单背景色 + + + + + + + + + 系统标题颜色 + + + + + + + + 文字颜色 + + + + + + + + + 描述文字颜色 + + + + + + + + + 表头背景色 + + + + + + + + + 标签背景色 + + + + + + + + + 标签文字颜色 + + + + + + + + + 卡片文字颜色 + + + + + + + + 卡片头部背景色 + + + + + + + + 卡片角颜色 + + + + + + + + + + + + +
+ +
+ + +
+
+
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.less b/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.ts b/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.ts new file mode 100644 index 0000000..032c6c6 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/system-theme/system-theme.component.ts @@ -0,0 +1,141 @@ +import { Component, OnInit } from "@angular/core"; +import { FormArray, FormBuilder, FormGroup } from "@angular/forms"; +import { AnyObject } from "@cdk/types"; +import { Utils } from "@cdk/utils"; +import { DecValidators } from "@cdk/validators"; +import { ManageApiService } from "@manage/app/core/services"; +import { OptionItemInterface } from "@manage/dtos"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { finalize, lastValueFrom } from "rxjs"; + +@Component({ + selector: "app-system-theme", + templateUrl: "./system-theme.component.html", + styleUrls: ["./system-theme.component.less"], +}) +export class SystemThemeComponent { + constructor( + private fb: FormBuilder, + private api: ManageApiService, + private msg: NzMessageService, + private modal: NzModalService + ) {} + + formGroup!: FormGroup; + + public get themes(): FormArray { + return this.formGroup.get("themes") as FormArray; + } + + stations: OptionItemInterface[] = []; + + loading = true; + + submitLoading = false; + + ngOnInit(): void { + this.api.getAllStation().subscribe((res) => { + this.stations = res; + }); + this.getThemes(); + this.formGroup = this.fb.group({ + themes: this.fb.array([]), + }); + } + + getThemes() { + this.api + .getSystemThemes() + .pipe( + finalize(() => { + this.loading = false; + }) + ) + .subscribe((res) => { + if (Array.isArray(res.body)) { + this.themes.clear(); + res.body.forEach((i) => { + this.newTheme(i); + }); + } + }); + } + + newTheme(v?: AnyObject) { + const powerStations = (v?.["powerStationList"] ?? []) as AnyObject[]; + const powerStationsVal = powerStations.map((i) => i["powerStationId"]); + + const themeGroup = this.fb.group({ + themeId: this.fb.control(v?.["themeId"]), + powerStationList: this.fb.control(powerStationsVal), + themeName: this.fb.control(v?.["themeName"] ?? ""), + + primary: this.fb.control(v?.["primary"] ?? "rgba(255,255,255,1)"), + primary_btn_color: this.fb.control(v?.["primary_btn_color"] ?? "rgba(255,255,255,1)"), + bg_color: this.fb.control(v?.["bg_color"] ?? "rgba(255,255,255,1)"), + border_color: this.fb.control(v?.["border_color"] ?? "rgba(255,255,255,1)"), + title_color: this.fb.control(v?.["title_color"] ?? "rgba(255,255,255,1)"), + nav_bg: this.fb.control(v?.["nav_bg"] ?? "rgba(255,255,255,1)"), + text_color: this.fb.control(v?.["text_color"] ?? "rgba(255,255,255,1)"), + desc_color: this.fb.control(v?.["desc_color"] ?? "rgba(255,255,255,1)"), + thead_bg: this.fb.control(v?.["thead_bg"] ?? "rgba(255,255,255,1)"), + tag_bg: this.fb.control(v?.["tag_bg"] ?? "rgba(255,255,255,1)"), + tag_color: this.fb.control(v?.["tag_color"] ?? "rgba(255,255,255,1)"), + card_text_color: this.fb.control(v?.["card_text_color"] ?? "rgba(255,255,255,1)"), + card_hd_bg_color: this.fb.control(v?.["card_hd_bg_color"] ?? "rgba(255,255,255,1)"), + corner_color: this.fb.control(v?.["corner_color"] ?? "rgba(255,255,255,1)"), + }); + this.themes.push(themeGroup); + return themeGroup; + } + + deleteItem(idx: number) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该主题策略?", + nzOnOk: async () => { + const themeId: string = this.themes.at(idx).get("systemInfoId")?.value; + if (themeId) { + await lastValueFrom(this.api.deleteOneofTheme(themeId)); + } + this.themes.removeAt(idx); + this.msg.success("删除成功"); + }, + }); + } + + onSelectOpen(idx: number) { + const currentInfoStations = (this.themes.at(idx).get("powerStationList")?.value ?? []) as string[]; + const allStation = this.themes.controls.reduce( + (a, c) => a.concat(c.get("powerStationList")?.value ?? []), + [] as string[] + ); + this.stations = this.stations.map((i) => { + i["disabled"] = false; + if (allStation.some((s) => s === i.value)) { + if (!currentInfoStations.some((s) => s === i.value)) { + i["disabled"] = true; + } + } + return i; + }); + } + + onSubmit() { + if (Utils.validateFormGroup(this.formGroup)) { + this.submitLoading = true; + this.api + .saveSyetemTheme(this.formGroup.value.themes) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe((res) => { + this.msg.success(res.desc); + this.getThemes(); + }); + } + } +} diff --git a/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.html b/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.html new file mode 100644 index 0000000..b8b38f4 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.html @@ -0,0 +1,30 @@ + + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ +
+ + + +
\ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.less b/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.ts b/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.ts new file mode 100644 index 0000000..0de0702 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/user/permission/permission.component.ts @@ -0,0 +1,172 @@ +import { ManageApiService } from "@manage/app/core/services"; +import { Component, Input, OnChanges, OnInit, SimpleChanges } from "@angular/core"; +import { OptionItemInterface } from "@manage/dtos"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { finalize } from "rxjs"; + +const defaultAllPermissions = [ + { + permissionId: "role_powerstation", + permissionName: "电站管理", + value: true, + scope: 1, //0-前端页面,1-后台管理 + }, + { + permissionId: "role_motorgroup", + permissionName: "机组管理", + value: true, + scope: 1, + }, + { + permissionId: "role_point", + permissionName: "检测点管理", + value: true, + scope: 1, + }, + { + permissionId: "role_device_camer_plc", + permissionName: "设备管理-相机/PLC管理", + value: true, + scope: 1, + }, + { + permissionId: "role_device_tempsensor", + permissionName: "设备管理-测温传感器管理", + value: true, + scope: 1, + }, + { + permissionId: "role_algorithm", + permissionName: "算法模型管理", + value: true, + scope: 1, + }, + { + permissionId: "role_sys_info", + permissionName: "系统管理-系统信息管理", + value: true, + scope: 1, + }, + { + permissionId: "role_sys_theme", + permissionName: "系统管理-主题管理", + value: true, + scope: 1, + }, + { + permissionId: "role_sys_user", + permissionName: "系统管理-用户管理", + value: true, + scope: 1, + }, + { + permissionId: "role_pole", + permissionName: "检测页面", + value: true, + scope: 0, + }, + { + permissionId: "role_history", + permissionName: "历史数据", + value: true, + scope: 0, + }, + { + permissionId: "role_analysis", + permissionName: "数据分析", + value: true, + scope: 0, + }, + { + permissionId: "role_settings_show", + permissionName: "高级设置-检测点检测管理", + value: true, + scope: 0, + }, + { + permissionId: "role_settings_bolt", + permissionName: "高级设置-检测算法设置", + value: true, + scope: 0, + }, + { + permissionId: "role_settings_temp", + permissionName: "高级设置-工作保护温度设置", + value: true, + scope: 0, + }, + { + permissionId: "role_settings_sys", + permissionName: "高级设置-系统设置", + value: true, + scope: 0, + }, +]; + +export type PermissionItmeInterface = (typeof defaultAllPermissions)[number]; + +@Component({ + selector: "app-permission", + templateUrl: "./permission.component.html", + styleUrls: ["./permission.component.less"], +}) +export class PermissionComponent implements OnInit, OnChanges { + constructor(private api: ManageApiService, private msg: NzMessageService) {} + + @Input() role: any; + + public permissions: PermissionItmeInterface[] = defaultAllPermissions; + + public client: PermissionItmeInterface[] = []; + + public manage: PermissionItmeInterface[] = []; + + submitLoading = false; + + ngOnInit(): void { + this.permissions.forEach((i) => { + if (i.scope === 0) { + this.client.push(i); + } else { + this.manage.push(i); + } + }); + } + + getPermission() { + this.api.getRolePermissions(this.role.roleId).subscribe((res) => { + if (Array.isArray(res.body)) { + this.client = []; + this.manage = []; + this.permissions.forEach((i) => { + const item = res.body.find((f) => f.permissionId === i.permissionId && i.scope === f.scope) ?? i; + if (i.scope === 0) { + this.client.push(item); + } else { + this.manage.push(item); + } + }); + } + }); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes["role"]?.currentValue) { + this.getPermission(); + } + } + + onSave() { + this.submitLoading = true; + this.api + .updateRolePermission(this.role.roleId, this.client.concat(this.manage)) + .pipe( + finalize(() => { + this.submitLoading = false; + }) + ) + .subscribe((res) => { + this.msg.success(res.desc); + }); + } +} diff --git a/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.html b/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.html new file mode 100644 index 0000000..feedb10 --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.html @@ -0,0 +1,20 @@ + + + + + + + + + + 姓名 + + + + + + + \ No newline at end of file diff --git a/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.less b/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.less new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.ts b/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.ts new file mode 100644 index 0000000..b9f83db --- /dev/null +++ b/projects/manage/src/app/feature/manage/pages/system/user/user-list/user-list.component.ts @@ -0,0 +1,105 @@ +import { Component, Input, OnInit, SimpleChanges } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TableListOption } from "@cdk/table-list"; +import { AnyObject } from "@cdk/types"; +import { ManageApiService } from "@manage/app/core/services"; +import { UserRoleDTO } from "@manage/dtos"; +import { format } from "date-fns"; +import { NzMessageService } from "ng-zorro-antd/message"; +import { NzModalService } from "ng-zorro-antd/modal"; +import { lastValueFrom } from "rxjs"; +import { UserFormComponent } from "../../../../components"; + +@Component({ + selector: "app-user-list", + templateUrl: "./user-list.component.html", + styleUrls: ["./user-list.component.less"], +}) +export class UserListComponent { + constructor( + private api: ManageApiService, + private router: Router, + private modal: NzModalService, + private msg: NzMessageService + ) {} + + @Input() role!: UserRoleDTO; + + public tableList = new TableListOption(this.fetchData.bind(this), { + manual: true, + }); + + public queryForm = new FormGroup({ + userName: new FormControl(""), + }); + + ngOnInit(): void { + this.initTableList(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes["role"]?.currentValue) { + this.tableList.run(); + } + } + + fetchData(query: AnyObject, pager: AnyObject) { + query["role"] = this.role.roleId; + return this.api.getUserPage(query, pager); + } + + initTableList() { + this.tableList.scroll = { x: null }; + this.tableList = this.tableList.setColumns([ + { key: "uid", title: "用户" }, + { key: "userName", title: "姓名" }, + { key: "role", title: "角色" }, + { key: "gmtCreate", title: "添加时间" }, + ]); + + this.tableList = this.tableList.setOptions([ + { + title: "编辑", + premissions: [], + onClick: this.openForm.bind(this), + }, + { + title: "删除", + premissions: [], + onClick: this.deleteItem.bind(this), + }, + ]); + } + + deleteItem(v: any) { + this.modal.confirm({ + nzTitle: "警告", + nzContent: "是否要删除该用户?", + nzOnOk: async () => { + await lastValueFrom(this.api.deleteUser(v.uid!)); + this.tableList.run(); + this.msg.success("删除成功"); + }, + }); + } + + openForm(v?: any) { + this.modal.create({ + nzTitle: v ? "编辑用户" : "新增用户", + nzContent: UserFormComponent, + nzComponentParams: { value: v }, + nzOnOk: async (e) => { + const value = e.getValues(); + if (value) { + const vals = Object.assign({}, value, { role: this.role.roleId! }); + await lastValueFrom(this.api.saveUser(vals)); + this.msg.success("保存成功"); + this.tableList.run(); + return true; + } + return false; + }, + }); + } +} diff --git a/projects/manage/src/app/icons-provider.module.ts b/projects/manage/src/app/icons-provider.module.ts new file mode 100644 index 0000000..8096966 --- /dev/null +++ b/projects/manage/src/app/icons-provider.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { NZ_ICONS, NzIconModule } from 'ng-zorro-antd/icon'; + +import { + MenuFoldOutline, + MenuUnfoldOutline, + FormOutline, + DashboardOutline +} from '@ant-design/icons-angular/icons'; + +const icons = [MenuFoldOutline, MenuUnfoldOutline, DashboardOutline, FormOutline]; + +@NgModule({ + imports: [NzIconModule], + exports: [NzIconModule], + providers: [ + { provide: NZ_ICONS, useValue: icons } + ] +}) +export class IconsProviderModule { +} diff --git a/projects/manage/src/app/shared/components/index.ts b/projects/manage/src/app/shared/components/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/app/shared/ng-zorro.ts b/projects/manage/src/app/shared/ng-zorro.ts new file mode 100644 index 0000000..d429aee --- /dev/null +++ b/projects/manage/src/app/shared/ng-zorro.ts @@ -0,0 +1,100 @@ +import { NzGridModule } from "ng-zorro-antd/grid"; +import { NzCardModule } from "ng-zorro-antd/card"; +import { NzStatisticModule } from "ng-zorro-antd/statistic"; +import { NzIconModule } from "ng-zorro-antd/icon"; +import { NzToolTipModule } from "ng-zorro-antd/tooltip"; +import { NzTableModule } from "ng-zorro-antd/table"; +import { NzSegmentedModule } from "ng-zorro-antd/segmented"; +import { NzSpaceModule } from "ng-zorro-antd/space"; +import { NzDatePickerModule } from "ng-zorro-antd/date-picker"; +import { NzListModule } from "ng-zorro-antd/list"; +import { NzInputModule } from "ng-zorro-antd/input"; +import { NzButtonModule } from "ng-zorro-antd/button"; +import { NzTagModule } from "ng-zorro-antd/tag"; +import { NzBadgeModule } from "ng-zorro-antd/badge"; +import { NzPaginationModule } from "ng-zorro-antd/pagination"; +import { NzDividerModule } from "ng-zorro-antd/divider"; +import { NzSelectModule } from "ng-zorro-antd/select"; +import { NzModalModule } from "ng-zorro-antd/modal"; +import { NzMessageModule } from "ng-zorro-antd/message"; +import { NzDrawerModule } from "ng-zorro-antd/drawer"; +import { NzFormModule } from "ng-zorro-antd/form"; +import { NzDescriptionsModule } from "ng-zorro-antd/descriptions"; +import { NzTabsModule } from "ng-zorro-antd/tabs"; +import { NzProgressModule } from "ng-zorro-antd/progress"; +import { NzAvatarModule } from "ng-zorro-antd/avatar"; +import { NzMenuModule } from "ng-zorro-antd/menu"; +import { NzDropDownModule } from "ng-zorro-antd/dropdown"; +import { NzTreeSelectModule } from "ng-zorro-antd/tree-select"; +import { NzRadioModule } from "ng-zorro-antd/radio"; +import { NzCheckboxModule } from "ng-zorro-antd/checkbox"; +import { NzCalendarModule } from "ng-zorro-antd/calendar"; +import { NzSkeletonModule } from "ng-zorro-antd/skeleton"; +import { NzTimelineModule } from "ng-zorro-antd/timeline"; +import { NzEmptyModule } from "ng-zorro-antd/empty"; +import { NzSpinModule } from "ng-zorro-antd/spin"; +import { NzResultModule } from "ng-zorro-antd/result"; +import { NzCascaderModule } from "ng-zorro-antd/cascader"; +import { NzAutocompleteModule } from "ng-zorro-antd/auto-complete"; +import { NzPopoverModule } from "ng-zorro-antd/popover"; +import { NzPageHeaderModule } from "ng-zorro-antd/page-header"; +import { NzTreeModule } from "ng-zorro-antd/tree"; +import { NzSwitchModule } from "ng-zorro-antd/switch"; +import { NzCarouselModule } from "ng-zorro-antd/carousel"; +import { NzTimePickerModule } from "ng-zorro-antd/time-picker"; +import { NzImageModule } from "ng-zorro-antd/image"; +import { NzInputNumberModule } from "ng-zorro-antd/input-number"; +import { NzLayoutModule } from "ng-zorro-antd/layout"; +import { NzBreadCrumbModule } from "ng-zorro-antd/breadcrumb"; + +export const ngZorroModules = [ + NzBreadCrumbModule, + NzLayoutModule, + NzInputNumberModule, + NzImageModule, + NzTimePickerModule, + NzCarouselModule, + NzSwitchModule, + NzTreeModule, + NzPageHeaderModule, + NzPopoverModule, + NzAutocompleteModule, + NzCascaderModule, + NzResultModule, + NzSpinModule, + NzGridModule, + NzCardModule, + NzStatisticModule, + NzIconModule, + NzToolTipModule, + NzTableModule, + NzSegmentedModule, + NzSpaceModule, + NzDatePickerModule, + NzListModule, + NzInputModule, + NzButtonModule, + NzTagModule, + NzBadgeModule, + NzPaginationModule, + NzDividerModule, + NzSelectModule, + NzSelectModule, + NzModalModule, + NzMessageModule, + NzDrawerModule, + NzFormModule, + NzDescriptionsModule, + NzTabsModule, + NzProgressModule, + NzAvatarModule, + NzMenuModule, + NzDropDownModule, + NzTreeSelectModule, + NzRadioModule, + NzCalendarModule, + NzCheckboxModule, + NzSkeletonModule, + NzTimelineModule, + NzEmptyModule, +]; diff --git a/projects/manage/src/app/shared/shared.module.ts b/projects/manage/src/app/shared/shared.module.ts new file mode 100644 index 0000000..56fdc0d --- /dev/null +++ b/projects/manage/src/app/shared/shared.module.ts @@ -0,0 +1,38 @@ +import { RouterModule } from "@angular/router"; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { HttpClientModule } from "@angular/common/http"; +import { ngZorroModules } from "./ng-zorro"; +// import { AuthorizationLayoutComponent, BgBorderComponent } from "./components"; +// import { DecCornerDirective } from "./directives"; +import { + DecModule, + FormErrorTipsComponent, + InputSpaceErrorDirective, + PublicPathPipe, + TableListModule, + StorageModule, + QuickDateRangeComponent, +} from "@cdk/public-api"; +import { environment } from "@manage/environments/environment"; +import { NgxPermissionsModule } from "ngx-permissions"; + +const ngModules = [CommonModule, HttpClientModule, FormsModule, RouterModule, ReactiveFormsModule]; +const components: any = []; +const directives: any[] = []; +const cdks = [ + FormErrorTipsComponent, + InputSpaceErrorDirective, + PublicPathPipe, + TableListModule, + StorageModule, + QuickDateRangeComponent, +]; + +@NgModule({ + declarations: [...components, ...directives], + imports: [DecModule, ...ngZorroModules, ...ngModules, ...cdks], + exports: [...ngZorroModules, ...ngModules, ...components, ...directives, ...cdks], +}) +export class SharedModule {} diff --git a/projects/manage/src/assets/.gitkeep b/projects/manage/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/projects/manage/src/assets/imgs/bg.jpg b/projects/manage/src/assets/imgs/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..31bed57aefb336b3902b9a6c4b087a90b4f481fd GIT binary patch literal 474548 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%0ATl#QhQuNmK|m`m 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%0D3A_%W@w?a&ZjkvyM~ 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 z�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 pm^ItCM^9=NjcW;~ zY~VbVBd0+j;lvsR<`2sA%7q-9WKOswxyG4}$o0i~%ChKeD!f68-ZB}Fzf1`oWr;3F zyJx-`?>1)eypIDK0_XyXI%&F@LnJGFnG+m+5V@AN@afV65`HQegb;&Cun@V>sY?~; zSuQAPRQ#@1Kr-DCwLS%38HC9ugV#?ZBPyFL3`BBeidM#B(C$%Oxg%-OTsxg-3~a9c zcG*seYhUTFT{fO-6tcdDK%MsAt;hZRZbA|3Y*swbUj_ozNx>L5YP_xWh>CMS8qQuX zA9+PH!PYG54y~3e2rI0TUb2yY;OYGu{*UNcw71Jy;VDGk?0dlh8pA`)D=V>6qy)oC zmZA3%3~2}u$;nvBD^dE6Y#0?~k-dzNyCP;jMe7`+-hHyBwKx7d@@ zZA}xYgo_Ep6iNrx6G_Q{N(MwL6Yt-ljc2TBJ4V!M5FVaWj~+M-c3jTSm^DEMK?l@~KW9d#I9U*13^?to#=3R%{O zX}}Y;z9wBgAeArWiNU7R-?Xkht`x}e(Rjjlso6c%HK#fQKMjT|H*i*5TGJ>`i44u@ zO1MSkX)kc{TpcoU>W9U4U)5VvQr8d9+?(kTV$P29M?Er<_MM1+C2W5U#X*tpU1&*5 z8bGNUvDu#+!|Y%-gW7j1(y~{sW9rkCK2Nv`>GQ|{q(=RmUdUx>NDn0sD?&+{)ywFM zZ{UATm*3eGEsIIR+mX`X1#gc=I9`gf>U`rs^t>h3f1WpYmw|W(Jl=qE(kjBvAlJdS zsy^xXA{0i7RN9tm##`-AhUpBzmf8J7W2K6LdK}{FK|lLS<)mg#DXD9vK(U~U3k3ZJ zXg0wLSUO*)(p7Rt=?dgpJBr$z=kVMBie0wmtfG>Nh4E7VrJ1taa$ed#(yPA@GU9B1i3GfE9$Wb(VL#J&#$|wfvI& zV-;LqR6;@wuCsX{2t9ZTJutA4j0DhI|73L0lwOyOT^75GQXGiW851#b$SixHDP2rH z;*$3t;Sc^2^=GF4h?4&3SS!>c9IMjML2Xd}F@Siv(vwAqnpH{N-Qf;#*=78WM>O$s zokkhT$iU5SFBq~PF3!1M@;5oNT!YS*9PP@iQ6=+?BkJv#LK14GRanY+DaEw~80O@5 zDh=4!@ZpSK!e0J?Fif*(QWzTwUD8N|mAwm3^9S>!g2Dw*=f-$k!-`m3@wFe+L}W;X z{n-OHmGh|SJ(7a;Vh^>A8W^mn66ZtUcB@-*_)m-4-yW54F62X~K_;`?DwR17qJt5E zhjEm7k?!2Cr3pLP$bu(Y=bX9POOz$zb#?I zu{&CXkqcj?T)0!s$^=c2nVm1C)H>|{cN#6do<^MbRyFa;nGmXH9JoR4kASimc@Chl zU`1T$G!2efw&X#g=^O}}GZ+{*EmP`du8A8~S=W<)9@nn+)?DJ@4`Vz&r-28=x4`%m zR`^XUVW|xezX15Zk%wQ=H)f5LR;Fo+whmGQ#hc5C?Y+>F4kn+!ux~}Un%OhRsm!Q3 zQyniL8@beMPZ{8ZRfPDGsUvGycR>Ub{wg>!S~Ig3>}AzbWyKS#pf@d`H%Bpe#IJ8( zuVM1|%$LNAT;`o5mC>{4Du_53W~^J(D|BtfyPiY$ZA1AYakr(Ab$06?2-rO1Ws|2# ztU-;7aAUc5DqYc+_QlqiXbwq`PhbQ#=_B}za{tDG@W`au){@wQ9Fdl4 zK%pUon5pfRso@?fs`g%Vy4*%&QF52LTe{_J5B$U4J_!JWx)$U9 z-#jRz|0F|sA}R>dV_Al@OPC^!60a_p7{AI9XPz7&v!tryi7c3~OK!a*oupy4>Ngf1 z9}8I?zj?16C#x(*4x-O)K66vHBSSq9e3BmvS@VU??e0G6Jv;Ez_MsZ zPA#vP&y*>XM6qhmY^e&=IE~9ow*q9itY95cz}HB^r?wo)4Zl9>gJKIObB)-%Bob8^qJpkpp3}V`fB& z^}p9_H9#viX+Xo1G+-YZwV4U%#6mrRv=?PBT2KneHGo=PGfIPB6PzJX>@Rq$%A8p% zX_nJ`2o6sRDCU^NT6nD$X`!1fXjC$7W(qDnV&73S`iCqt+_a=%?ckQrR#>C~>T`Ym zj|Jt9r9z8pbjCWvPORED*7)JdvN9?VDCR|a?0H-rzK4I5dB2%FqEc~d-cuF$nyRIt z$@(Zse`?;WPq;A_&a2xZ0W^ws)mhFH-e%_Q3bo_!a$4ffr+<~(eyHC45ab)yWq3v` zwNUL+?2K(heY+cRY&v$4`#EL*qkPy0=)(Twne%xNP-2= z3}ZfQQJbasIB()^JA#;JZ|~Em5$YcHd`VS4)F9G1=GFi08-D5-6}JAK37%pDB|1T< zv-Zn%bQ9;~&S^y?wg`ch-}B%uFYSE}DW9)H zU|mpDGC=Mk6&M$8qUnQX_nW0zWF^{A$!oyH<;>RNRoqUqlT@@P@{z$)kV`+#zlxTg ziyQh&@NlFSbt#!Y!f2!8Br%`m{kcJR+%K%6b&-y)@u~>%m_c4*rpQy{l2ant#iT>n z9QwH{hPpj=W#s^RrdjD*w5E7rlp8LUekeZNv-`taN@r-z_79%kh51(%26kf#>1vZp zD-HG+I4stcQ()-Ni1ky;uSQHE1?>t^Oq}dt)*Vp^b*!)%CirIINm@n+e4ChqXQ`-O z4nxTS;>G-mu>o0SG&Lzabg3+`?!q(f^>pd+m-Y+zNzA5JKIu?r)Y2rM@em5c4jF9I z&YJ~UOR6l7kK0#eN;T-QaI~(cL*DhSi5aAoWl=Xzjw2Ynw-|D`6eO!#JLS~4vwSD# zrBaA=9p2j!o1-)wk)>>!RWb!kxkTVZ@Kc_UY}$4&A;eO4@p#601JgjYCuCT|#d5dylxZJ63k0+FeLj6sJK zy8tdh4yMZbH20(}??uQ(1Susqh5zQ6&3lIVTH zu{w3H&y1@JPk2K*E1D$|O zSvGOo#40A`!V16yHcWm%73bdB-v}8~;j3!(bhzW3Blp*Gs> z_M-q;g76hA!Sfd^VM2MjB+?uUEXI z-s9!JSuY>H*e~V{U)_|jax12=4Xe?GO~7jAbGk?$U)A&$o2z2bmE`01CG6QZ=o>i{ z@OLFA?9xC`h%i(}g68sj{P^)!aCpx)#Y8dz;mE9s5Z2+e&|7 zy}ek|kp+ULl`mX}qb+XZF%EF?LLwO^on^%0V*1pq91HV(aBo(Lf8=<5o=SNK+7yj< z@n^$gLID?AMdI;k^MRB6TL~te^DnXJP*;r)!gXKEw0fEb%nAxxJP};tw?TM7Ud1wr zrafCNwQ1ve@*Z;u4hYjbg*uJyj`Eu*p0Jpu>^pYoNWYTm)x@eCR>cNFtp6sx+hHhD zlK1mw)ixZgUbW8B4=BgP*&oD%jcb9@Pe*v+d)sEQ!T2{fJ2IWlw|TO!Cw=^v0d?x~ zJ0Mhy2T{yOFkve(J{~h(1ddt4u-%%{fuSjAhe}Mz+S%#WJjC1IcpM;}j+^fD;d=p#KksUitTBAzO4V0G1t=!&_^5vERdsxGBKL`c4!WSB) zsGQTXk=}`-X3987T$LP?kP>= zJ~IXqw{MlCUv0)wd3w4Yiw;l1idX7{4Il<%*LS_uP&8SdN0t&WE;Dgl{mYvk%`P&Z z5Z*}jSY9#^)wJ*;>qMGKWfC@lHT-KdUIs=b9TqjZ2noRnxOV_@Prf1r_{HPC-Rxtq zD`9BBEU_fnwkD!#1)_a@_y|ipW?1iwBz5!?eMps0W2wyg%{c3}_u@O@j?o5;W!-CW z?51n1U<-}pRG)io3{UJnQo#rnk=HX#{TeCQII6cl#arNPx;n5_wWa|;4D9}_f@Fy7 z??uEC-a)s7P}i(D&%kjFmFdC6zxlP{kXRoQTAV5%Jug}23#QYxBnoVTN6@X0o*2q;) zvJ^y4d4k5<(5VfNVBFA}0$6^6BeL@Zmxm)Vp=L6E5O)}Gjomg63 z8s^MjJFG?XU?{P^( zhXIh7C;-UTgnxEvLcA$}puGq&Xw2yZ-??#QTAg5z%D1HtMQ6lk(y4z{{BQdPf>fe3WU)5Y4{6^?DL`PA-7yWwio9lwdJU+9N~pWCulP1!@fAMN zfNj1?e3Gt2z^4n49BBftH+OYQSoqc-DwWTFL+))fJ@ONx8s)_}Tpg*!iY*T^r6biq zO60Tgx>pR$lqNWQCG;sV+S^G?un9&VPg{}i%2dMeDSRTcs)V+ygu5&Ad!ha1!||ic zvJ%0I&ZCQbK}u7Q%;?sHAMhtMW{Ql{0p{##HyNLd)J~Gl=-734^~XrQ45JUwiGo0W z)M!WY>Sq)G<^i#`_qo!q16RImD6SLnaYNVof>J~pO&TEiP*U8ZmGEW{jbyGN@gC_x zG~Bl zw>7sWB4`w!8bq$Be5RFt4N!yi<1+4Z1Jw#Y@XooYNh?U;7MOQf^TqHl!_&D6Bc?ez zK25DzIy`1cOgzFar>l3qJzM=ynR3uXKc&&l@>uWoGyq-?Ur!&q+xU9~^Y3Nc{R08L zB|IfjdEO<)^dh^`y8J=!7bC&K?Mc;ULcKa!wOq9lz0lRtE3jVkV&~t=Du~QGCob9a zh(~QPS~RiwG!d&<8`Y$Kksf&^w^BSL8TPJ_6zfyCkCvDTpzW{x`-RqF7sOoTeCr859}H!H~tou*)_X;3$1Z(Bj4& z`pw-a#LHhsqu@;@DS{{@dTioXK$it$!Y$vZmAd%Gh63pX$9iqPXIB}3Y1rkI7u(6# z3MXOKlCe*ps|P|zyp1C{Ak0VA#&7MsMXgN+LosKPr+0zltWyJ7Yl~JCO$5m5>rj5? z2~oh{53sJAm&XV()g%hyJzZ6(EWI4&iGtMfV+pqBM^rMM66g;+=b1Kbm^zZb=}hDn z#i}>NCITirnR5K#x5gp8f^V{J-MqhUM~yi~z|`d1`?c>@wHcgB0K=>MfDS$sXgV|4 z6pPgdw+4%J*OFmBz<|IX&b`YBYm?n6m-vG367q&M|Yj zS^_z{C|Z@WMkXrG3LikJNUGSnHBma4Tv(y4mY*ij_BqqPncX&ThVHB4tS)N52Bcf~ zuM}Op8}(})H1Nq!n#Pt7;s}h)yK^rldYXLX)i3e}=r{(_QjYS1W67W^cjY5F+(Jv9 zfR-;kH)Z>jCb&X>=etO5_2!pQ(fz-{GXho@fpU?HQrxwA4pV4cJ-J&v70z;IO@l8e zV*SZ21QSWsRa=;S!KP%sguAPXbJWB&LbhM2jy9^hWP~TOd(>0B0(mEY89Yv8cMA}? zw^$aR2hDeGef64a{XFbq(&i8BQuxj;Wh5XEq&ixpa=D}##7RFxr zXXW>v3nq3BK@R=E-_aKvZ*Pyk4|zyQu`vR)$YzwC@26*nF3k7m0&q@8wqfpm&CWXO zja}i2)0)xUwB7vG|3J)Ic^`L_nhd)C4`kw|nM> znl+7k`(a4zxa{*LsulYwi+4?eBYKE;`z2-}R!ONi;ONVmHte(Q3;&=vMoQT0U)fwl z9p3os-BuYc%(k$SW!)s_a)gu9I4?G5fJ$YoX+43ps{S>ERJl53=OD{_M7-WI=QJBd zKR!w9Hr6L{QBNbLhOz7|{M6dxxx7%7Wb8n~-}5C|ddZ)fbiuKeTcXdBfEhAfE(*ZH z;Rd0=CgubtQTsuRC1}QPMnsKrdM;Tyyz}%B+y-x6z+_~IP;^Q2#qY48vI2-8Y6SEyss>2({D)uj-bE+AL=em%Lj@E$L{glfh&}-1y2v_ z&CvJ!Ydoy`Yt&ODej;OpV;`Nw4>lT6?U>;wt#~~>cy|{?bNGdMb{BSLHpd(B)?A`) z{i3Yd8?b=ZYh0EmOCPVTjuFE#xtg4vtHo1Tg#=P&2(jPYyr?~NI#g9YW2Avbw{f9p z1&{)R6b1Z9;fnpTbr|_cdUl-N?{pW9n{`t=Eqq<}?aTqv zNS|b?RY~f(;THaRYGr^s6Pwx_2^#mz9cl<)0nj@0HvQ2$-^&6*f~{N;MBWni@5m?Y zcnYx7wN0gqd`^?r5xDmbg`wjq1nPdY!@)QK374#&rEa9G+BQ9^ovk@R#KiYlf?JH6 zX9zT#9bt2Tw?%^F5K~8TgubYmFg$Ohq_O6EDA{qN&hx~;%?ot=*9}h3sV>bjI8#2m zK}vfqk@(N8K#n;;HX&n{-1!Fr2JkSnwQtr=o}@nk>dzqXVEURxa75`%yYXx#KsU<( zCUHQHk_wB&0%uCV!QzSdKsjBy>Bpu6+dUN~_2Fz4mhz`0!h<{FS{ejx_cCeaMM;;F zJn*eMtWXOCo;%_afPY?oLSjEf3V5Vp%FF0RdQQAJvrY+M6oi^ik?Uy++&4nH=1$l1 zKaFD6E!4J`o`uv<`>sY~b(+^HV3$tciYieUa3HfCydY_WNM?zd>XZba{~ltku*>4F zgp=lJ;|$xX#NYeeBT8bnGs(eARdg%-YI(uGm{u?hwEFDZ-D&{`o?cB^xvosB25X*@ z)cWE8ewK8*BCz6h(M;g6^k}_A@G;;hkXguAF=E5?d7FM+a>{>cOZMf^UqZfx`vp*X zay?I+45BaRm?yRMv~6=~(5njCTN+-NHPEf$sbbP-Q|9nJ1-cgyc9>J*ljye{5b7R4TBLVhgjcAoCo6e5Mno zELx$MR90)6+wCs#Y7?jVox`nxwZrLpELbDg&-Iavq;d8DzBtSE7LX3o*r+E_?|O;T z%?}_#;>5ZK{7@cK8$B5@MskoIt}CQ|BT!hjGhG1v!KVHxq@Y(z1M%bG8N5=Hk73$?}IEL9-1SRe(_8n=IeB62`*K9t^Q$uVxQ>Ar*E6p2( z9VZc2GHs?Eng<^EP7+0S%!#b!R)bE~)ibcr+YVT@xa-$y%`C!3pJ%(`o7jOlG=z3# zS_iTtu8zuU+{YM;TMhli0-J^E$z}e4Bct<%S$`q#;!>8$h6+o@Zc9P!-#x?@lFiCw zh~{-8MLYh+$T!~K*0uZDH4DVhg^rIBR|3LisOH_DMVlUs) zIACc*QT2%Ex%ax^#KLpkO$9obP&+8uWG5`4_uVG!;;^zW2xU<(TSClD&7AGQ_aSM( z+^Gae!XC3liIk&gQ&{qB$PED^>plZ4@*lc90RU@Nv=Nv-6l$K*h0!ep9cp_!|0ghV zQ@70ca*0Y=tS|fV@Mp^sr3G4OFClJDc1OnBpz%Wk{A5%@%qPp=5w;&cv)p!IY?ERRjIaH*9R3dzlu< z;0BHgwdKDwK=im+Y1}uX(;6A-W8RBRrkAZN=P=T-SH%F13Ue!b=Hq5wVy0+>blya- zM3RbVaQ<>R&gO~PaC|2h`j=rqFJ;)j@a%W{W4?dm&L_G$xFJILD)^@?BA3blUEH3sP4hGOxevfy*MtNoI*X)-ih()(d4fL|*#yGQ8R!&T+k5Va7! zfivDmj|kO(puQynzMEvMkO%@^${93N;5)7$e%QAgOwYagX>a18BccXwkIGjVJhT@a zY3nzDY|Si{Do*4B-mx^=>iZaKmC;+p9;Vi4j<@UITj-@YGkTG^NbK!`H&17>Mno})Q<$AvpEuiw zlxeYTI%1y>ACtR}{a>`_N~+m!?_tB{j8#{<<%}K|f#6TB*)|qIH{-8v=Nk+*jF{@t zY5B*Rd^;h$W?%a13^cI$EA8O*kOB#kjD9`n3N-Dx?jHo1#5uNJ3H&^Dur>+lD9RM? zhiL1}R7k^M^8jX_+`7g@#+QXcQ2JnghwGI?HWSSFl>0fi8KauQ17N4iO#|$7MZMY9 zeH*}K0{`bS6=^7j#1Bis7rT};6#pVZ0A0vHBQpuN3%O?id^QyqR2{wjRGkeV;iT|W zf*+aV4WVRugYtSKxVwaY2aZpz96>L7zMt_l>P8|@4Q*+ybD+%}B~kgu==*LFwwum2 zxaYso_EGRKf74Z4+exTwu5Z4-UbkJEG)+8(ew}OjYd1>H#{W$Z9bmXn9s=A#GxFfo z&Kf`XqfMW&0F=_2O1FcNZkOrbyG7tVc6x@}J9=)%dehl?FPZ^8J z&IKN+OXI21BNOt15uHsfu|c3C0D9LT9IAHM_}Yrh>JI{{CL`}9r=M(*tQUC+oq~PC zx#IUqCXLhje=~puQ)VAIObKf{$?kn!QFoQ}&iVAnD(Te)aj(OMMk6H^`br?ZM}F$@ zG&pG*khwro9kn8!vL)Ut+}Xm8e5=?$xc)xD6&;H;kWPQ>6CMu^e(9E{juP3Gu3ICC z=yYye>8rxds1(|U=K-fo;LY}1jdZQ?N@fThSJB&Z0^yeeCurbkyOY$P>q*(v8eks% zc^jZntD}?O;9FmG;^e8P0smbl*mf^a{zPSTD2#o5;$G1dG3(Thszc^?01FCDpckibKa!%&> zNmp-(0#wWuex}3esxta^CJqpfoHP1#daodZGW-$j!+>zmdmKb4-v&x8@bUNRgepgD zJ251CrC>dMHbVaGFfx&%y22Og#}J@u42kw|`RSd7lGRJ(YLle9Csnp=?MTth^+L_u zZO81{Wu=>?EKA469-=y}-|zafK%HR&onP(sb1U%u5-xw5W-bex*U7ZzJC@L0(3n&$ zm4%$~7;hL+{M3ublQB!bP6@gG=wpYxD`rho;9X^_C?zZ5nHS80fgu$EkX@)ZBrEVE zdUpe`!9(8Wm1Jqt7_`>}LlFo$6Z^;l!LapAH*_iBkN~Kxf5ZRnTMi(#%1cQ$fl6aV zRQL+=fX0Cfm_z_KLbr*2otVjlg^a>-1>#xuzn0X3!@&@2G40IBw8e8P$DCCBB(2-GG|CXd_mAWYq_{lT* zK^8=6K@S6%ffm`-Y{vNe`Kiw>Mw>>)t76XfK!7yjh}0tXXZC2>NY;X2Eb1ek|DQWy zK4#im;uXWEtp?qZ+M{I<9*ls4MuCnNz;U&^i@=s$+_B$NJz%d_e~>-57O;Pu`kqua3 zNk&3YiNv`|=t|TLm1!^Ez6A@LYMk9OGpp*8Iv09X3%`1*wB`N}YO#4M96&f-LqKNf z{m%b_c&~#>6V#(`ezqnZGE=*!r3_A^I28)O4rfox_%egE9aqEFH5%m)G3)k^Lee2h zAQ%H3w~DD|2_(6kV$2rz3-5u9G61{E)JuU8N`$pgN;a#_6f-5ZaT2H1<^x&Q1h6)ZIKYKUJ|^y; z&7}FAMl63s?6QWE_@3istcvV=JyF}nmsiE?I=#dG*l}SQ;Yc~m=oV4=gTN6x%In>! zTdreg`P7cmfGUIe6VL(3r8n%`FG1reku2M{dLFDQC}Q-inU3v#%-sfg5Oj0MS+e(o zvG{<9vjAW;dGOY*_9>NjP<&a)^{nolscXB{q{)l$+mH_KEoYF%^au;HqALz>o@$~) z#&VMbfym?tX}9k0x!d=?6>(>RId%iWX@3yVj?s_#X1pw5V*aH6lroDyCDJ(AE7xZ2E! zyGEiQfyKCWskr=jBo|!WTbl+$MY5aZ=v$w1ijIrqK}_=QcaB+?S}HUt2}|l5~5PbgbZpO4+K3w+>B$#95u&l8cE$;QH1*QhUdgI=pyT z22B6w67drjbpLJ-7XrOSB@`bXBm!SsR8CAeYh?#+(Wz01nx%XmRD{sfN(anQ)taSZ z9yx>%-7-j2v})J^NsO%bSINyKYEkDjy4rosdSHvCxSVq4I zXVRf@pjm#+oC#i-Pn+AtZD3JZlHn%ZS%9uB6@Uarg~>+J8U*8}8+@LR*Q66CoSF$q zS^UN9e$-oY7B1wNQZrFL(oSQQ{?b6Xv}CUQ*Z@m!wZjOXuwrUr+jE?T7n|+587~nl zqCG5o50BNb*i^<{I~DjF&`-k|JH-8)(=kRd3)546F&%b3_GxmHlF(Qc1eAcEgu5&9 ztdHKitdFGo*rv5)o?IVB51AbYHWTm?ik>5oBmlef2=wzvdy{;%KM2)4{NdxTM`UYt zlwCg5Z!8_1Zt;n(c&F+Znp?MQ00{LLJ`aP3OYj$8zMpfOAzU42-msO=nJb*SxX+xV z&BZSZYMP7Vu8$Ny^69YYq1TDncax;nYOka6TD{7_`6eSelr!y&tSrrvgh;;p} z%vOUQ$reoo7ScN)UJhX_{i<3=zOAhu!F(@S7@Ho?f9*~E0@{mI+-rpok^N=5QOEz4 zEx{-;J|ZBWwERpzah_eYFQ)!lV{M@~mlG@N7NP54nDQYMISn<4!{)+06U}0Q_C1LO z8OZ~OTT~?D-p5sUvca**fMFjqlVe5v)NfnXJI6Ntqjjl3 z|J2q+F+t4h4@_;2hd(-KTAY~qS!CMRTHB7xxre@NynKGO+Aep!lAuZ3YIwvSDz0PL z`XY5F)%~RZ4r}@CcQi_vPj@ng7n9uTl?bcLrS(9+pe2Um^yWLCrkTo?Zv!1knHz1} zsYBf)ejg)KOSXg?507^QfvBXF94*iH;j1Yzjk(FD&JZ?H8{M^@0704S~xK|V5Y&_|96&qBo*??S$ko0a2~ zMGx&csi3KxdEaqUHHa^O$w$1)8RSgP@jT`kJH_$zDh2C>?@o8b-2y}=V!>%!8!srL zTZfOG4<_SCy9?a=90qAu_zy`*kcrek2nvDl>caq5A!HQQFOslWvj0V74m^Qobf>vJ zM@VKzR(u#e+mN?nL-&#nzyho(<-cgWHk8<{W=xJcOfpgojXr$Y2+94CMpf&b^){1g z(Rw31{hRmi+X#q_(-TN3AjAe3qK_Q5r#t!c$`BgqWDO;MC_nWWt0CY^nE^V0c}4&3GiuIHNSNjsDd zruI_zpVlczs<_ip7fYSfvT>U=46(U(M$rjrLM-K+MMAox0hAtehql&=-2Iz4XkB=0 zIEU-sk-ff_RoSNpkl15quMgQIJW5A)nP4&r7jjc~Zb<^!D5;SS4B2baXeKGh|3?^C zfCEtmgv28#Oni+}C<-8+nFHemi(*8K)m*H_zga)@!1P-6%W&;Vs%?^PyaC%5h$Zu| za>FsGZ+gdMlGn56fF_vR!Q|QQ$t7J1ngWn^Ibl2KXXec!y^l3S-pkZ=5kZfjK#krr zx25d%EvTlh-I|E!$#A!aseKBtYnu^`)6F|9UY4#5Zm5AVTLGYBKwJc<9iOB#)~amc z>(I&w)-8-G%@hJT^-E3NibOT^4P1IlyUUM!Hr3XeAbKlp+gs;*CMV94bSTzOpK_ja zNK=7ql8xSCqO#abism^621FVdFfVS6*3r0iVT7i`>@-Tq0aZpnwjID+TU291Gnyn$ z`~Vi3wb z+&Jd7%E3i^6cXpktfkk5YsX*Mo_s)pt2?~kXqcfWz`QFMw9f=Sd~PlO@wXT2)#nL! zT($L<$dM#!F8FL7`A&iY{g#>yV0$#a57n7!$bUoXHfIb##5sERADtULrkX`xNGO)Z z7!cvA+SBruNj&p|&*T;5@^mfHGH)y7z0z%}zgM>zB8K?ObpJfpNb2v`jvgD(%M5=7 zd9HhNCAXitL3aqO5s*>bGoH!M{&e$Taw<+aF9SmX1SdTd%vf_7&|-#oywPmo9Y5SO z9_tWglF%BGUnvK0VAoX^?pB21iOYOEIJ}3tOWE0;ohc1{4HtR0pT`$yLY*B>iR=8m z#)WJ#e|w;Ou+aqhlBs(T1yv$r$ZN_EeBwr_CVtxQJZcX!6|IlG)Q#y+Z6c{+#!p`y z2iT$lOHob5D^hW=tO#u`x)BVw2Di}%6eL|L;~tzdSM)k}o{7UFwUUo!c?JML9aAD| z3F|;^%Y$(=@~L1v@2`2V7~a@h--9F+`}z5ii_i}Gnd@^-P0a8qa$i8SJJOj@`7~iX z3Cw~vA+q{SAaB9)RNo>Ehq82vAUTf%>5(bI15m&$?An^=HK#LPoJ!8f7$4%?rbm+d5s-rOQZ)Bq=1jL-%Y z$zjE(3=1#|2J3wZUap^9PGj1^%{#Lv6a|D`hJ^Tpm;5kWu{|B;76J=OiHjg~-z%t) zk#BF)mr6OYNxUoPkdGmjY#&4j5%M*w8wKT=-8Db)Q6v5OC{G<2Pq4DLwa8zVan-u5 zHsGgtbw*+EdGSjwm<<#n^Cp(`9dni=q3nF;ONtSF?pQPMu`PBIj;3Gi_hN)@LqGMe zDzZ+*;-5*gjJH@j>fhC;!UkQ^gR}tS>J^o*Wxt_@=8S8C-&hh0=s)+$gox``%Ty{) z_PS4vM9zvbdh8saCG3`j%~F?gO;N)-bIL?#v7C2zT5DUhLN zYFNsL{PvGD)OIX4>)Gt4_$m6!^>$8T6 zUNcs`V436p4L-~E_15w4oDdmNvVF?{jTU)uTEl$%jX=ModLc`kaf_vf+rJ@2RX$-= z7<;C4Tsmn3%#rdPY%mMm6MOZqz_(!c#$A_;U2KX~5*KOe5xpE!JGMO#8gIs`(FB)Gtwr7Anxl0W0ndEyVkiSUT+rbVv3vDVtxacFGe5nV975 zcVZ0}ZLQeY`8%a738M!2N>%$NtQbS|=^Rmyzn6X4T&4o9)&3C#^yQrWsVlk?Q$W|>eJn>^Lp_xe}JerMJSb_uZhs}hpXA_WH#_n{RhNoIMt9j0D-4Je-2!o);)45G6o*3(f`eEQ68jKBq6 zeee!n^6}MgAb;`u9>&p+_a7PjBkn~n-d+y-mr_dYAB0$m&DG<>#R+|LhGC(4x+yRq zIM{4G8(IdYQey9WQW^2T?Zkc^4(x)+FjgAHJH$J``4#_~>bDW-v_9r%9M^~PcIk^` z1~9rLGQHKaWlc?3QUx;oE=tu0)?RUCRrc*vs-3sPwH5F$d<)UyJ1#q@=_zUq}}?a$ax)wR`u6LLyb`- zefnI_a}EyX8x{_F@b-DJ@KJBva@an{*Tqk9`A}Rvt>^Xr4Z&A<83SV9w=LLTb|!y+ zN4Kah=KtbG?a4e2zPUw)HU>a!#AaRQ@`qgBu+G-8=r|Z$enrlkVf5qzS9X?KsS*f&^ zBIh53Z5LAIpG}{gFZtR5=$E*c9zNDXdTw74oxtl@y-Glm_IosBs@cK9Xkyq8^x3ea zc*tEjIk|POaaiN<2LlM1A-g!?BM;82liA3KCtPOY#@<0xh^b-6>)!*3XizjLj5riQ zL-2wk<}Dx!D4TEpa&aydH|N}j62-G{&GYlp0;eX|3juj=+l6v>-kR~rS8~Sv55ase zfsYMvpr2+D3~b>-V%hnw5;pwv_XMHV337z4@G~!(2jrQfK9~4$6qlD?* z+^`-~;&KO~+9j^nkdfoN`skZ>Cb$0Q)0PgE%u=$Jih@sc4LwZ* z(%vL;ti(P!06W{FOCOCnMJcTIuBec}z6P6LjWK|7CFb7G)+Erj_MBAc;zJo(oVv)#> zaZ!l|CC9%j$3LWvVo8s<6>2u`Ihf6FhA34u@J8No(51<;p8e+IShkazP@|3uXy(z_ z>BVPf7&$sx`r5l_R|m?Z&uiD%U*Bm(@MdFL`nzf!_$ni+JGQ+hBojz;as{YoCfOY; zNe^L%TOqi$qRkwokI%f9PjA;R4*V^;sUe)v;hxk}2g%46IhvumN}4Hk^`(G+B*8Ut z+nz0I2V=D><(w+O0uc!J`)=-{gsJ>6R7w$lh;yz2{tYno!KM6>mi?Rzf}t@z6^`xX z;pzp-s=o|%OvuP3-YR#((LgjQ*l-;gr316RG+o}pi8EFc^Ok*)1L7%Pr7}I+YyAB~ z=QbPJJ0BSi42TRigS`3_0he$v8nDgRl1VI`1e?EoE;s*Uz8c?oycGuE zaqNsZ^7je=RG;DOjoQt1H7N_yCdUdjwfRUTY{KA1$&G8U_LFOg`OH82G&ocs5#lOuf-8+t#UeMs`p+rN7kHs+*%FVZ|OZw7DXD2C8eVQ@cJ&& zhq`~wr4jZLpSzEa&@!1T4iH!79mPWkWH1%l3`+P2zY&NX_2DL|tIx1TY1PP_ejaSE zi2ivyl(EykW#pVrF@BLlPsNd1Sk$sIxUz@|>6W0R_nmE1(o1{8L- z!yzP=HJ80l=3);n88aabiEUssDOqS#uPq%5?+YkAvvl5cVaJqLa$_^eYTC7@`Q;RjY)!F<u!Yc8_Q;(Pk5u>qx`2~{dCDk0rJ%Xu;Cc+(%i@_roB9ShqQw9AF; zxu||m+fftFG25em9@5MlfFuc-F!U_0+)KMpu(pTQeu>lwFQc*hp@JX!Ui+K6dQwH_ zef6$Q0t`QD5x^e~?@0@V_uR9;rG;1W_1>lcQP|}}!Yv}JF6cZhA~PQEE$QG>WlrQ0 zqY9e-c=82PJAkcv&_Vdfg3PjayU;5ETrN6${JBBJJ~qI?S8XHp23z&do7A6`+;pg?f%c4sNGI51F5k&ouU~7`)4M10vc%- zun9F9MW9g#LjW_Dn6)5bTOUPvWeT6)fA+T|X5I>Ta&^xc7m>Sw{Re^j)o|q-Ss+cb zSTSuIjZ``(@CNaC+Nl)JUPFdx~>;+z0$L$Dqy>NEi$vBC{_jiSt zqxW8XCB3Qt)qXBw0I0j(qLAct>Ph~_l&Gbt2FTHtAueFtZ1 zq(vU)lT{JnUvoa`A$S98*giBNyQDg82{WZdUV&$j@KvM))KKc+hotMiZ$z;%75;c8({vks6?^G%P20(+!ie$9ALV@cYuj$Hge^&YeN7YO*tx zpjnUzb$*|u!FWd0h6!yR=*4}L$@ckV;Rd{EN}L}l;N9)}=Ik|8eHm_1qBKZjTsvr4 z2b^exbn@blOAiW!pIPQ7kjcxFRnc%Z6fZxKfBe6-`vhS9Y4=k@eyE9|w2YRUK?2-T z+@QAQDDZPm49z>f)V3>19h{KRBPCz+SDhnXWBZl)TPf3J=u&-(WHQR{dNVFuZW)r! zY77aUUu^E8eu!QMBO`DNk}9mt4S$2ff8&czW(=}8Iv+dOZlc*&U_GSF*1j!F4Ysdf zWzJ=J()+RrRf6C`e!RiJGXx%3T3r2W(!MDrP62H07c*(rtt=lBu5~WLBt%9AWDbXt zggze*(taLuhzjfO#^3D5dzvAkH_BopG_~Lc5lR4(>Pqc-g39ckNdQvTC$QPC%)t)P z&uuKBg==heSz{lb`#Q2E{lwvUZUnZ$Ac2W?xz3B=NA(C0X-*(wrzR+0ePbUGaUWS7Jaj|^_#g{2)R4M#q+1e&6( z1eSENe_O#!-)UzX zvz8);X>P>~N5U0f^OnwZORUIo@D9tr^|Q65YM|{^>!Hd)a9EK|!i;Hc%AVzr&w17Y z5OBWCdQPnlv3?5-x3H+y5j?M-n*X}4R0^vDXw_ie&}wB9h)vo!7fdMH=I!%m18|{k z*-_!>9=UrG)N9%K`c>uWp}Bf1ea`BKy~VgiNiH|zoSirH`esQVu!5*S zo{dfxK^@+DvLWhZo9`OCIAeHRzpm2W{f_raTIX>*qx_M|I)7%;AnQg-u;^h30zp&( zui2 zgw1!MU6zC924P6v%`bElX?IyR$fruMjjMFfeOM7s?|1~;uPByne=DPy|F(1SJtA+V zV8C9Cq$Fb#M{H*Jwch7+r790$kWH#Qi)hF(CP-V3lp?+_Cm$k9Yp`>!3c$>o0^ke} zlcAjP&?WtMO-Uj{PtkD-YGtOlb+*m&I~#Mh25c#cQCP#4k!YnTaQHrEg?!DVA5ObS z#*8dy9jb{E6AfSEE*0z$gPtFmHvE(r#HSvVLcJI)4YVV3OxfF>BsV{-@lr0R8lH3ECq81(A$hGj2#?RlZ(9Y z%g|;}Z3t4rr$-f}w6;`=7Z1nYS+-m3g6`rq%z5#+h)spz6I|rwn=9qYD%XRKFVkV# z>DWVYjjQ@V%uRyNy<$=@GIdgXh1QFu9>>zJ%5sGvIzX}Ou|IdZ|AUYZp-n%C_mXq( z;b*BDJoa0higme|vzRxjZ|IOeh_`@`%&7PO_J)eiWDu`nWxsemQxzY1a&}=vk{@wE zS_M!vmCS%FtcjaRIeb00l>)cqKM3qK{#QE8KgorwcILimJHg3zw@Zy)))5AfZoHhC z6<*++UX#uMe;+*b>zndDp1x1yG^q)|rHbX%0{m3?!pmaa;sF_n5wFQ(E58m?1$d9A zyQs7uUlm?w&@$v-NT6>S2+S>TN6ir<&I>)$%c5}Flr zMrkR-COOJjsTV^I?=k@q`|Ifh?(vkdGmu@1&8tr3A)CBrW43gv9A0hmjQpB7+^sv) zIY!@6sxiuXhQ+r|Az`4TIN{2|^a}j152@w2Z_If0u9_#un*1)5mHS9GZs{N^WdR*H z#p_-1Jzb<05N^0Eak5jgVRMoMk{%PBpVo407#d^Bjz_}$e|hRT9C0K>P>n|luXtfE z0-)SQL$Ilht^ihR4*n$+UuZhPD3<^JEP7p)HrxSm}RUcF}k-WQpn znt4hSKhHCnh`SD09pY)Pk4aVX!7JmsInJvU=Qb(dPObOWkwV4yq})npuB(?Bs+9jr zb>39es?kM?PSRH`u=!FmhxC=B!nWYql*k7>)sHqjZAm0Lbce{!7#WHX2TF>D;<)^z$D$+kMe`eprn(kEakcphg1GWMx~`Z(-N#ZYN=>7{f_f;S5oOc_ zdlLHx7upzma3ipxC=9Q;Hq%*E^(rC2;b-A-K_-FWCyT*MA zwR*`BJ}CYZRy4UK&N6n=9a8y?bRGkl~R#gbg`2N8^2v) zz#oLU@1f@Q{H+pgBXVE-?3NEg!^LI4@eSAw8OF~RCM6{UB{eh{VER*9{&hE3@LLh> zEOW0prMdzN{Dq-ZmNciVcp3xv1UIk8S5db#V~=#ibeOIDZ8kLpwazIZYmKw1nY$YiZB0(JMs9lB2ATb{}%-by1>|ztJ`k9P)NX z*LVIwAbihcQ-y5&XaL0f_4tdn>L%EERX%in0xoJ`wVguAM^>^I@_u!s&VR^9`cEM8#z-_jKn|V0Lh_?Rv z9P`0$<*|!Zpv>hyxr8onS*_7>%klm}_^c>}hZpx$V&KV8FMrjmFHc$S75!?B^@}{1 zj<#uPbfn)^gnZM-`cy}TY{7>=QC35KQAk)xR&B zd{DGn(EV4JiA}l>=Zb^UJy-ud$XyxC_fcVa`{~MA-+oSl<|8XnGthC_`XuuGVAO=Q z?xmgz-fz3}cW0?mw<^i)uTqs>(7Dv9(yx#B1&4IZ3312o$gZmwX&NZ{GL1faO_9xk zn?_P;y^OLLfL8i^k|Y~#%B^%?q(Z}MJ(^e}`R4M08YX1iHRm}(w&KE#jaGGRp1X`ip5 zCUW=0Julo}nlS@z5E(OrB|b9g#1~`R&O;*g(?=bAN_7_Om2=wK_1P9ve?KHUugyIL ze((oNhC}f#KIdu=ZP1V8T~D9U;%qlZAz(YF33t&D8b6!q9+UIMsi_MEFpdC=fen4t zpkq<97Xxf>|vq>bh3}jG} z3RoRahU#Vb2~TEm41gikW+8@6r{9xKtb}cyy7SPZ12@^N8I|mB5LTyu^Ik;Fr-fqo z<`ox9$0M)L6i3=_F4k-`?_gJi5DO7hGR?3Mi=l?xCHT&AqwWVXiLbds<-FMTtfVcm zndC)E<4w|T^r99(v+D1?B@hMA>aVdTyWj;}SOTInR#kcmaCO6vKR)0*F`8vzpf8g6 zg#Cu{ZPhgE)(=c3dhFd^8$v479z}8E+cCDu1R3$bAMAelSDCuaQdKEn_j;=nbekO~ zAwlY++tJ2vew%`6PPiSOn-=jp!b(I2TCdE1Bl1>*W-F#6 zr6Fbg1b9K89?eF*jop4Nsj@zAvnINHrn}r@D2~K_-)mW4n%g#OLhJDWf9GS3WvohE zX;v`|^_5pk5KkF-=>vqiyvb%~+i8t1D?P4f6n3lue1AZ3;0@H3$28(NmP+D=%xvz> z%NQM2FLF9cCayI24v~hPa{QCmSMfHu7GIsNe}zF1Gjc592mk@M3$Q+ee)lJxfD zR>mSzZ}T0R;$e)%KwV~>CCe15%OX&c;0G5Ro?=`+FaAxR9h;qDARrO&2;_%;=bFn(q8+pmzqSdC z(6bG543NYNBDwtIfiuYI3o#cBjUwwc-i%0+()hS;wC_Ml?uu{7#;XQn2?INl=eGOE zI{SgOu>z<(6lEe=qV_KYuLUo$qR*3p7+^>=fMH<(feX=t2=x5ITr_B7-{;6nYp9zq zz&XLle~)BJWkXo*(k9|Pao3N6}rfiZt@b&!Il}c{d4A6lN za4NkV9FYa`0v3u%Y=uo5$fRvZfduZ7bX#f5#wF>nzZ7Q$3!>T3pH}AVe-PHr4)_R{ z&pkJZeg+=DrNaTKNAH9r?lV^Xep`jq1{q-n+rdEg303Kpt(g{JC+#ClS2{jx8oPOe zA;6_Uw{IqePOci~{YD<2al6;Nas(D%P}G%-Cdrj%pufW;dB`W=<9GGwS(Dc-H{Q1J z^buoVw~d;R`|fC7Apn{1S5%hOgkF)U1A3UbyU-oI$cw?d_^s^X@0&x;bcM3XT}1Jf8&^m)SH;_w3XGA1#XD3XSm!SMP# z%Ul~+-Vd9(&C6*?Vza7UCzVuR9 z?o+05hqnEItqt5cNoCQ{dMM(pnzx1;V){PqU{r;GbeA;7hQ58iwYY* zP`cPnjSV71G7}Iz1R;e|#(Grv0}Xk?E)k0t92MF(1-98;p~Up z8$J7)Rp+25&CzL+k(6p7FIqQ?gg226dGWY4==dq(o<8R)Ptqxt@C=ophHki1$ieuc zZ^LEZIfjvBbQ9UAuPRsuIWEe)Q+QF7S>5%KZ;R595p2S{-+O7rNVO0Rl|W! z^1#&1Lm>0wXTYoJ=_pdyNCYfAcj>R8f5-df$Q1_E8y(dy+2fZ(y&it-gP*?LyA7oU~!!fsxFlQiDkr1C? z$=I47uIB=hXRM{T$6vxVv+mr^Nb%vE40gm!3lF3*#co`-{(%lC0tKJw)t$^_<;&=S zp1XjqKbQfoefAtdu9NThEm2j>Zjer!?QayfIqjN61|Xem7Qu)Bj^>G_1bA@Nz`R@Z zvZWx7k}aL}t3FG=FGJt7@bvv~kG}oDALyONXWS!|9C?*}+>vOPK(kypAoRQjFq*;AF2} z_r%R+R{;Mgst=BJ0+y;HfcMTu4_#pqhYoKLw<7k?^*#9N?0r%`<=OK#9BAWUA6MYq zn^)18bhkOGXh~f0n1{f}`Z}!4W_O&poELO+>0D#qdDyJs!$)`@OGl)vT;42&4K@`X z_iNW7%m~*>;=To%c1h_whxM}3NU(u8EdBydeEcQWvIgJ$BKN%u+A}@CXXbRZ6xH?J z(-bQYkiJG0@_C=B9TKLIp;Q@DwtNvIgK)f4u(yC74(kEz5ydb7t`;(1N zf2#8HAyJkZp;JQmK8Hwryw00o04XT59%=S;I7WbLbx#f4iD#i)n~vAowk9l5p~4;Z zWAKbOL|(1Zup2gz&8dkO&PDFVJV8+1N&p4)Lok$#hEBgt(KHRM%$RZ-ok%;PNV`{s z9#}Chm2&z#`;~Q5-`z~H@);C0CJ-vLe4KCH4Q}WPd0s__pQ}AvY_e{;{kg;EY&TW) zc5!W`4t?V#ZRIo7S*>G1n#Iuxxy5Ig_tiXk4MSPnuwC2rb!Mxm}n zHyU}J3EQ8@kx8ieimDKitY{#+W8vtrJK*z-DTslXjCnRrCCcErI zM}&xWIBFV_1ZX;OOi7^&XxBFel2A_CwhYyORYK)q`w9VJ@kW^@`F-Wy6~>P*``tXJ zZt!W)`uALMQbB=sfdUhk8Zc++{oAiTcR{I~|4g>?)OwHNH*~UPNi+I1muk7j_Bdj) zm3>L*=bHrJ=RNhjaT&Q4LdBaXx|60WTjvcp8Ek|A;cHPPR$dv9N(ZLjV7(7Fz~ba+ z_N+K(`El)BIi208{3gXUnocuhs9}Y6IeoR?Wa=bSbjpJW#`md_0555m6?mc&9@5`+ z2f0{xn*dsI{tX$4U|xORwU?Gp3F0&*kpKlyB12eIDpVk4f;XdmWzH?RHsm@}je(U# zT@z65ej_yP_#z0cWiZ7H{pQ`+a!$0BwDd-hP17gW=)VAIfRFKJUnDI7n9tx5>s;Ch zM!;6h4Ar0Lf$t&ZXUoZ)JbaM}Inv;Z*@uhr!hEbxVFMF<*(J#+<`eYAZ`>?^CF#8F zYIvTa1Wt9NaIKeUU#e>(4cSj2em&OH2z3K3qOq2H=O4;`m>=&fk9Al%U&W{+H677- z8*CG@5z9TJrS~9et8zile0@DdaF=|X;^_nxC0sl3AXo~NRH1uem=F~~S3RX}`@=2M zN&J`5D4i54m$w8x`L}@xXXQ}!=le$-!UT14^CuOmbRl`Kt3P4eSoOYT zI;MW~c*5%))-X_a=E?muxssXPY?coq{r@1`v&-CAJjkD`E+G#G!GH4p@Q`~4x8=s_ ziwPl7m6sU6R!mBwuCxGTY6>&JB+->$a8r7ZY|F-ZuJGFK0OG$!#Rs;#!Oogr?r-wG z==~BcE9*jgrxR`dzx#8`z(HVPw7v}0R#p4wSj%NqrGNOFUqKx50MK3&7-_~6L>|r} z((tbO$wEhyU;aTzr0MrX*R=_C&Bn;!NzNDMi46eeD=XA);4-caCF2LBVZaLR{l|sjH%(?wl|Cd z_1aD@*Ei+C>xy=sj1BFB>ffCc4A|ndftPPI{|j$FYUDO`{^(nAA6os-87; z8U|au%|`=Xz_aaVD{eAM`oNOC`ZdY0-QmCtM z7>e-qYClDwpCW}<={&9Riwx*5qGNHE(*e57#=G%P*v@+A6pVHT1eU~+k6 z)&gAigkR~LTOs(W91cy5iN6pUU zY#tz&0uyjcY`#2bDHuuTMO(qGwS!J*=!7R3VRQ5WRX*oN4RFREh4_I_|DkEGQ${>i zw@gFH@6Z@?!Wm*bezvaul%y!&(Z@?|jT%}J#^Z*XM%IN`1~I{FH7gp4ZP@%+yHJvu z7;p|3X@1;h)ewd7hb{gXih15_>;C#G_fo4;E6-&x23j&q{xc=1%oa^bG0F4e)3okJ z-99rGi3cuxHPe!cx>KAP*qyAQ8p~?t@P?Rsk=eUd&cU zbfKbAGgje}EJf7TO_h9(hLi~|fE#5`xFBYY;Sq_ig=KxL`yE~V?PF?yr+bU{l~Uv@ zAXmcm_9I*cba((d9O;VUg5)1F>GRwk%9{4C>Pf3Wfrsd0g_4)^wYy<9W^CRNAJeFS zhG9BK)2N37`Dc3fbr}a?I(ojWP)6;L^*(3metJG`ULk|TVnK%QyTG{)8}8YEwiH<1 z*ZToOUqs^|?w;Y1ULdLPC{EXl7@IwtxM1SKn3}o^o=KsIWSBqB%ZDdv!m{7^w*Q}g zXjaT-RW_>r???fyM_hiIRM3Zo0MP z=`aITmPR~HSXP)&EaNvTquDdv47$dZasW)ujZ1>r2jM2`)w#@=$Ow80%?INZwlMke=jF|Wd~Ijq)!+Ai<$B_YBAu!G zQ05+KI~^ZDwmeVh))h_g0@7S${!2C`n8p$VnH4}+LMgT7|4Fx^1HH66T+Efx zua!Ab1zlSySz?ekWExZ<{R`uY4>=l^^)Yw}>QxG4#p|+s)zE;ScN4o3aQUYhQ%;TM0$Y198>?=6Gk>e_8l+#$GI3KzTktp-8=%P%pWfG2$|?TrV(faE9`y}lp_l%{ z!th;yFFzC^y5%`7#fJDupLZ0j!N*RBPxSGRIn)V5n7hh(>U<=uaipmq-{U=h4Xf}Y zV?|oL&AZHK2u||(mN>Z)eR`0b$v95r0rP(HJ*Ufb4k?zwbF?x(JGFpl7Y_&YwIFg1 zavT|nrl8(0`Ufja*pnN*YCc?m&WCpP-~uw9-|{6COnv za_PN>(%0N}zxW1xM?QhzvR_{EvquhyF=$(hQCsM`{ZZRr`rx(@oxuKF$<{W(8^C6* z{i=F`sf{`Fcb=;6$6ATUV)|B%N{m(1+SX{^YuT_0>-Yo2MaWhL|A0jqrNd-b<)^SOD zX6^hr`&UkfG;b}0Rw#fL@MH*(2>}GU0`qeNK98VlMd4Ogkp9b_=O$j6=hRvg&fUNw z;|U!b9vxXQAkJwrU;4DNoJXfn0(FyHVE<{B+_xNr=+O=|;vJ(k3TMMfww7WA76V6r zmYgj92cpHI)x?Qc+svJ}<;Enug&GJYZcXgieO8ONU)^0>YRY`Rf^GlIvTiyW3-vDV zaS-LyDjqcnD1N>`UtuK98Yh0qjLd6fmU$Urmtnl?d#+pPk@L-z zUD0G8X0RZ|W#da??K!<86a|Fuqwb=ZVCIPD5gvw+blI`fp^ zQCuwRZFqXd+(SufFPfx-gy>ryWx+Fn=e*C(gV^CAqAP+2MJd#)74&%iHElz$OQbzD zd{Hvu?~@w~hEftG&p#+2Kja$-M2*>Ky+j;H4{ll?9Ap^iQJW!xw-U1)kZAov+$FkL zPt|dd0-s`yXv3t9P@j59HR~NOek}+<=OoQAUhQV?iM%~R4|&O-lPhYE^3tY|Y=s+U zLxyn#5wsV>Iwsb5a{?`TCU9IDIVFeQ+yH)7*qzQ^7?!L$oT4^dc_xQBnML$V2PprQ ziVz(>ub%Y?JMncS_B`pY&{O{Cx{8=!k7lE!r76UraH0&zG1h>}0r_1TS)f$*Dddwl zdr(ZX01&F`qp#j#DBI<&{+TS2sxkK6NxMaxa39*gfmwOVz+c*}0@9!G3jEZrVz~4! zuOF3((&>acqj<`dnM_XD`hQ9lGBzJTw{@|0o#l%yEM=3~qCCPNPsBnRnxdB4Hp139 zzbV#HUhrd6H z=W01Snsm9-y?O%8cw$yGY<(?C?i`wSn^w#ElFUMvd9KfTKPJgd(r~nojJO9oj_a`{ zkrr~vA3exBqR5iu;*=MjkQU=qjyo>}8mWl6Fo)VmspP+_h0fCLOXcEBOV7dcDbX%~ zHEiAQ<+<0p&TD~$>4#<*GDtJn9veSEE}4csxt!>NOhJv=Roc}W6;_s+ zq=qAXzlg_LL8;;9Up5H7&jpcpZ)Xck6O`nTp8`$ooH*+Q5=i9W9?LJoi6y%01B;4s zZ(8wdHbd;udTTDv_YSL4QYdcrfC)I%AszBM#P>RVuTf$y5UYUOuly79IHwF^rSFed z*-1R_772Blao%<&iifl`N0tbed{-Ttf4uapfAdC{ru$o%Q?nVr*>pC}m{Tm~RD-Xf zg^$84xjsS8H~ek~LO)&VatgDvR-kF6y&>xN2mnr$a?J9|#-#^I7Yfvk3JT_7ktIiN z{hB3%rQvvUtD7isyZSh|>FT9Vs2;GM9^$$gBA~l{S$ci_{8OSTg=VTm^N*(>bu05X zCBtJRp0Ctgi@agqw>g`l7s51gi%*Uyu=W8;NoYkQJ!|1F%t)K5^R1@5eqhtV1JQaO zbDE;0yY`hv@BlXBA92>(WYRJe6v~-@p!XjCWuk98;sh88?YjTb&yx``Pl3eoiixn> zCr#tIXYqPBTCf@aly21A!F*%C>u9Wh!Q5wy9TY<)k+auu)wrQP#syGz_eIMNo!%_}J1QligTp&#?+FWtSb5Ge4BzP&ZT zmAdC*4Y{v$_W-|vO|Z+#*)C6f_R?iaRUOOM%sINLHu^)STK3Ypl8n3!t?j}BYo!2F zy0N{58G{p$szkF-O9o&g@3`xjJHnzrKXw3#m{v0l^~g(;eT9mvLOBFLo9sjPTwp?d zd&X2AhoLRiVF&&|$SeixM$?GR0b^HewyxTgpDIj*KJhtX+Z+WjP2@kDwY|PJ^Ti@m z_$W*t7QmtKahLnoe7BF2KoH;Fb1XHc7e+TOFh}NSenj4y7q4xvUnhcGOg2Gs3eMtl z@EURz<~ug@5p>}Yj=Rvn@2`ZA*6g8u0R^giijW6(%rJpb(ww&m#kB~U9-6$aL9;K2 zz!JLB<@3hoMr~8zH<42d+n?&pc-s4`0@ACnwVpss%7a&C6w+|*a63JpkVP~NfmxZg z*@^c1>VUnff5;ZKos~9rqr8a3A9^SN7RH&$CMg#NWKuS0g{2`;+@UO%$U=%hI{j2$n>3?-lqXYSvI zjR3$Q^v6S^1bB1?gmZc21V9;AeEO`DNOUT zv|;rJ7k33AaWt;={PxQD#?k`?B@OiuSgS<8s0Yb!YPTZzn3LUjmG{4pTjPq{nl*KsF6;H&5z@SzDkGFsREK`IW1E4>hvYGSbKW-VpztZ0FE1TUVSjzd zTRZ#kLV9X&CdB{DH0x5oDa5y;t_}UG)>uelgndxN(nne^t-K?9gJsM()H}{8xU1eA^|#v#P@e zRb2h?KeDkgfTl`z<@#T-^)HOrP=e_3UbZ zz>xH9Lwv(}&Sx+MbTUQ&91?v@eC!-h)_f#C)u30JheA0>YPeLdH8?Z!+a2cmY~?=) z*wZ2m{RBYsQ7=i>Ll{lKrWc5mpQK3J9V{T_jz7qy+tPn|#*BVOij-GYXbY6;U-Q&H zbaDQpfX<=}ppqqTKY}ly;V+SYOyL)+J0%EG3e*AyCaYU<)HRgdKO}+MAE3o!kMOyd{4ELB>yUE*_0aTWoEQINoTa@o z7SJ59XwL+^{iP-2t=p>byesDNL&y9ClWePAQ;ejX-nSs6C6@|kN_+~9oVd9>S`%r) zm^pfgno}9;dpGC&9T@GXQiHqqvQgI^oEyzR$1QAq{(gLVx&Ag}SUWjSVceVwJvyr+ zVQP3p=G|qZ{iCoS7ybTPc*(I5aIKCq84tK&e*_&dLWAH5sWcDi9m`n#zXeW)OemDH z|78Az{g;-w)O3cBYWw$r-l|>`rIA0)?$+xNe1M4tiw3U%6C>v zxaEa5CK~h)_}`(rCD##)?M`PHxoDXT%rVE~|zeTd7<8r?O~uSsL~htvBiqiT|S| zCiUNz7!uDuUn|6sgl`19E`~Ua9t#~Lyy!x5e5C*v)ZCJQwX`W@S-z+7hSr>u`>Qv$ ztvJTz;-*XL-`C5lp?LFM@zZHZ&uh=?5b(K_E{o^sXsD zXvzKck;2FanxVB*Dmn0HS%cV27WMj$_0Eqi!6TEW(-<7rK#1}})XM|gXP|XO4WK51 zBr+`!G!zfIVwg;rEwf*Be7GQ^%l$3FaFsy!X{qI|);@ZGTjQg$Iy|Juba%b{9qD4} zvC0T-Q!%8tjD!uaYiU0XaXwtG$9QozZh$k(>b7=I4&lzC7nad9rpko-g{rJ|<%h9lr3^)&%= zR9aOq@$;M4%^j|(gsNtor(~o3q(Wl=V>_4Q7jY1+>A%dh2m%OzK%bteK5uI#l@X-6 zej&{*GgXjFd}4Wb>7@KXO0cN(59_nyY?oFFb&Wz01_esuJdi0;`vOowyfsOk<8DG) z{vF#f{asQVQx&lLm`u9}Fy=8C$_6HHwrAY2QT)4P<)A1 zlebII;lpX2MhsPI-%=1rv&LQy1{Idg|KV`^gv96|mtGJMB^xR#7`yZds1)mM7ZC8F zo(O)yin)RxqtqumKKRENQ0CL2=up&u_Cd|CmZh{|*OZ6v`-lfDI7rNLAQqo>Ov~=4 zip=imaMD;gKyw^RWt0pIpkcM+l{)8vhk1=;Y*aI5T6e`4FL=4BOH3cR2X2Y2vV6Wn z#VT89vshw0Mf`xtD@D0%^rH}wha`)%XU~19C9AoH9*;|H+;k{Np~j^(^OKkek$WBX z1?#+*LZuKu2s%<6P)iBO_kib1S~G$dd^N?RSj#Ai7RdA%Ka=bUf?7nj{mU$h%ArAK z3%THlfeHzqHcF$LId-h2qD~k6p2mR*)@VnMS71*sPOP zz58hma4QGA3s?NIostO|VT8TNS@I;K`P7Ut-r8f*^OBQNYjfBYOGxy3@mR)@k^iCX zr%?C#MPj~o;G`ri#4}K{(fM4rL9Pfhk@I{f}6gLZO!WcFZQ+4ImEPQGgyep~qv0t2cvsP)DSH#Zm$A-OD>e>MwP zuKpqnzS!AS`irn9d^`IXWZVODTL>bxdIU-|bQ~9d5yt4=_|k`;gKvBt04{=!2lO;5 zfGTV88+C5QUxeqAFK>6h0;g`dMF$Sc{m5hB^(bidCOmPO?!hS>@h<{(d%=TpIKq0~ zUxe}37rrNd5gtfCn`PG5d!7GG07#T5tm5mf3^wc2?9ZgEdQI9sdxSsiJaC?l*B$>b zn)nG^*RAfOD8Fb}-VN)x8|#AP5j70xW)(lPT3$Py1g8G|AF73V$f@Q1IB;8bWL*9Z zASeL{W7-`9V;1Jl@c@z&9-$Rzyw7-6}6 zgnC7~!~}Bx_w~Q|9YAE@seo8$vvua{21pej1u4y4CRFW_>5u*&xtVnJG14F+!ieAy z`e*2jHhXd{?Bf6VmXwoOAVPiIWbl8(Uz+rP$RH?8SPE(B>Jy$A*Hr$0RI>8Uk|@c7OJiD%+`p?!!|PSAWSldhwszO)7C{~R z4n)S!;Bm2?DhGd5=)_*A?4w=E#c?{smG}jiCpAsB_F*ScA`%7O!-edsW%#O=({0UV z{BTzMJnWmUzH;6BJWF0(Hw?pTDRVD3$ygb*ig-35!{>SwH_a=<&->f;F9Lz%%J*dycK=VGqLbW#p_XAh1fH~Px82nhuYn~ zonfy-P@rM-535GJj8k23ObaTh7j%ZJTW>e+A#Fk~;(``f!c`5INKoRl)MjdDEpLGP zeBoXe=G_WO{@DZF6HI=p=Abco!gXh;Bkbw{1h=wa!qtW+|?`9 z=dR?*&EPyG{RoQ0*Ltgl+jBh|q%B+YeO8=1l`ib|O-aRXD|8f)Fbj=G{$n=%nt zV1V+JGOY+(kC-@3o?*E8j|Um`CS3|lQYhOnaqw!aC_Pao-NmnuXy#1J~e=_I2x5{>Rpr5b5C>eA;yC$FYS!9?*!SC zaHIYLF3Il(!PO5mW`Waee-SQnrGrziurs~ImIo9|M;%Sot9D=>;OGyx6wmFl_fXQ} zrlPB`uvCi(?7^1p39wDdg_hc*o(tigKMM8jm-S-RS@LslgIHp?U@mGpj@EZHua)OL zwP86O@+XIV-t>wUDn__;B-8^S7ax$bFuJ8@P@Jx@HvBza3fxCEhJ`YeY(ku#Uk5x`kPmY(Pbi4+0mSDzBni68o;*fc%;F9fFM@^dF(JbOW+FAJN%Jy zp=2*ksaE_iLY^u*oQTcjpw_v|G6(z+z%`U0=&W;~-CeIrGl&~<!|^bDXCbM=p#ag-Ow^-OH{s-;CZ0()k%tVs*q+f?H+SWK#o8jm4Y2^jyGcce2Jgr;19pn{i)OrFj>j3;CVyA<2ce5~~UC@Z`z^vqB3%Edvk7hXt zA{DtBS@;FP-QxR&*`8deUYIum(pwuZ6^X-Vt(kNS{PSV zoFRzf0EK|?<8hY1ND?3LeM_HczTc}-cyWQm_f;O^d10wS3YC5l#Isz}LA$MDd2SBH zyQznLv3iEZ$HTJQ%FR0t9nq!dta@^&eww9zl%JX8@IWD7YoQ5OniT`CVCNo|Z|4h* zQ^pdBTFHfR)mN13R7#fMJ6zRk^Bf;(Rc6Ce;eGfY@F za>UGMEe16lySiVXgl^qo#u)pk^4qA0ebGuklG~qK9*$S6ebc&$4UR^v8+2BW zV>5aI(ESO#SrMQqgvJh#G^h8i=n1v)DPu(?7wJA2wmANAwXd}2qbvl@A#b9tUe?o7 z@S560-VIAvx9Sb15dN$UX8EU|_OPR_W;?>m_i!ws9Cy|qUn|hfQ1SR5R|7w7r+^$< zSlw_7MJK1o87-fjfN$J!e|WBrHNpKCVdC4s9?W$lc&$Ta%$6RYbl3ZmA~sgP zS1HR7!@4`qcIUp=4>vBEaiAaLO+wb&NaN){)Xxd8b)(dPtKT#kN#udjK(-Fz_5toy zj6%1x-v^FXXPDbUC47y-g5#cYKpYyTAM>ktsCKfi=G)x2)3YJ=esc{q+f#ygj=l@6 zH7)5te}2}igQ?PH_Pjh=}bo^VQ45Z%AJg(yMHHXbPq?0S;jR!Q6kgGnfV^D{5 z2k`K`tI;&U0R*)=!|^4Ax_O>8t1hKp?mzvKw?F-1`*rljC%DT39yu{XzyAEH5`Xp% z&|G4(`D*Zi8!+LKMI2ZpbYD`|eC3t2be$(C+D31^FBd+RJvTC8+V^?>BRlZ3T(Jdg zzk+A0S~vQPo{kTME3&aIdr5^}Mjn2ngA-mneBgI!lkI5I+Z@qg#@*4K95TRQ7;_rgv^8AHy2?Fh|6GHU9F% z!nqcSY*JB^S3)1$-IZpnLX?l8wyq$^$k=2=m8IX7iA&=xwkSTj#J@id?c2VRC^X{g zkTJ}}5Ql09FEm8W_01W%T4OjAM%_MGX(?>0zelwd1eTPk?+WqCI;&My1?M<;yJl&R zd6V*Q=e2i_P4q0Y&opY%{s3q9D!?Tie|^w8S6V?rDQ_X)pjy{w8xZF;Z%BU~Z=6~L z3)CDN(S`yQ$F8@!HTNeC38$18;ib;xLh*M)_bC9o5-2I9xrSB~RFQn?)#@q?^}%Ji z97hrN8Y$r@0AU{D6n#_V7aIElQ>*LM$EBZEN8Sfvs}1V8ZO-jVGjk)_k^7_q!!qV= ze8I9@aAQl$E#F*X3L2IiCMnK``s+f={tg!tfLMoHebi(=37p@i~-f`yt5>lSEv>tNC<0;!=32 z#|th5t3=ghc5M{#tUw@wkGT@4Wgm> zoDVip-H=Y4^RDqEK&-HTzanBGV4yj&#hxKJXrzs|o(EYo+PRWTT|5O2Ud!i|GNr0| zyy0Tsp52HrtA4!kxa)(1O84uJjryQmJ>Qem9&cDS34gH9evw}&tE^HkJzCON%Fc~t zb~U?F8u_5qE3rX)Uk_?IDv&a*n4b@Rsj)a zqeZsVUNZ}GpQOkfMLP=M!rYF1ZedE@Qk$!!-EOMB?qexK4-N&V!Jo^?#np|zJ4KBe@fBQkgAAzfAu{wIQyB8!;Z`A#!5%Kch# zyd!|>EqFXt&DKn+>Q2I z4C*_M2RE_Glj;Tx0yqPGGOL$00f3$;<`*PSPBEyF`N8m%n4X7gq=ynzS-AM?ye9DG&gvrRps zYa9_J@~BLoaZ`V7o`Jh_yNn_KaY^%T{Y@%HP%p6Mkq&%;PgS>S+CieC48O(c5m$IW zkE@{#&6*rM2T-iKYWVxw*jJ?`57`J^IHXIUI^(FB={sC+3Zv{b`n<$9RGT69ms;}1 zGLASw*_CF+$3vsGey?9vaTwY2F7TvG?r1#ZCN=dVAyhR%L{YVYXy9NY+SE7Ui`?;?jmj6sNIGf8%XAzSm}&Q11)BIm?M?{9u9v1u;O_9K^1Km@hRsKxHwz`kE?4V@{@=bFmi5A^9s zO(riuts8#lNa2+xpx#A^h#y@irqU>M4GP;+@QxMHN@T#9mxX8flUnjef?Y5!=2|GZ zwZz18{@m0kC#1!l59!$y!>irTB^KP6vlZztA1`J~qmiDG2b2kId6*_zCN{-y+_~Zt zv)TMK=&uI0sB=eN&!96}wN?ZAs%c+Y$o286${dB>Xdy9?3tSGn@1s>uk*21l^szWB z@*KJZB|fK3XOk~5rf$i2(+uHcB=Sv2_iz17DwSGJhy6=Gsq^VDDRHapcMdsN0JeR3 zmWZQRUv6xV@CS2D>WVMrkqTJNFeUc4*d9>NFks&y^?+tGQM;C8FX0noh%1O_l<)*A zveK>q2JY>Xfs4ctlA!W086|8e(!JQl+gVvihIk%{juEO>Ei}0QMfi*0(7U(M5$l;y z@*JlnzR{Jvsf;Sgy1oO5xn-0Bjq*YwE9-`HSZSo1*+(wjpRZt&Y}u{qYIn5CEX-?}-mTw?C}ml=%!J^q zGoQM`k#*iE;ehox(t`63;YPj5+^n-5*>JetMhZ`%^!wR@jFvbChn4Qe1*5Vades}q zv*%_Evg49LW^ZLKV4kMYP77e#;MAE3jdm(`JHph;bbFyhGuu%?nah@*KYdfB97oZ3 zF{VCyYwiYvnT~NncJWEU3we<2-XJj^x~6gyAux_8Gv8J*zV;~BC$cI0t6SKcz53@) zf?_$m{9nnY+m7c<_}QoD=r=+Q&+&n9%Hl4tKyy)F7pXrLtu35|$^*Cj2o*gbE%~;% zwQmqdY*{&~vUE+rcSA{a zwPEKF!UvL6TJyoCnS<0S{Eu;r_cAOL87>jZsc2nexq_;l-(!PC2h09!(NOtqnh>zs z!$)(!7@AKsU7n25w|=XP`-FH+*|b2HWdIrV<}PTAsp)9*mAl&_BqgK(4gDU<#C22d z>rzkMbPmX*6gAhxi!lkf3TRHX9dGDol6Yjzs3M6wM&R1a6grP}Uv5n#UVhvn6yy}b zEofG~4jRnqb{6-EF;!s0aM!_gffK~N4SKG>h4p>)@n}GBx|^r|gm5NNonc2l=WG;M zqmN3-0X@W&KLu$x4YLf1rHGqCyVC6V7)7xr?1SPiF2BFkZ|#o3eF1f3F^oK@ugA>x zqeAjRMus`OsMOI`&ycVdEoGzFnZsrgJH9S1ur6Up`mhSqq&QkJ7}6S+C}V@EqEbkF zOAn15d|`r4+>7GuatX!L!C)xa$vPFB1VPA1ol(Go$57u2l=m?o^$g_ovlBQb2t9VX z{m#t$TSS%P0_&-Uc;Al^ z6T+_*W;-Q@cy78+dgbzCaybn_^oVj7+2YUQM`d-2Vky}!r=lU0?>xTrB<}pT{TIbL zaqtBwe{!dX#BPv#Q{OMNM6r|;7nkTG7$f3};O7L6?=GY-5h7H@)@F+&@-B`Nc&Wk! z0AI$l{K~P!(sMP#dY#5@3%&G%w`@$XYVTZVv5`-9>4uBpLJri?kZfIMxBm~Le~v&h z`up&@iN~`qF%rsM1)3qnV23J*mGhjN7MM#dtY|2Cg65F1;HL1I*b7yx6S0hi3kbGbG{x1Bh<}sO-Zg# zCpqNF`HDNnUr`)|JwE9~I;==L>1M9k*m&d+kcJ#NQFIILREY}38L7kKvNKuCdBl9? z(xAS&Q`-y{*V0Qq6g28aQ-mG?FOzgys$4mAt0Xd*%Z)-UW_JTT)Kyg5VmQPV>bdvQ z+g-JCMdp2V+TjD%?(<08~v zVBdf$MJvCPf&QNlqmz1Z`17B|-VYn7fD^TBQajwb?%f&gVp5i4w>5{n<5Ep|KY@%lcsba-7iSkdi<XY%?3& zvwifgsdm2BrtS7($xNhpVaujO@%^Pj^%njmk^cQpw&Vyq8@=*=o``1!30GW;q?b;5^2V^rC|Nwik5FoK6`M8K3qJTQ12%Tg-ek zYq-VVxqR7iG1*4EKLYEc**dswC0|m0rp@BCZVp{HQ?nl%s|pdIRnY6p;TlH)&ae=* zoD-_P)el$Ks!fl@cUDyIqI2QFV+2p<8LSSPqk-L3cLYY%ex=oD0`q)PXbWK)8B{#j zLP`w;*LY@_$3gR4r;Xqo`E(88d2 zvcPYmun;$lXSQ=eB}#r})~;PA1GnGhvBpuDK@5>}sZc?uYFDlB`v|aI!yzTv;Y=NI z6jPNP`&b_$Cc;6zCn^QAzPz4+td_UHki|EJYOIM0c{wJ;{2rCw8_4A+fCFS^iP;+G zxYiTNKK*jeo^V@sqQvx@LOi-eo~pI_Fml%XA?tAo+(?l~U|q)h@rK(qTa+CR9t8j- zqCoO{aZy^qtR%dyhg-Fa&MN!yrsn8(NtlAJY^2=$_l5fcZiNhdC1EE19M6LG@Zh>g zGac%r+V>bKFDCCLnh-J!i1P3%lzXpXdzvnV>e!eQvA<`TFtgq9?CuwHvGo7lU>C`h z`?+2$ox{RK*`9`mO8%_YoV_7iZEkdC!=6&9fL(xPS}|E}$o8AA9EK2IpSilVglpY% zAV)XYMum-EN}NN3``iy1f`n23)mt*b1zbClP(pGUyXkY2NiEE3Io3ob)(OQIG7Ipi(_mhs znI?FwLO|xP6{jlDZsuI8q&C(}--&@8uem(K%*YN%;0=0ZwzJ+#zyi`7fYm`>+=ixF?x{JJt+7+&SEvz>|hA$C&QPeuO9jOCk|MY0f z$MG&EEoU3e)!;Q)Z~GybFGf1?-F9t=#@ zN{Z=}d9Qg!&6m4t@IkFpEAsek=&$Jl?+W3HO_p~*GWUQilpc<#qne0o#@9Yi)$HbV z|L_#-?~6bDPC-dYLT`-?gYlyP@EkER*w&&W2JVUVmdFVCgt7&2kNzTP=hi-_?EcEk zg}x^I8mPea<2EdLG|CFA)S+>65_qKUwpR!F;42BKntF{xQHds)9n3P^g*L#ggAm8? zeYaO(HmdB*9K;g#r53psbI%07DAs&r&cS8W-PgHtXxX(5lN%A9HuaXs@W|;Hyp$d5 z!-p_|7~Z&Qk1+Va;wK~GvYi|ulbn(Wp@W8Wrwc{dY-iq^Y1*T!4Hb|4XEcuC6c7%b*aN%&^XTaGU z5L*Wk7J_0nvI8?Ijc3Z7lEU?Omt@k9CZ6qW#5;K=hh$eOI*+KasIJMQ@(L(t$$M|p7}0B>|y)1 zD`+DL4)alzmk=4=H09@{AE-ZMi7lXc`W-M4UDH-jwh_f2A;hP28ZQvK(%6>}WJGZl z&dHOKa!B(O}&HM`S9g1tmvu<5mcivRkJOj0~S+w#96|ZT0w?nK`efXl%DKX@c zh~zFB#h<-@CiwE-LnwHnen|NC64y zFTu_wSBeQaY=*GrEpUXr4Gu0^fWz<#YJK!)R$?ip^5zP$KyLS2fDvX<8;-JipqEdY zZ^3Oi*?!ENiZDzzQKo4N`p(w_;E1Nf7TI~VSFTQYoe zoxGjZ82N3`mz6^Xemf|OL=81aiF1 zfS=1GKC&2qxiJ&}{h)D}|jHEpz!Vr>IE23d`KP!Bfo@eW9Smrjd zI`+|1h?j1FV>4GON^pjC=!l6tt-#Sk*nI~McJ-(-u<{=mQn9kcNhmqB`{Vdp5~yGi zt~2;s-&USakY{%L80O7}Ah z`gdu0t{!Bo_db+AYnx4&Geq07%vVn-tLz`PEoXDA=Q%5PeF&T;ivvFOBMDM2loc}N z?3X~Ku0HVG$5bfrw)dU2I@^vF5Y-wp5|Fx| zLji~;L4NILXX5bN@q*{dmS&uI^i%Irb2MfVrz>~jJWySS6@P5+ukeG}$7+#Bg6 zIfV`|%gL8;t1J7fHW&{@iETr5!Q-lP4JSyypCiW-{Bd3R8Cxx^=*7vV2WbjYEEow!4fsY%o@3@?y zd0?nQ`j9Q9D0D=l`Ey*kuTYkLZw;8Q0#f6_BU7nQB?6?O4};#4Z_1bvs+1#Hxqs&N zM!b4taP&D$Gd8q%pPv7)T#QD&tvv3i5#S?rzX6naXng-u=J`S9K3en_L0)ywl8OpE zE8v1DTm4>j^(+=496yjqJ1)@R@Ee1z%X0dr_W~D8Y2>9|r0d(5zU5r~D~=Z^--JvB zT{E+vT-4u6d^#(Di#lsRM#_>l{4Jn-nce{&ku3>|F zf(dXjTki)6GhYy*)xXGN&t}^fc3kJ_Zpmjlx^`Lr`H)oBeW+L_o-ABrte)z8-mhQk znR;oq%L#MnG|P2Q^1t7Ld32gXjib?OV-9^aUfIB0yDXrlyDmTH8fe)7cUS=&digNA z5OgRXPfQFQ;5#UD;qgN_)*hpXixvZ*y0{`Jy@BS1_niYXtd5yN7d}?Jh{gT6`huX& z8^bzHetsG0-PNeH`ELwhk7b8V_oqbPiaE7Xzz6`<`1#P65lV{01$(h*#uU%y)WF1K zFz~sB>wY6n_VhB;tTABDv9s8TS2 zHZyXCQ?G$GmBo`viH;G+fw}Vhgeu;@*Om0 zh##vyt;N*zJG5oI{Q^J*=r??V^FT_6vOzR%xTpfE7j+dXQ;L1YW3J2NnJlZ?@8(<0 z*z&BBBwCRj2(7P}j#fM}_Sev}WkLeDNJkHlI*@BcrX6ky&n0A8n9aEPVkQxU%a^&j zTPKk#N@^et70-xjl$023qWO+;jqH@(_Xc}N0hS|`7(>d|)zo()W3i9Y#j^&4R5}2Y zj)1fbyH$Zy*`;jmSzOZBF_`=aY=?OaTgU{BdY!RVRfh-4BFRG}jCBN-s@R`Wg#e$e zGlp#8Q>pr^Q+B=SzX+&yQfYR?)hofv%gxGaT60^sQgt!DoL5=FHjDE?g9blJ-81(a zN2Ip3CT(>B(4=mE4gQY;Tw*#dY`a zw7M&{ppPqqa&a)kpW~*-7_MKT-lzH#T&w(qs{19`i!C({(V1B!==>;p6gETY0nKxR z>5iB}h9)(~W+E;*vSzRQFzBbgtEnXta@c-tdJlWK*j;P9tbS4j_)e~dBgX2UE(mFI zq>2#`r~0lMpaMde{(DqF{D_(3-$Hb1SQQVx-`J7#sFjN*jFAY3$D(iLiZay~mg6t< z&Z8ONN!%6Y4k8j7GJXYA!-csp2{{EC_h6nX6jA7AH1?0mrI4Kcb=;DJZ=mwj82}nK z-&!-vSD-O<{A@T9V=9W>6%()>_QS!s79KnKEsYKo1$W>Lx-2tS4`U-XYplT(yBaR( z+cLoO&x6GEzOrt_ZmiI8@oi+amTEFSr_1ud^Z)^YhGpQmqhC1k1iEr88Q*1`sYscw zPtl`R?_pp8aR7b4Kn?$I7vv|*j#E%U&_CmcVPaBwTZr!2end$IST)DZOfR&-ou34P z?&C6Fzn@3CeN0aab}%*(MPnis%}%3Q%isMPM$DA zF&;N+K95^4A#Nz^!_VE?m+6G9{#~uy6|^A%`(+e4N<&KFjnDi&!f$xbFn~-3bO`Fxdod%yyt*JRg2vFMYwh<0`q;Gmbq1Lu8g0%+>2KY+%)J6 z4-6)XjI4J_G0t1n@=)H9XEd_pizSqNWhw=yDJ?uYfu|dDb3~`-4J7R*gkEy)VSKD0 zOLO`iM}@!?Jw|yeOT3WRNS-Y^J8!^Q(qxXoH>A9n3%^%vhUpErPZciaG%=U^fPMDq z{e6vpaWI!M@AarkqEmQ`U%%bw#D#xc*haWScnQ?G6Q2p5J(Y1>LD<+NbVP4X+GrGP zfoiObms(rL0zbdk*r&Ilx_A<8xO+KyxrC?Putb(}rcNnzu>Il}c`9`m;Gy3X&FiiQ zio*JJVd52_i?V%}1+AC`;E+#MbHXnt6%`Ikf0QDgUB^Xzn^Eh*|MN-YRQU|TJ=pHW zHFrXu8E|9aA#TO6h{j za%}syyI#^qS^__^Ne)9rw(#~lunM&0bi9KrXst=(76PYjW+uc*sZ#!;Vj-Imo!CZ*Ue$;FI^4t4l-~b6awR>;4HD%4?c860k@5Y2 zZ2ppfmuaBwkR|UfbanqN_Yj-X0l&Ehs6hAI2ucmK9aYP$=|R&8XU8-i zQ(<*i|3MSHWl8xJ^IN4S6p87Clx0X~2W}a*>S_XEtf{o<5%Z;2pkWA=sYZ%Y(`pe( zI4QUk&JS(HH}{^x$T=j6nvRegJD@ujT;6=ZfE*Hj%p&*0Uw!uvU=SP_nk_Wn|AFmw zsUXK1A_IZf1givjaw|oy=rcp}mIDuEWPAs%^bhAPWpR(auB3i@Z&;ShH{`Dmc-Ave|E zeR#{Eg5R<1?f35_JOxlpr2lYv(#?g>k8|T=m8&O^kZu{;xZaM8$UiQILk5K z|BJ7}sCHZ12Ax!Z1qHstT+k6ABP8>~cDc+NzX(XEpCkb+EYfD~dBlu( zKD!29>hnP)bX9FYOp{MSEuZ_*+CL?qjZfkQ_aH}v*XXM+ZT1}n&DfqVem&w~TLP4j zOY~sh*vDR^FazLy0YC)Ipi;lQQ{EQ%&AVwzD{zARODFC69;e~ zSS_q1xiKUHm%lQ!CzrEQvcj*YH29|np_Ud>#g-!wJEplSv0tY)E7&Cp+*Z=~sFJAn z@?i7n!Kr>CZt2`{juIPjiMe9lj-T6hf8ZYuw+;yPPqY}W!ujiV;{L^WoGh*zQXG|2 zv>Z?h_gG2UjyLN{tot(Z*SoL4<>5G#etfDd<>aAX$wHeHNbPT-t{rSnwXWL1xuP)_ zqogfj#br5ZPtpUCQ_hN}X?;GqL;U$wLJ3+y`d&n*@0**CR!qRS7;zLuLVXtZcSo!G zUrlougTSeNZt4DF?>uYLseq+D&FVMdBT`)COI#P3i}k%0tQspU}LS z8KZqqS9KNX@#cV5I(Xr8sRKS?;uW4)8%dC3IU@a>Qi5yM>~~sWDZI}B=NNwgc}?Gm zcuP*^GdMr|FH2~vZwve&cAPM&NhISll7n+qGjs%kku z1}+540=WpNz4jA!g>_M)5|2T@4%$an%42169rX zN$577?Z#rI`NY$h2PeUb5*UMhlAT#;0`oO% z^4#~8;Q*I?VW&BLjxFk>dgTRmb!|r23^S1cItXS*_z#SsI1!Nnv#x}L&4+^;W4;Zd zm`y!A|9x6?jTYIsw1RXfzos*OSw6`g*D{4IyHFfgE0Jq{;Lgp=jU&%0T4=PUXqU|q zW3k1^SZqt`u)NpQJPSaITK+GtzA_-HZu=XMmO)xtxQGI7$ptPfT$@U~uz5|1 zqC&C;57=iNhug}z1PfJkoLOD&zL!}X9E{XhY&9$yfyR|K5YC#|#>c5?XDUj$pO|Lo zCNq(7@ir(AOJl+?38tF*V>**<$!!BHWE;;)MI4Hs=eyjSdPwWj-Pp69^-ChxrJ`G} zI9u{NigFIjsio<;R-ljU18UE;wN985g~DZN71SP>qWjqBT0Jwbj*Pgh7=~&hTYm|BiUf90b!5k9-*B@S zcsR}%o{%x8G|ufTk!%QkW0w`;F`?L^w?q0=$_N?~aiAm0eH|Cv!xK}qeW(?(qK61b zc`Kn1mpD~Y`uox3G#a4zD_j&q-C%AfHkmFVO|S-9s*5_kq65f!9327}NJxgCF#xs)NsQr^6Y{v?BKF z<;%Pho}p|n?jivkz{^tvGdN6HaJ&HsLRM24Q-_Y8ueA!szYlB|4kQQ=vu|W*yl-PD zT)v<0rT6Qra|1Ld822p^QAZh1QuFa#qf`H_f{PI8Q8Z;iLd#EOR#oCbqL7dR%Zh&0 za<^3?{ad{j2n$h!JjF7|yLmTNPJT2FRF45%X3b{!#xlg??MtFpSlZ04JK>QjIH zRQ2ekPvX}-J0V|#c6xRk5(-Cd9FTv7@rheNAv^wxKnS3kQSpER&WZYTIknS0IG>rG zy%XZ7KR|4L((w8ZO0%EYEM$&I4s2#PX@pp}@qlS(&Sp<1$xJ}7wU;*BzbZZjklTPf(f3p#9xzh1-rk)H zAFYcjm?q)UCC{j)kuD>THnlMFNG!_ZqqpG5^^medL6t6FxAS7YO^SK%>lc>t$}CLE zuM1^=P&j^1aC1!8f=Z*%bZm}Hh#XIMyivu1TzznR)eh?uY2!;X(L2$18Xi}VFAPB} znE;%Q5;&ds#MkSj@7~T`%tx1@-;|r`%p|H`JAMmd+Mwgz8D!nJP)1OvOFco8vHOEE z8#vB2SO*H0LDm}gejr}vYy2J{li0bGVvw4!{b0MH_=D?m|2hot3$lJ?$KCr{w^Db) z_>1htMWEcvcVmHL12Jdtl~4C}h(FXyO>RparwBXE|3NAL7@KzQJiDHPJucnhCprHZ z-gsc&Z4JChi~Pu+PE2K}*s*Dk)wAmvx-<3d^F=0_qJMP4eh7E281XJeFvYlcxPETq zc44|hCwU7Y?y3a}tV1(OXs_S22J32dX(b$lI~mxjR1wX?3Q}#)#xX&Xmqp@6*Z)Hz z@ulWZSgLcJSN$tt{2|^89y)Rt8NE8)Mqv&ay_9kkte4>OS^H_=*UgRB<~qK)GWShc zUnEgy;0eeveEHLSyHD%x{C+ohp{pwKewug#k6|d|v3iR98>k10jGx#gX_%%$|6M5p zG4cDo3K$_QP-3)!cnZd!!Jj7Iu=FpWm)&BzQ~hdzIQGK9jvb2+0~T$6&k|F^bZa57 z3zE(Da!+#slF0IMkHE>E_#jY?3Rm^@OBP5F`#M%${AZHl2UNDN5wubG_veEc?45AdiQ;2s1|{2=T4gWxb) zWoewiB;i|}tCW;_78{Y7P_EGG0$iha@|JD<&WLoWX%P!`PM;v`uU{@d|HPILV$0aI zBr|=-@AT3YW}>k6@M8BN?X-zB0-GO^F)rDKmryfO|0|eEQVT50?0PDGHSjOpCw|4> zHJE+zzp_8Se5dq#Y%u0b^#0-%-|rCSpD$UY#+k0}wZF_!K9TbIgYxk0M&R-9Al89j z>%Y)6<9_!4K+k5pj5))RR6IoMibwwN?{7^oy|mrvtl0?t_44y=4z-uFbVieJe%D+C zF>~=dOIf0seezTke3Issrex22_XL0;C2A26S<&3@PF zHG5sYmOMk8QofF*kkc^VE0LIBwZ*shEuxE$UIXe$);#!(LN@Act#3}dD8HU=2RxKD zqqTTeoZ>K?@QmqB7HYE_bxG7d$X&x`iw($({81Ld3tWhLd$4n{Fz?F)6G0N$PEFC%Z)Uc6A z?*V60eY#D!ImjXJi}m#H@U-C!E5p^u+%_104Tb+sg^Mf0-*?9_R_+a0W4KVF-Z_h$ zjbuE;-eLT5K8}4<3}?TvCDtF6X!u5D-J;`$cJcx3uJdU5q0Rud)k>-~$Y9GE^qorz z59_^>>VZ|eAR4QfOszc+nMlGWyAN?D)zbQODf|e!R&(~pP0{9A}P~Of}nEkZat9r^eRiX~V zLl${D0}ppNpp8}<<5o^D``kABEv~QYJMg)%ZKe}^mSm29Iw=?Vfb(Vdr-Axv5{#zR zC8I4_qswhtFnw5%P;`<&42hcDOZ7T`?4>6zyl4X3#ZXh7C+1n}D2Bhl)T{Via~v!P z>zzhH*JdXPmw(V02fnM~QimP?1lL?gz0Cla zL6#KN*4h14F8~DaYhD)WTe=^F5~jdrsUI4gOV9uRu&KhCgxS3S2s z`^k&rfO#n%m;2VS7@&`_J{Am!==^|)-X`kEV1NBq8qw3Fn4-Xwz7hoCUu4*`M{#CD zo)y|`R&lZM1JwSUo!l}sdjI&fLlJ4>wDVmTonB_ ziUjUE?3|;8TOncaghuO-noX4#FYkF zSy8v#y4QqSWpEN`(H#s?;F_tk^{B)y20)zmk*MMdV&YHCeo7hn+Ej^R+R>yFKD8kv zCU&QSb68KNgi*f-T`6z7%=z`x$~$kuW^8NlB2t;&F-7K4rb6Fr zvX6Rsthxr_)B1JoFxAw3YwNznkv&rLpK%wFt{pu# zwmO!z6ytrM?d7mcqOue*QOE4E(Q8Q>b_oa3jWa{DXlR0piV(+AUtgDBr`bu1lOmf< zSGsX=uBTi^o_iGLM3s|~jh&x-)Rp*Z~g7ezUa{*#aI=}WzCYd*|;?g`$rfZng>O|(+D;#a)hTHW;^a{20Ja}Mn zc=bu?kRtk0&{_rqcc5qE-6jop)#jSuJQ0S}ZVxm!1E?HuDmMrMk_S0orbyO{yU2egC}$BJ2#8ozBQe zQLE9M$xZ)vG9S&3S~5^pt21LA+(_Gv z%^G{b0|)neG%GGg?E>Rd$;k5S0Rc^@h-6PrSttNY{5}QRmWq{Z)+Q(TJ)Ov(Wfl|5 z*n;?@^LIP3?Ahmh|4{%`(LfdcS72};jj~RxjGIxbG#7!4iAj31w@q>$JjDju?gX*Ric)> zSMAXyF&B&3?Q)6XJvAMELvwEVVn{{Uoin#uhshntnd4>41tBL3qLinez4E$F2fKOK zfj)rR;-EMzsfO7|B&^-v8^3z7YY&e8uqNN5<%;(&=R%kS6Xh1qg6|BwoGUDgO_Bhx zZld1J5^z|$l-MwT7OBkY)R0~8{$?gbVVCTlsq+~{9O6P>zigC4_~6+V{8>9VZ>!j* z_pS4@Qw8mX;Nqx-$NtL_%`yZDEP(vne--+SDi2gX4JrfK5Q5sz@ap+@oW9HGl5hyC z8a^xurREe8WBw$*T}>SO{RpsSLvnJaWO>YKAGC|(2hQ2(l(knr5|KDtC`A%9DC`vr z^}Oqd&4ZPX%s! zqyRlF6OZq4Z5xK@ofw{`08k^ZePamjTSe!fd6)J@wvN>t_)jmF89XmVNmi>VPG18m zQaOHu3zTB?FoHAs3d&3o=0$hRbg%5d8MffP}tS3Jm0ZoxEPzj?I zQo8~QnPvES;yfsU`lUQurX+XY$sKNdwJ-Y9tVE-Dk267Cy8* z-i<-14mEJ4N3mpgGCb_*t~A&4yb&v2>(P<>rl&;y=feq+RR`(dL-idzd3*ha_5pwT z0ih|L*ix^Z<#1Q1?E4d_}ck|UWU@G zm#^Ob2ZaSx-v51s;QtN-kbPgcq1xvYDyf94%h3Z`LBp$k_C;w>M7AkP&{(*m!BGZv zrNT@#8ET#{f!{{O-b1YUx&qGcy-vlYW;TKGMQewACiHOpRd)M_rBUd@KQ(@*1)b3C zKW^Nl6nt;amRQfcRqbqeGOuauH29@l6C}^>r5}nyGn5w8MqMl_jraZz3248Pjd?Rf zQylXJ*dMrJ!`WvG7duuEjtlywOue6HhHe6{sR6l)jvo-(y*o89T3O%)CWK{}CU@RZ z)=RYFLsq}(xPxajdw!0&75L*+fO}Zj)OD4Z?0Pu#w`4J_Vz7s1_X@CGS+;csW%;V4 z?1WgttBBkQwv}w)yRR5@^7TY)un@=<%s-dakotBvLvIL6S?trm)0E8)u0`SPh-r z@NU2iv{KAZ_^PAPN4s@)Z?i-OtKGijspR7XY0*f@g(Z6bilaI7DB%~I@B}W8xq9>a zhzi?Gtk|iExuH)wic5b`4vj5WWF|87E1Y%*WixM?H21oR1%p((XR23+4scQY=?5I;6eaGv>U!LRZ;j$G$Pxpu}(ETA6i z)eX+(+V2QB^2p3;Z8FX@!f8q7M~%x>xaf!Gx(KT4Ls%JWDnGxn+;XwvpT61Xg9H8n zUTxt=kMy0p67b{uL ze>_R*-HN~A3CavRD8zjuG;4wiHZM+vVP5?P-MtUnBeYb`O?YJm-eE z?3ssZ<`C=ESqY|Py|}cGwNRnhwbp9&#WHo!%s@~Q%)O6KfrQjC-IzXFnL(&KXT50S z8W>X;r~#!yrjC-*UZb2|G{qSe8=G3FRq5mIgOjPJwU5&uQbPh4dUUmE?bV@$Gf1($ zvX{#dTH5SSX7@ze9W3p>rwuG=TW+&Ex0#9Q{YeA|Y9FV_U=deI4%%4TNt~Uz#V6?> z3jA_Z7urcR@&EW&$`2?vNTY!i6g$c!t$d+ROF5zHxFBziVN03*}OtrbM3u zERt8dQRbcQ>yXBzNrIqvvwB!X~?&f&9+q4ZvNDez_QqPQ8idd;4IDYRO!MJd| zXY}HWK{>G6dpN<%ASuYa9>hb1ARhXr_wR*^(SW`z`k%|uo5TIyy+W!>7>v5r&ix>& z$m!kViiU6i;Zb|J6j#{f@8xnBSLW*iNgzR*s6aLwT6X92rDonSSvyWaf`s7kI}wim z#th_E@2#a#!vFW$5+?+A`$3bNF}eFu?pR&t#fgkGD_i}yuGR)FJJEfnjmPO`v;AYQ z;J1ZR`CuH|*Vx8g#5%W)j7nb7CsnfcuPq=0pMKmC4H$Wqk+Bjct<4rAH(smBO;{A& z4I-hRVI67m?AVW#i;>s8w;k;=(0;#OhrQ;e(i^Pvw1_s}wzQcaPR)z{5;KUTHlqu( zVI9$>$&Ri_QZlC%nO>V1cVVbOSB*->yGi#rb^o3sy>Y*OC! z5CF~N8I)JJ|JNOZT;|m}vAPv0_VbP=>iCv?I$cKw|BOZztX6 z(Z|`tqJCLNHa%ok>h?|5PDnqc*Yrvnm}87R9<5!<5CX&_W22I%fCl~&?S_vD^5#y` zPFZ!>l!g@9vXS;Eazae_|BgtmcED^o;8jMbOUdj65}xOnNYrq-)6TIFPYal=T@_c4 zVp;AeEq-}}l^+gBq<54Gp-j?Eg=6%X3z?GOe@Hjj-uVT?y9Tw%>R(?*5Y)4QTQ~6B z+K-m~XJr|F&lTGPk62kSHSVa2VCVD_k2_)b9K|M8B$zeM-x2TtuL5fSkmF9G;qIb zt>bZB^Cq(nGs~;`l4ZKeu0rg^@aiQR9I)>y?~2M{Rh0!#PtH@mbT5p=q?G7W$yc7T=U5Qw*w5GP-0)P!vc8l9G&` z@TCShXxuVavKnes-95Yi%vIui$&H&1#FTPN?|FCVvq~+~9o*`)ORst&cUdVrVp8TZ zGhNi%_O7tqSJEGq+Mz3%Y!oxt9#+?L3+Kb2#Q>UDbPUH}Q1LD4F@FYoVkz!e!{$P* z2LiP=ApWMz&w6pULR5j&t#=(Fu{hZAsrVa~^`M>(L{)3%g*Ix)Fy#zy_g%=QH<~+5 zc}pYJis3!J+l^1-4rlL9vS6+$hnz(PuA%cRryJ1UZeYEe9{M8$A@+WgcDK`i>_-@+s=Yg z*0Ce)0(#L;t!mE+vK;tXHjjQSQEf z^*rH-S&2QDktV9iPKql(H&5j_g2R3=)nYw$pVdr9teayKcxEny*KM5D@is2 z5f##YGAFF%u5lA^X`svA=5*!+^w4jix}VdA{OgsQ3%3aBPpNKOcD3}*!6>=p6Et%0 zg(xpthnO-LH5HN^)}R(%-_GBPXgsv9p4DT@#@&;62b<1K!NjQq9Hr{|EukMWwagE< zJkOk;O4hqFn&+#sShIh@Oy{#6R2XV;TySCca3S?z{PwQXwa^vcVy}EjnSrcEJLgOQ_xg)~#YVy0m#_YtF|qhuqqZsRFz#jW9o90!ct$SuEo>*2f! zar96%$?VffF44=v*WJxi(S0_SY9**_9PRd@_-m~63%9)>;pIX2#wT_oFP$t$60 z)I=v)N7o*PED}dt{vKaHXz6(8KW2{xNWg6}_V4HLM4qV^iIG3cf3l)D-|fATb}D#E zFg=BTz;!SC!^m ze^C05_$?Q_Fkxvt_pkv{(@1Ms6hfoK8_bN;8uw5bS4k^(p#P_z{x1jnp&QC-CnTik zDZGp9jl5iyqV8RTY4!o9d)D_G3zOqQ_mvwHa+@;XJ@>!VD?3-?jeF4>CkgpcTQ8R>N{rcVA>vfRvt-Sz{Hi~1%ZT|XHBGDt7C zbc?)(tGC7=lZ2JNI=hBeW@w&N8E!&mzv(sQ>A^dtY>!(1RA@H1f*E&U_0E~s9&qq2 zCR`^oOJEApj?(qUuMgGIs?oA+L({w6p)5&7+89dgW%Z82vQfvYe*C$RDE=@Lst*2w zd(<;7|C&%gnar!R2{2-P(Evni9_3lhk+WKm1%$BKv-f7l}MXg z`Q5I-+RLCAaaWz_V7l^g83KYd{IiN1ZLn~+`T^4&`Wo+%M9*bobOEkmw5WW@o2cBL zCBx#NCxiMOF+YRp+0>`QA#YA1rGAuPQq*mxip0Lc?{zPSKI2BoCZNYw!I-`Q<@UYU z*@3lMXoatEof#Nhs{+6MJsKtsdA7)pgYT>Rw`a#u8@^^;=B$V0=CV zf-1`L_<&qC?Iw9kegTfbx(nWP2G5PpEL|BAC|8|d&&EixX{gQbqT@$J^90g)dS!9) ziap>Q(c+>2R5_;PZ`Ubgg30^W0Hsih{}l_&b*`6QUSZDu7P(C+W3w>0<4NNUA||-RamHM0{p|@8*>6N5h8~W zq64j^2VoBiCmRS^(roIwXnmh?Rdj26?YGhBn4gHgmTCrM-&i1^yvEahEf0b%H@yj- zkqMveYXS|~YO*ydQlp&EZ-e@^BJH`qW82FqmDC=H{rrPcTpJLJ=1Ks^Njzu_9FM?v zGb)UYj(&ewj;*LjMYYF5XfcHMkvD=vokEzN2$AQ7;)^&YcO~as| z$@mRVbNEAZ%@JF8cUW_&o%Qg}@jm@G;ezs1Et6-YfKb#>(o4!Uo%w>J_k&^~CN(;$ z#`k0*0bUyu0-JtROlMPcie$QuZRlCq_T9PB`(+uALGabmpKlI58}$g{-G&mY1_}Fw z5i76JsR{dZ8fz$i(K$311T{UIOT*1;LJiqPvw%i*p$E8Eito(Xnk$W09Vp0&d9c-1_;6C3j$cU+e_=c{D9r?s zGT;>>T|U2Qv@gn>hJ%%GLHNd^_*bx$^N4s{s|3BH_K2=SKv2o^OmJq+gbKHJ(z?zm zLYqI-3t1`W3C@jDC0SSWpq_jy`b#yYUnEl>^Ul&bRK#??e~3TtVK;!`D_br$x62g6 zw@-9YKSjZj7uU!9hdcC&9L1IV!kOyIf!&rx)CBW$8ka-s|bjxIJ{BlIDl;Ka#jVskb6NGHir zXei*7_K+n(9nj>M&x;~io}~o0hdd2LkvtbG8K1K51x`6}($_>9vY)1N;`Au7QyMpo zKC&Di!6Uq_M@EZ7ns4aOZT!#P|FC1BsAkdYkg?2);mtfJh8Uexxa2%1+~e0<+PITM zaH(hvt*@ou!*zbYz&S)?*%w8vO#8$sqy+Os9Z%Jy4q~xwDA!QO@!MwS_?6=kL>c%R z0&YDy`Wr);uBk`g)<1o7v^h7lSnb)XpIkDOwaV{JwPsLz46Vxc8@vTIom4pBZAxk% zjl~%v<^qXPqS7eQBp@nS#d?IOHd+k1^A?h25hf)x=WkdF*e(-#YkeXJWVzYG)y~n8cdIcM$DYWu>f6Q#@jJ3(7Dj_9BtuY^ZG> zqUfANbB!W4$=2;w%To+oa=*cZ7lJy&*e~-kjLets)oy(nA*Ch%NU|`jsiqp3)?vzE zlFtT}O!En|u`KG{nt61DYuOsnEsJj^xC({`EKhqYobHwmW0m!s&Lt|L) zZ4vZ%gt#nG#TmUT^pRIr*TEB8u68Di0R9y37}QH?7qszROP*3!ho}@=N3vsxMzOmo z4|K8oL2(66o*OTYPIGJ40dj~WJMfP?`CPJ2i3D!0KGy5E`p1JTvEI5cYIY{N&wbfG zB!TWR0~0q{k+zG4A|&{1muaD+-4`3++=$0ZByjc~^@aed+Zu}|E@UaIsqhzp*0+&h zHGL7$F4|PwTw01;o&3xO{Z9wy8C{OA8w|sZpG|^_jw=-{9Ty6xGzbor>iM|y@%%8i=V4^5;{CzAz*9wk$7IS;Ps=5& zwjxpTgUoMR#_H^Bxwp?p0prIr+UkOx1g@N~E=Z%$HQtaOFJiCf4(IeLNxtQ%KIuM> zSeUHcYi@Xg*SaPP z*WS>-K$?PliSR+5Bx|;xZcd!e?KDva99Cj*7uN=>9P2XUXvo%(@`U)v6zKBzk;G@< zCrH+Jv1ogAp<)rPC{jbhk&G5k-jR<#7@X_ZQa+H zo=8t2E>kd+r&Rdy^m;Pi?Y{1kkZVWF?Q{3d!h4D1hM1{L zVsf!Z^PWf!MBoMOS3I)$D;JJq zBSIivy9beATaymm$GjV%u=6u4urJM)-p5B8osuTMqK3bZv|YkVeMfgAdV>0x-Tp)6#tXpm8OdjzLt9LOL5ost`~(HFkhSo=8H66nXuiT;t?XfJjY?v z?YTrb&z>NK5Olzvh{p(vi{5=tGdiKTh!8tX@{GQxigD#G8Hmvw0kTDIb7*9A>3hX; zPsj_UTb(}tvy+w+wKINBu2l{o{ABK~ZyGw+3nN37>a1F$43SaXZKBy*5T28fZ?EIY z;uEd#q$YYu^$Nz_N13=_`6EA;4ITvVztIV6-Fm`!D^H=h1t7u74Qxw&7sMBgI-ERo zODxQ-VxYMTM+X`anmnfQ1_m0w)}^A6ap^+1l>)*>lf+7s<_)6p1ecl=6C;R?)KoLX z5*u{>1)0yC;rbsgt!ZIa%5Z;UB`PA+v3B+W=fVnKdw))y0lAqb{tN8g7`)#{$}C0p z_pL{y!gZt(t9YJXx9%pIvso#_q|{NK2VCi!0~J$GzhbPLweBfALfFPU0O~;=m0yv^ z$K6~m>IygUP3HA6lL}LbukmHc`%w3{+_jtSMBDcd#fB`ixTROiBB=ZESY1Yj872-z zN^-J`S@ojToA>yV3BKLYCB9!(Nb;m1!>I33P(PJ9b0TCmU)qPzDUa2vg>M!2zV)NA?$h(?8QtRc;z#J-q$AD#lb z-vp?vO&%7$Py1UGd?lY}FZ$OdNEl(dRu+#%Zk@pYYSHS|^Gp>SQr`VRD66V_&ssCm z!>4lay~>_8 z7>12tYa?^Xq-t}IyJGK{%kA}{k0p6A#3$F4Jk1P?;pwP}YlCgX!cK@rP7UflMw_1D za*k7#eC5S;_MlUOsbVjYbRn7_0d0d-G!UM(_r)(r{(3MWg`#V_AS~+SgV`Y0b6)H){J+Xmju7^a| z)gmei-@HH7m#h0e8JYqw!?(nPO z*=Fs`?Ax`OAma8KyAyDWB6Eo!9zLWCk3K2VEKgHXNxY=CSjw@8BQQI# zpl${AWo0DdEG#sZ25EYD|1|^S4&n#(=IX%z6^|*_fgTr^^de}Vcxq&@Dc~jjD9hGo zV5*sRp&ku*YN^LFUqm}maPd!(OPt21YFO5}#O5`XJ=^KG8G26gu1%$-*Vtn+Wcg1m zi64F`Mkjo|wk2A$X#mjYUH71Gc@!S2Avt zWL%_c?yo>_`Wb_c6KYyALLg0noPndn!it@3t5boq1XM5=n-LR17ea?*$oIcmF5Y z@iwzRz|xn5SH>Vu-D9KMh!EfvX|C zn1pr$5U{}8V;41oPC91DQD}T&$1!ZpeMIbiOT%ig^(CPI({)W=$sZIdcIC@W&1+kH zQwEJi%im?0I^PfTiaXNmWQHJeOyIub@Se>qh6^r{mmh_inUrxFm55!a$GFFQ$VOd$ zUie_z4q%1of&+@#ZqvbK$f>w7S4MV0NX5diTuL^Bgc%S0#YfDh&Wb;L-HY~|Z{MXr zIz`3T8)a1GRVY4)%5#Ft|6nRCWU?iM&gCo3OP&}xYjD!vI}kaX{aVCkJ>9-ws-bA< zv=EUk_g&K-31lXWh$JK z;9>qEz1U#SsGsNB^7IWM`M|3wq`;0vx!PXaJ%WFZIGnpgP@G~>4=xnUlb@xv2nTeB zfqm^$2O}riYJ^izm4}V;eV+EwzQ>Ptfb7!nZ8a5gicCRKh}aA5&HN5nT;h^QrX2gC zgNiOsv98?G>#3Alm+T(3K`Ab~-Isks8qBmw)>NCbi}7)r@bp?fY{{cQdzfXarq&{$Y2Eii|-} z$WUB3vcmL*f|eZt3R)4*(! z2%NnZ^hGLKcC<>#W8>A*CBrC>=OqUM3WUoeUp5t1O}@)mg}vb}sNcZsTB!Y;Nc6WR5D zZNWu>U6}WiGS80j3J*9H{beRaYS(6TYO-pLGYpO4=(6es`RL$ERE02i zt?A5)X2yc^a0?Mwdp+6)&VsTE79hK(hXNTfwk+@h(P9%m16wDv1@ML~_Ht=m;Td)n zbyesV0hfA~vft-qD_xRs;p`f!ZDQZYc# zT&H9;%r#>yj2k$ravYSK-mSq2RQ z%R_&`AVZW(fxTaa23Y)W5tSbuq)**-)$l`Mp|D^iwY{cG`DJ~Tsh?(2+8U%oKV>mC)0$tMEhXJir04L4bxuCCWa4ws%F$ML6+M#7b=NfIRk=hBCvZ$Y4PG6Crb`A)mV{y*2K6P+c1?U3_8q_28vcuy3*_GdE)MzF_Rpujsc0!NZIV?~o0qA5$?`wn-29vZ z#sbXb|1nhkXDkI^EU^1)?gwp=1-{+!yP9E>p|fGmXZOcic-jfKk$Cp_FosV?E>I=i z>*8ZOLv&5fuURSdT1VGqS_ca4kQ_|L154Z42-|MiJ4?G|+$7=lzI)AhXH2A&*v{2K z>z{P^)ezxgX+4{;Qz+6Liy@stT>i?eJCrTHVLo;Dpe*jtab%g4;;a30yjy0?^UZ5i z%Ajpag!ZiIr{+jx9;_k?2&Fwr0}U(@#bfa8W$VA;#~s*B{9(3W!e$EXidz$G{4s$Y zaQo;$00d(NAQbyeR3Ds6$E2ejr*T+9F9V~oYXq^^ujSI(>43fWkFsu-8FHbFWYig^ zt&m9cXc*lYe$t-x#G2XZ!~Gd^BR+P?p7AnUTGJQvKcA~Bz@I;uYNEngaSpyqEr`ZV zrH(A94>%4C01Tmc7`{mqAEnadR!rxlbvLWJv4Nit znI{F)tAd6O^t3O#o^F7f`1pTca{T9|U&$Ca9PQ`}L3th=IO(EK`1r#8N{`@eqE|X| zJzz0i`gmZn)NcJA{#&tfDdCd zi6Oi+c?kJ9_FF5P)0~U~`t*QUm`MMJ-gFAdG4NSe-$;u-YhOBklm(k}(|aXNO4~1G z*TfR(_Gmy3G4+-c^w#m(A7=M}om9&SPEtOU!2r?rp?RluZql=~j2sjUET5#IySJ0I z-N<)jOBJ->Ij;Hy*wE+&w~aig+vfe@n-5sxnxU6{Q~=(17x~77ZgTe4IYBk~I<-so z_=Rh|avJlrXHD|}18X2D2OG>bJ5k8#x>+u#_K;U>QbcGM3X0bA#D5cl$;1+9nA{wO zjDF(N7e=b!Fxfz+ZQ7fL8R+z=Xm8$g7Z>Y>J2_JnS*PRL-;J_FFQJQ54{Im{lAzo| z(gI=O{NebMA-DFm?(CElHzm($RO5Z;mMhrS10qsSR5G>hn4yrCtdBD!bj4N=gN^Gf z7cU2oRxjokbu@;DXDV3|BXE5$Gj&`j!wsG|8|!dMQrV4bGu<;e8F2H>jI5~O-?+@x z>dMzi>a*?@oJNi1s?KCPpIdl>>g;o*npr5WesfrolV&VZR-lB!^% z<260Y>Lg;cCjfRhT~uUZ`E?})GCom;S4_zcTxR5h^*F9&pPPI?h9(VooZ5-#7o4sE z0kX#XM62bzsayDHC`G<2e(&YJ+P_;x%CVm3g3eiC$gnX#;fv=jCAlG(PuD$}HlY` z&vMZ&di%z2+GOx?O`%0GK_bcp&mS;I7xAI!Jn^DizD4_k(erug<-xhm%>f}puA=kz zhWR^SdobW(K6tqn5dtuXXIiyPtbs&iUQ*1Ed}q0)0FB z#x4x37jwu;GU8r;q=|k^5=U!>wS`NZ<+DL!rc(CNm0%VMkMIBOsx&5 zNyI69i>zmS3$&RkW;1s`%t(AkX4%JahF)!IJ*v8FE+L%nGHQu!I*pIQC^^#)vB1Yd2gjXmJueP?Gt2l+K{FTl$)E&r_hly$Qy!6(WMF_~!$m!n5 zqJZ4JA*8T%jhoYwsKL42;5)(Iu&=cX<=ZMo+csz`BWh1ie!6zlXJDDM97+u-tVS|- z3A#lvGy*P6unn+vOQ;G-LRk6oiTHyNf^2f#$>;-uf)b-l zHhaeb8Rmz}!TGHBSJOlkeX_ys7Dci>Z@vmJEd8I+kTPV(iP+W%imlW7TY2{dnwMwQ zdTV>PoyT_l3Cq%s%Bge(M|AYzeOUL{= zZaOtOhoub;>jQRaeHlWIy!XNM!K~k%q9&H_F1Nh;znk-Eeh4nP*Sk-EQak5YbpL75 zQ;qq3wKcKQEe4m-K;82`>OK3^|R_Sb?4mY||!EuTL^&`00AYsI5THVOJkhy&!>ZG%833LD zo554>ZN!R_u~QPg&5)rxyK(F@rtzN4j(RV1QtI!(07Q-DRHf?qKyf}a0+vSZebnkP zA?47(#5anpi$$dq z3~phBVqvpsAzolBi$1jM?m~apoT65W>6$c|5qfkCcE&^0q(vwS-uri%(d$ZHB4iv4 z?wupr+Z&dBNt2b}wl(&0<^a7}loz+XE&O}>FI9Eh;Rw&iJhcd0Dn!w%>c?Wm}bv4UWPix?EPEKOV#8A9%x-<+hu}w;P(_ z_pYVCwDN(T+it`boeF1$U+y-VmPZgr7@jcnp)(`>wY0+5?{_u&QxY94MaGp#Jv)|qWh>YV5;*xP zY>jx-)Bp9#{M^bT$R<9+doBhCm}&P-`=O&s*tsKYFrOXgU82s|6aJwk`Dvb=;!l|R z_jt^Ar+BD{I2eoy>gQEvd`nM0PBJ0C6|?;T@pPI%OYhd_eSzvVuGf_y(Kmi zdS;m(nSvNub7)Oo2jNt(m35PaBs7he-}}F3RtP~6rO%)*2jM@Bb}B2CH}k>msHA}t ztaS(>%ZNJONgs=b``X&vMLG?5#ZDKQ8CGR~KQyU?^+$rv62Oo4CWO3R1am^KRP=FQl-IuY&>b(R3pJnrtKspXcEUf#twj4%rWRWoDE{_tn^ph$R+RN`&$|N!n3CghGX1UQXR~IAQ@d_u~K~I zNvY`ZYh@vE98S@lx@i*NS~&__D={<$?g;t&^l2em0oiwcsq(|gDGANwxd$QIp92p* z0S|Tn4^F&Yip=gCx45Xl8Ik%n&~RdU>M0kXmu!u)E_v`rTzr+EGA}#SM~wvOO{#xy5fqD{+t`ZG$ywJ zeq>i2;Hz3?M&}pEfID1$o?A46W#?KB5dr)Iv$G)?6$JuFEQk7?{))Aa1W$_dG!&VV zcl`w@fKlhf-`Y6Ka;n}o(y24;?9*;IYlgB>`4E0iY0I9Pz+sWB1{ng$Om46G@VL~I zf5P>q8_CuWFyzvIzO{%Y|G~|amhZrw&sGuEb@tm7BI$a7WpKcX_12s^Qq@>{iYmN6 z4zRsv6Ob*o)EB=oV%}(5M?dg8?3UHo|E*~=S_GeOxk=lb*D`s*N3Y@5;(f^}G(aYSSH?zyrdr*nnrf7-rTh8iirIVOGn!k>1r$l@vmt_z zi2ct!*15?Mwq2;`y3a!{E0G~9V5@=R2kxD1Trl(nd2t4Zp`_HFa9S&ta#5I@qM?s1 z*!13Z#<31>Wr;2}rVKgDB`hQSj1YHcV4r1QpFk8H)E43=zq9K}1go1I-p7=m0G>!l zGrNS$wCmX~Ia^jLgH{IAGl*T(8ql`kj(`VY66`UM`+>d~ZHMoXwiSObr(0J&VB!Na z-wH7G4CIwmT@sto8uo@5bat0Rhd?q&ljl-V2Le#?CL5EF0hV|sC!^11c&EMr@^#Su zc44Z8-V7=+4ZV}akR!2h2BPmr^@gzfnvfI&mM zmOru(^8B%nu!Ke0+P}nxKPb?NR!M@XT2p)c2vFA&u;6bu60x#Dq$aJXEAoXc6v(rb z08FM%c<%k9b-Xh;g;-3zfc?<>)|%5U)T$@%q22e2tLcBo)@D#D^Zu$6zPMW%gAFK$ zb^mBM|4T!dW2TfdbISp^*wH@Cqot(u`KueGS@aqYx*=QOc5?;eX8b|P2wS>`z4J*& zShv3K|B?5VQBkgK+mzBB(l8(}3?bbhCEX1IGAJ#`kOHF8(jeX4A>AsibR(&Vl$3&m zfV#iyM)!W6{l$;>_qP^HT#K1It~jqVj`KJi@-|p(JAJ6@9uU`t0d+vnE`=sQfcr#K zQ9END*#Pe&+Jlx58Zn}>X(wBQj#g{ zpeg;T{;GwpmEfX^Y2avA*gwhf&u|b-T(-4S(1hv$0wr( zF0sK4yCt*=`P+Sp8YTqdmxb`u+TyhSy^qk5;kAXb7gjA4bjA<68oeqjAFwomi3%n(ZC+ zKjp5cXEju%2ns&87f(&9Np-p=@#f$XQ*j^dzR;;;1njA>Kc>TZri&5@HZ@@?|ohUFZTkEN1P?LH`#cB zstq&slY&yQx^kbM6RAa+J>_5$xx76z+;Be@2N0+Q^|S3>)r~AZT~W|zdfT>OFJk4# zHF>8a+w2kDSO8zyBn!XoV;m8;1@wn`bl4-TO2HZP~Ty-TD+C9ciB zA>VNTUvxJmv6>8k&BhD@Zd3x3Zx8$$82R2P-=^*;KT{yP&ws9p>4;t5)@jKq#>pup zL6cgHzaRPH>W`IDKuv&*d}(9%BNR##MRE4s5UdPKe&&MY>Rj<_0#=|YEBiPLadM7* zOzh#A5b4OmP{SVIdP|{BpYTC$OpmR+&0a6HUBOrd;0O^RC>Px>{Y{1C+K+2~-pwB&5HeHZ;7;;W+)jC$WOv|!K1@9}kV~Wo zw5<*Ylf!*Wlqp{EZ8F!U8Z45K%SV`pVceX;YdD8|o60w>f34Ej*iI!8@Q$WG5E%xN zlEL~5bcy~Wz2t|XyQ+N~={~7W1rew3PC_eb6zvQZ^r8e?o=QI>cDi)EyOdaYaDX+1 zl?48{Nd0yMVsM}j3rm*g7yk$ za-vIYsLs%OI`1R|?8F%;aYp>5dclZ`^!met=z2Pfx)-ryul`4{+e@ zKUSm@xNkcj1QWWsV?5WDm`aoTGs+jRCe{4!zi`D95&#Vm8M*SW`jg*8NBC487di15 zoq%(lqu>R~B-jJR_$}wztpJ2zS+J>q{QyZQ?E@6E5BhGWpL^YsZc$k_{!_Vq^(o5j zg5Q})g}ZOg2n9Al``XAi{p3Cfj<<8G5j1ok+PgE%0iVrIYd?Tu7u!_r$47fO5D@cG zISgG=JKX07LDFRf5a44AG`V{Fh+b1bqxviS0>$#a1Vkx`d zCaT=y>upZd?`6(K8gQx9>AWtwPS}>TzI5#lPN&_ay&HbHYX}8!zZ5kYUxnTx5lN6Q ztqxZRV0Z`K!yQx?p6({WxF8*6EmqQ^*5`cYkc-i*3cM;?r$8Zeb1Y%rtBA2PO2PAV z^0)hHl7pnRqS66wv^{$?y@Zk^3W| zKq4q{uxu#bQLrtgQ%z7hQUmBS@Z{UKB$KqpAWbB-14R-gYz3Dx8U=S;qlb*|uH$&w z1u{SP5aubIH*weNnBCK%Bd9|5H)( zbSzw9>rR-X*tza17{87q7#@H(rmFFa<*d1Hbp+*GcpGolUq>h6Jr941aDe6mdJ__m z;m2X9Zqfs#nr*05Go;9Z#2X_Tzg?!}y4Icaw9~=GB-1b$NXZ19F@L*+vptBQKhfvC z2vV%~6m74Go;aY5*IF#pZ<>Yjv}SIX^(wybTyH>0(hK?<)C5C@69Qc)7ZK(ngStPS zd$xZDSoS<<#)m#Wq(33n@GBh;rcB3ypeM6aJJ#i+;V=0F=Qht^P*0iQ+XnU|oPqHh}k60;L}7NluD=v!d}A zI0kk7CS6!|MZ7#9u`${5Ok$wWV2vR61g(U0nM#B^-_AP5oVjK_rH>qBv(s>J3E5Z&rMXYNa8)2r#Q<@ z*X&v1y*Mc%YXQK48vOjhJ7g`f)RcKJl9XvFQS<}_lPHy6A-z?eejUBGd9s>o!4|!vr#i*%CQmN0>@mzkm{? ztI7SZAXL9fP~Jk#EhZ)>AA0vby11;3T`;a;Dp^o?0PoyKH1w2l8oGk-rLufx%5Z_b z!&oC1X+zTO@J+^Y5agF_GM2`;vgu-2ywah$@A@=2hDo;9CAPv^RC%VBu3&pEdgA!L z($;wstB3z>Fkn@{`7-+d;{#en!!W)y;2qa3s|kYS6MzEI8CJom-&C=XtQsLi3ZEjt zVvuK)KU_rE;2s2Pz$_Vh!BBY&^KQe%J||f^EQnQvv*T8CD7Fn6YhgRC4$fHMn97$k zJF^4Xg!Non1@%`?y%N-O+lx)T6BK${?3bCe(rTYd*eIK16|7ceaTiz6$#Y@pjBk;| z%U+#0P$o)4DfLg@wv>FaK(07{AW~p0a3@m%T<+EQ@Ua1BLh=MQ+?BbG2f7 zaWm1(rrKC&s0Cbx&NM~Sh43=zk2rK{@Lvof7=5bJt3U(_{I0+(X9@Zc3bbFS#!g9? zeV|iF&KFgh_%bbF^IF?Mw1X&3OS%UddeF?12c`aDJY}XhHZPQLFax5N&GebNgO zOjz>~d>u{yzM0&xtcn)q{o={WUI;wh^8YXf`>H5RLB_0Cu1pUyuN1C5F2q@8=!ZN_ zUZ+5$7N=>JK}W+u=!TxF5tHtkOU!E9*9W6ijoi~)xEye@At>!gqcBRzyYjK9Brz5) z-`%G?jiM`PiD{!_1hmN|3VKV%xGGv^0B$pdB~OWQ-a-hSJPHIxP#zLFUNS@Mxx|*nFn8Aww*nSZCw+xBo)Z*h(DUyYo}w zC^hZYnt|&SB5K+zhW%V6kTYO{H*)9&PsKC1p%9dPM9W>!$d7nArmoWRR3t&=y5$si zWZCrtXnnY5{}jyEe;8fSUro)V8Zwk;(rptbYJ4GMxpHk6wCX4GCE^WN?zLQq=nDnkj{TfI};LSR^w(_3B;65P}( zZ^8q*ZxG65f_uhy^KvF{fk)|H{No7+%Y;011VEUO;X<1zo<6WzY@T;$>7Zc*U4GV( znOmnPijz7@DXxfvl`(77)zUo^9Gqs!9F(1C{>tE~V*oN1vU*+4clmQMtOV-2NfG{^ za2()6+fx6RV@|7Ri>Pg_G{2FA6j>KIekxN!?K~z~EOX~6PbLA! zz#+*}w{fVlqY6n`t^i4RVdmFM!&hwMp(zed0yaryLr<*FNEgNzC>?XUXU+kyjs$R z2R__++2^&81Q5rdEYl5^zeqo_wx49xIDV0HjRONo3^Qe11@45z9k*52F^&4*W336t zw&zegr3Bj&%=jTgMKxsw&;X}Ew40{jiV9(X5a69Z^B%i7Ck4I7P^-V#<(>fckQ%et z!1E+FqRFEHQQIIEtr&sc@JJVI9^IFPb32&DI<~(JClqdicy@?d9bXCtx^RnU2CND7 z6R#RQRN!9f-E8!=Jm^S0;#wyd8h>vzv!M`JAjVzk8oHi{GQvR1&0P?i1B!Tj4PS%R zt1L-^vDkyaQO)oHfjdem06CpSpi_uPZMa7Z@CZR+&NfN(#B!fR@CH)9S@h7T^qbqd8EGG(-4V9TMsl)G4;&B(I|hIs&22PpdKCa z3=p0ZhC58h0wiT2fXoq;bQ>#RxQQ|c!9#g`SES>AN4%hu3=nsOW)l%Jm6C}nyHT8z z_fv{qC~~e>2G1E)EQj?=u0XQ#7kEhqBa;DHIdU5-%@vk>W>AP?53FgfZT1! zKl0^0@P(Zj6gwOW#24k~k6Asu(sV$% zSqC)F2o)q>mYdPpOfM5P1y-DB+CSDug8Ffmp})*To1~l;;1MzyUxDf48<1%Q zH#FXZ3511%@t0yolSH0y0kssS_8Fr)+J!DL!-JPY5A`*ALT?C4r8Brm^crl19I(X~ zwSJYEM*=^GfdiK45;LIJ?ao(LNKhN1QMn#WNofZ)QGqe1|7XmXuB8HLRT_mGOP%Xb zV|Dh{GDB2J99XUQ{qiZ!XWpopnt^XXs}3e58TAeJ5Q-|1DG^e+AoDymPghU_JV}FY z>?nkTG7Jv|ru9E#eh{3;`PQ3rLm}H0P-Xv}8)ni53D*bu;m~r3Pej<*b%TmFuCv-( zc^d|K!)|3BsdN26}^p}dWbU_V)632fP$j)(vW@-}>zNmn2h zbne6I;fKhQ2LqS4|4e_!z%Gx62Q0e0(4T*N z&MGhh+{~pF(zx9US?7Ax;`C!QQDd>Tl+HtJH`y0NXL)3 zi9h?v2FZI~BL3iCa3G#Jfv>I)e}aZw;Q>r?yfoQ^5KZ{{<>UZg?f3iZf%gwCfxVx( z4%g|a1SSx&*OvGcpN{sFwx<8gPF#ov_jkGLn|VCYwgV%;Zh`xh^8*>siTuV!9hFOK z4NK|%D*jWFv<;@6Cxz61(jcF0Rxg3Y7E%$+uH)Aab)J5yMe7+h2mW5zmzBz2SvHCr z9&Bvja^=u8#0mCe$h&=69Jbiu;32r_R}Ma*l3abg+eH51Beeh8eMNKyE9ATSm01Kg z_bWb+gA^;_hVYZ20{7AAF7dHcDywy9R)@Ao*NWC08A5G0!&+HSQ?QJ=#!y#Sp7{*=r5+* zCWH0Q0xMCs>xMW7j#j{JDR$(#KH;g#xCAW}*P-fy6reCFG>eG1coke?9rBE-K#dPD9MF1* zNj=U0aVF;UA6N`sru^T!9&qN;l;>`^Vr;fvnC-I8^v}9;Kv1_K#YS+ zLLk)#_#LSqpWuyst_Gv1d%}C1kQ~bNa>nS1<~^6#z!$Yzpt#p_yj}6R9Q@t%gcGtp zr-nz<;7+_3jE5e4KPAe~9Y6}7+CSnrAunwI*f3>E72I)X*m8$Mnm|Suj4<}+T<~p& zjT@_iQF$p5eB#jX7W;x4U2_^F=1gLbOo@C9Y0H1k1Rq3g$p2UY-8(`DzZouN(n^<^ zur2Jxq<}E25Z}}vil=j1R*y%Fp1HM`L%zh5{tSvUrg*^3FQP-D{xi`91LDFf)ukNL(ims^2PrlW+V4u!L+LGlb=n_iMGv3tj0Hq{k!dwxHdwp3_*%^uN&FzG(gXcYys!>~G2>0oQKlfr&4_ zus90!75E5P3rjvc_(pgXVe$n7)^4T=SmC8$_-cK6PV+On4d5~Vb9jc{!SCEWGV*l@ zy{T)ZunbF9T0w-hDV{fz{jNcM{FVD$Q@f_fQLbE*K-g(i7%FNBPTpGEmKpDBWdHKg zdz7pYQdnAaqKxRXuDx@w(unKwf4X}(%S^b>uKqrCFL!H%_5#`D#SY0|XsTB=SicZ2 z)IYFoBPL)@zfjk18>nz(q5e$J&F682xHjC$(QtQU>JvC-q+@DLDvj%YU(})vlxM>1#P9-T9X%!v*2>OV5d^N>XR6_T)Ik^S1&qD#;*w!%m+Yuf0 z`g74zO-VignClN?#SOSaN}$nj{y?Za+PBa8WheBykcBBbfh^2lXr6Zz!-vewj4>R2 za59>T?{v}?^tdcljJh!AB(n5p-Dy2#A)S~nNW&nXC_=d(U>0Z|mRk`JeUy#Qe_{l=JM4vTdj$wMDE%)Wk^`HR|P2{Dw%C)F;HN`Mhx6xafhL zmSC~V_Q+e-F9*QhGx}}erpjOBbFWw2;0h2nhLI-^509cPYr`6#3f4S%%vyvGAclAL zX#<1{Rs#imh8xH-CE6ufCZ6`DM-}Z`fPSDTr9}<7AFEM7_0~Wd@r|kUxrkfBi^1|L zrWBm`Cfc;^7vUx**H1W=f&X zYG!&;{=raE2&OIyY88=J9hMAdphDVu{42G*G%rZv#g89t1$n`!`(sMsW3a}N=bH84 zi^l{~JyGR5;mo^*JSEiIlC#=t3dBw4H<}zJpM%kF+_>Qh?tcfe*VwOvr>Fn+jg=-Y z!K&eU4@iI1c>>n;eOe&kJFu;e{DfzgTrnst$?1e}yh~9Wlosw1D-dNV8at<;Ap(kr zvW#<|>`|gd2o}dqn_*K??Ip#TEPk%@@SYsPsD`P!p;r@t3am==*v*)C4Qz5=pQjy4 zs6>G?C2)$+D?k2l_r2Do#c;V25uNZa{ONks&xYY<-B)$_w$31S^mu0t;GIDHv*_tX zOZyB{YEoTMQLUPzPj+V|y|qgZa`*OjPOqlQO|J7GqDLYC_{cKaEZ}JO~n=l%sD{biz|0RTSx={Pw}S*hi8KnvXqE}vXc zM#;}%CDCz5RGF8b=X!5Vfoh4Bu>r_F0{jjh{Z8$SRExr}Sogjd+>6Sy67cUo%%|}o zX6C8a@rwX6&^0UH_ps~AW%P4N2h4B*xvhZw_wrB^{ugHQ2{#YEL#tz6b=_+Wrc^Ja z_mZ$A8mrz#K51UQ=t*zdO2VDeeRk>&=S)!b@+_kbx?(YEG%+8+ViQEw z)Lv>%gf9K@EMGsU{Ug0Nkp05=AE-0ax_^;#QF=o^VzX0zNk0N%S|*8$kLz;$0dP)A-?TQo>|98N4&{W{Ocy`b;Tm0 zs08?S)E#W_DOk<)oCl0CpM{$yZ`>vlT?B3t5e@(ZRVM$(74iSq)_Axr119v+xx5@^ zKfQNkGY*x;KjmkOO3RcAcjl8NHcFfMlurrjLUl;yav5Gbn3iSSQo^TEh%Re{DAJr{ zeB4~#1q>@_wp1-Tx)yPU?RQS1M2KutusQ;Vru=Dq%&A7pLTzT9+u_xU)=vaVF~|whrGtUs5z^%EH7%*CCME3 z4o|DlJK=2UKyB+q5nFdcV*VF*7c8?F!+YK_#V@LWs`wr2ta~6t0sS;n|MV#ofQwFW z-F|Z>cmFm`P1iSx!@8IeaX=d?0OlO9u=!zSziHwgll2$8U2;&l7~u>p@9P{1A~XA} zGV@^IA6@$3f1$NipYU4X3x_VK`#2|YhtPJ@0c^m)h4s6UP~x-JuKVYSWNDJHP4B zkM2L4Kt)AdY<+sY7h;P84@XV31+JK946dlXvZFduZ8*M)Oo{u3?7in_2;Pxy?+X3` zo0Iz%>rJU}kr$bx@(__)OTC_FVc}AS*Q$(NqS|0HV$S(hmvsIo2Nb0F#j%zI|138Y z+8Ax`+xC-e%-|QXBUs-GsfKhCG@8@Ixxv#zZX?&s-zu&xCTOKxtKvee4Fxo!evAG+&BGWdJPQ-448Cru!z73OhnU5| z3@_8`)z(`lfx!=#t({|WiW%NY*Ehf_0|L!oG-5TPKc3N!h!rPO1Z2T^3}6) z{uBJze=3tr&H+zLxdC`EFsRN@3liPu*o(^%97QrJ16hhjyS~u7*lzFgZo=ZA=z_mv)N~fF5w@DaANqFV-JQ^KEnu2{+1>)ok+gnEHw29;=$T8~C0b=w4H>kEy=_PXMRAzB(NW*wsaI0_u`TP4gk3_Tv} zRn`lP0guD&%Aa62kb+TwzrWs_?|xHu(QBf^-?SstcbKnvi7?mNT1}G-$c=oH8uQ*{ zBNdu(zQg*qXM`sy`CaO4tuwJ!tm4bHU&?miRpfjOm5T%#{99-W3R)c+Ka77z_va}qe5hZy8lM_3$kSN+7nQYBcZ!9c4-m($KQA0A{& z=e+?V7sOBVXzLhl46*$S?SeP<#<#iar+D*m$KKKiY{NT2RW@U3%BW@WPS9R70+v;f zKzVg$UhquU5kcb~v6Qvct3gUE$F;f`+ZdRHuxj_F~dkx zY`~J1MHwf9VW`v|XP?bERw~WUN!md{TNCVv7Eb4z*ljTE8Jp1!k$SsuPaX_@V4 z*&D!m<=!cN;PH#7A#ni=2*>6sEG+H<*-KA+4?N7xbVE`tUy_V6%q>#q1(}-7d^r#_ zcvhxiikwImh+(7>Kj3H`{Y_MA?W^e)lRR@M)!&$4pJvQ^!?ja*7g*@9Z)!W}g!n_h zFA?xsF?#*+)p~-eQ%w8e-pq0~GeXvvC&9qNx48fIB;df4Ae$UCg^peZaP(dbcGOuL z3hUmK^=U0stFthdIsD+-0@h`?-TBp@0;fse84e&Lm80?g>sYT7rb-H(=}C%Hw;Fqg>((=QUVz>i?P|@zjfB+DEQL~hxl(CR zZ~l7r$uKoZ)A&v<0&=@e(5Vs+GJQ|clN&?qJ{VWtfTj5Fabk^%YCp8WheQZMaAxcF zSmEvEOMFRe4jq|tyVt?IlnYT#AkwerwUqW3oZw)3+D*7D7$VIYfz9L6qqQQ1m_XA-eT>h0C%`vg$^U)C7UHF=#{DE@HdK zCZ1Y!hixyNu8#K1nloCy*YEV;*ekNhtqsh{yO1Qgt)>D*xHpQN8+Xe4{yBGch*1)tT;#oM@zwa2iK$U zxo>g7z3DnSlndU>ZOU98HjXHPafg}(H@a&yYST%Kbj)$MQWsCpOXtVCU2^@=N^B?K z1DuBl=*ZOZT(etFu+V+B%A$uVE4*_b zNNVjp1G}DmCN4N4-5)J6H_o6k*eqcKwH-Z?+!$%+JCq%Nw>)Ry3A)CcRUhBMMGz(Eu10OtN-fgZ4sfH_pD@AK4CbxvY$O8hx5_Py*+t(dDjIfQ>p9$aejev z-g1yYJ-`y6J}+%z*jSSbCAF3XVML)Xl~w)F}EUGLeGG z(6o|7HEltm^rpw=$_>D-Na+R&q&{K-=%Fx$JOP+I>0DO$rUJt$E<#81<`yv_%X>Y$~x%|3@nt z)mUS}xQU(q*ilz74 z8D)jQ%~-)mP6Rb{RT}wXsz=Pv-KPmEzXl+x*|EwWcG}c-qha2#9mQ9XVjg1dN?fxV z5@XI&9foLEPqC>rKJ1eKM1piQSV;91l>6#qNh_HRP~$f#SD#LDTxMvJP>3zetwSGA zRTXG+p1K-Y!~mig9w)_-cEx>y#>!Squ|1-#QNY&faZh9&l$;3$v1sZ$aZZcMUf_}=y-;~FowqNl>KW{R9>k4MxF$O%!ZL00YVKw1V zU`0QEMy~uUfG-H$L7Z`WK}6r(`fJytk7wT07H_T)bsPDd=^Kp=1*0)v%?+BlleI8U zyYX|n@SWgqr-IyQEwuPeJMyh{#dBgK{c#~Yaxg&h=ylI@lf$Jy;X32K^-=}mydi42 z>%j=ayWB_>J$G6;R=CFCn<#b%Y$;|Ex08rIKd)NL6^Zun>d%AZifR2pn5|^MqjAF{uki*9 z2dc&{=*I0`;R|sMQDgD|%7T|KsW{mGu$!Ia1@T=lkDd`HyOY}$9S!RF+fHM40?TXD zt`mqh#21;K%nZeXTYbGfJO16D(!en>^2#4M9D19wBlsX>guETkEGca=5l|Uxl*jy2 zJzYrHvuVierMdSNdb#U%h4836K|GpIxT$huI9QCETJx17F->@z7Fu-upiY z7Q2F5+&|kukYEMQ-8vq&(U2<Q%qyfSMCa;JcB zOvu7gp3RnAVBC|2AtF=FfXrPwMX3BbAua{Q_k9&D_G>}{8k~-nzPh}PcEKzbxCeVS z0>CWjl`QiC7-)ZD6-4{{8nFH*t$EGtYg)f-sP|FqCijtbHp(bxA*m?G{zvAmK&I@? z1HS@Tm8}W_wcuAECQlX|T&P264G{0{&~|-q_Dw=Bi3<(}{DdT#B*%)QhGLKaVe*x) zkW)OGIX;mcsUU^Ck!LZ&iAN!>xEC05y#Dnvtv*-{(&|xT!}TrogdTxN$rT{LppkV% zO1Mbobo%RSc&Pc3$xZ$m09pwV37Py_C8CmuY{oBB!ISd3G1PRz1 zG%{$I{8D+BFz=E-@;*geVPXXRv*>O~3EHBF*RQeKCX03~%0tt}*|m46-t;Y`56T%2IYh^r!}qmeHf2VAjCay)c0 zD$Kbo7;z1em&_+e^I2g>JBq~y53D4H5bKvCmBx*;_6hkWh9i}o1?gmt@pB?0B|CUW zJT9@L^#nYZzCSQMW`qTXE^IWZ<`V;a28Q92;hq)Uq};)qQRv!8j#`RA%5F;Thtzr$ ze`d?}i3gj5k;SmDMadKphf-XBS_p_Q9>JWe8ZAun7V|bqTk@r%SSB;Hw5X}3w@!h$ z&Xw1qA2AE{rSwu6So|Wep0q6g3siP6sGNR8%5m;b5zSEt~9nW zQl3va(5Y@^veCVI`K`1$F6yH@!pOt{0JyMNj8CZ*9F!F126jXELgb641^RJV)tGd~ zs1>%1-Io+0aK!BjnfKpmfptLT$8vC*hz7ev5r>wy$L4zC4YFQHIR$+0jL=) zQRo?iBZyXc5^wP1C+RGMt6}B>CJRmYgS)ssh@p10lXyxjd#j1AMgTU=#Up;uSOtSG z_dd8xjUeaKKx*XmXi`U_{02p3&17gIAlx0Gn**zW_#Q{ypnQFZIy!cnxe*!7Lu-9dq=P92zc1oJ0<^)uT<4RSZ;*sI{eU*@z}%H;;|6 zXjW{>VEmmUtBe#H5%>2C`i7=Qb*P)ki&PsTgxfd;tLKS-+U-5@O;ziF-RG2%&}#&1 za_kBS4PrKK!Y-Qy6@D_%)V=PIzNcBA&b1x|`eqiP5lt61geAT=VWLN1i3@fCsk$t} zx}r0M`$aU~h&E&1gk+K?gDkkGYOoC8hV|m2-2GgL^i!79x5gfba%YS?}8TWffa^4`aA{c8OAafl2>!~RNVtzz#>Zfx=Z@Rf$j|HQp?OFr;X zdQbJ=)E%u>{6^A49H#e+bebq~7~p_8l9VqYn_(Wio&qD_Dpg>JPG>ib@Arebj^i#l z(D__tKmvH>q#NJqOybSjW0?u=WV*FpzbBlEe89VkrIsfU?aThkE-g@Xd{NC(XQ@p; zo1?W{-Y}EbJbI2f8W(WAgaP(de*JI7313OU zF4Z6_O?T2?p!o&liHWFO3bV+{^0^M0auqK5$E+(2p9bdw9wT_x^98kUfKE&NZV?eD zV8tPG?`ap_ZBBnBbr+5mr6?>wg!j(tH@%h>UJs8sqs&4P8!kc@CqL4&52HS0D83!+U$E~=l8Q1p8l#E@|&lJcBUq$YvM+c3GbmPa+q7yDoMp`T>hd*_y$!MTX{HY(l z!lE~slF?Nk%M&@rn;icwtS_WusT|eeIRvAgM5?ZiBZdClUHfp`%9>qyU4l{n1ZW})7lSs3ahCG zHB-3Gck(wd)zZ;sA8Dvy-7g$M+g-OcWM z{`2_UOs_>hrMaVGh#!$&{hAgM8LPiy!ohE~Jb9GW;vw6%leTKk_G~{PfmZBPoe}wXuS= zK%l|LdpZhP95*RX0>9b`;*K&-uOxpQv|Z3T0C6Kv=(cg?8wzPY7HU}mO2Z8LVGM)~ zB?6&~YF8NsITolUjWc;dIJiCX)`8jIHf}HttXwmPcx(fmt@r6KEIKpy(>LdZo4*v8wi9yB2%eN{Jz3-bRR)@f z<2oBlZa%`l{20EQd+LR3^F}KsW}!ApHegcA`4>`}~oD@3_%5Kiidr-YdcE3w=z=WVYV;T>TS(+TAW0)&6Me`+O*Y2SZKg> zR%U;UBf3hTvI;od2-^x3T#EcBfP?>lubdUk%~Kg6iSJ67VtNt3caV_|8a2^6`JR&v zS4dr!EyF9-GL&M~xhl z@4-_&U-pr%X|T*@Dyav11Ohp=&~v36f2O;Hi_e{g<2PWf^WLIV#A6LROHP*WelM8c z+#`u~{+qAHfqOtm?v-%=SU)0P&-6lbq4HSi$%?}7G6XSLKtrIrhTcZyaB}I*<*~V0 z01DF?M)D*XgP5Nbrsx4_w=2nTixy(6_1=Zs95`p4Icc`Ao|zBjG3eliXIMT$Y`4{{ zP3?cF%*nBCx~Ou2$FdUM7JPPEu}SC={p5sokMQi{d1Y)7>e< zWMbp+&3vO<13{sfnd+*|yb=YBzKs4&`aZVt!VWE`hSWHJ7XW(*V4;wZ_};x!wtnJ-<|X`ekOAR zx>3IK8Q$+p64lMBMT1gfhxz#yS4$=6|FB-%i;oohE)O8Vc?$D9ny*Gz--cFwE_|S? z^G+rGW@#WSLrZsgCN`S{N8HQV`en!8C(zz?jNp8$0cTJ}9f z(HST5?_mtL%K?CljEqQ2+*2II&%?b`k8JA4>==Ylm^7TdHn|G!^ps1}pryNaoE&Sq zH{X@x69S^d*^KznAT;6HO_GQQEu#oM9Ylc~@uFVUy$3!DCl^Cqx#VYI#UGv=Q)rb_ z719=t_cm6$J$&@BnPdepFy)=u=1`b~XYlmbDw{m^<1Y&{`zcIHuvl+D9OBa>&0@c@ zjT7ojW86%2vwFDFxaqymZ$Qjcqp_Gv6zL$_z06cGD{yiZxP2<+-^@D;ozq-T&1f)x zf*$DcPxf?2|fla=xT*-kL zBTA5EhdN$&%#e`BFE>>)N2oI6roCpgg#Xyv0IQK~d2Ho7t9h6Ok*jM&(cd6=-Lutt zroH~xKCve|OdW47JY(PA{n_&F3!kr83_hQ)=)hPnW6X`9Kw{-PD|uJDGU%faZ?YIS z*W?S?6Ef`f@Z=LZICqCfUcLET`ONl1s?vA7Q0Ft7FEf18J=)fQilyzOcj=Q}^at0! z&=Sb&$F#*`%(2u=EiXRU1HP?%muWSLDr@8$s?`^uo9S{%bD#c;0%1jB~ym8}Ir4K4RCa!d)+hG-XR+1y^ zskpbkv21lrpthhX9atk_SvTit$Z!X4+mpDV!7`Abq(TyItK0Te>gkE$Am7V1%)^j* zGN%!eb_|m>m5?LXix~f2-mVNSS!y>R0k{US>+Q~%oHJAINFih5U45ABt)~dm3B$o-w__@ zJ5(9&ArR@tgf_9_scyemiMsYzV>jJ4$yYdH-j-G~Z<95R52F8J=16Dr34|v4>Z9SIZ4v?JksO1xwQGx~T$?x!ge$=T zYq0x8k6oJ*p<_`eJO&R4QZ39bP{C_W+y)Zdh5T#6BqRowbV)XqbLb+jGSu5HyqEh0 za7e^8^+Fd+#Xt?s|Hx_!?}q}_T17_xmrRjudP=#{U65>2nrP}qOgC|4s+&f-o~u4n z(+luq2~u1x4sELftO0;ji+lQWJ$KP4-C!5Vl!^m74h80d>VA9lm9y?Rurq|f&VYJ{ zTDF!MXEjAM7u>2PxAZ!^1WzK}RIkVvuCa_Y(E*Wj3!~1sIMqR>&-m+4zCOh=HHyoU z>wxFgH14soKPBxzQuS^d`u>fR0sQrR>$FB5bKzTLg^8DFza zC)g4*O8r%MD5#$Af_7m8H&Px)b&cvzj&H1il11sbEKI)O#@*kLfbYHEy8b5Nx#l}K z)^TIFp|fMVjNIriw5#Ob_F(FZd|Dq+gx<^>r^&kARTNUxK~%(Ii1iN1?ai9gDj$3?b-#%KAFUKb35^zd^j47K(G0uEY8lBl>)NK1SVuI zqCV>p#^^PlDaxnG4sXeJZq?c(_f}m?6Mn~%AIeUBn~3UNYA{R-4r3|ot-qD5^MU#5 z%U9i*DfrrL9;V!!pBwZ8u=i@3QuXy6IoPa)JWwHM%`wX8FZkv?lbXZ=VfK0ydU^89 zKnzP&z%)g{ahTB0%R*aihNke{tq|T4_Ml91aPzvs$?t=SPr05(vYWacmdSq`L*5@~ zneNUkF*KRwb`WJqRZrY5q20YxYa91bja;|0FAZ*E)8ja1bs@KrIKPS$Dbwp_@pUJH z+D0>Ky3W>&=LRd;FuO%zLuOd5OgS^ac-()4^jQgz%LH6_<3s4wnHODx61_DQdbHMHKue z_PU~qN5N8aoB-dqFM(v&lz_k-vB{LPU*lm&Qv)rx&R$m`zvD>#^KB_qsDz>bWDX~i zpP=s6?#%0-R0ss7RU}?z=Xm$oRudb@Ni+dD3E%`!&25)ZDvVXFTbfqKaZy=>C)BgP zeUjtA(OzAvp`S~}4+xJ;=q~_#cIoW5!&Qv~@N?M>Cj2%l+Q@tqUVa48Ud3$e)Iq;!uj8 z^5xu3%eFQ#?7KS@rMdV*GDuqY42lc=L~NEHO*AABm=IN5GxVaaV>3NZ*Ue8AloY4XBq>^Aq1r~a$~mZllv z)j>Wona)O3hcn;Nrxi7P7#?22WN761M@Btug+*!1QIkT6Bm5-dG`v6X$43=FFh%RT zk2i?^!Zp54hPL#*E|UFF27cGp?S$lBZ6zHP;J!e$OJ) z)=mLc(j6(-84YL^!E#;%va7k{JydH`e#;NUtUn+his3!s8=kuHD?MP>tk1vB#V1_O zSQ{)Mvu}c769RBz?p3WJHHrOIAA5)>Ky#rrFQ)_S;hw~b1X+KA% z)J5$7BJQlhs#?Qu4=CN;-Q6i6-JOecQPK?pib%64>F!Qx5JZp?q@=qWQIQlx@qCND z_c`bG-29J^H~0X;T62E$jWK?s`Zlt{j?;cjV>^6nY@jZ@-ye>{QzL*suUDc`#msw% z0Ar>IK5wE?>$+vW6*2sCf%}E_@Nhis&(-n6g%nP5%Y)a)> zlddAU#f{sIfA%*z6JG_u%FAW~=JZ&(FYBv66drtJ-lNGe-1*7R%dvu9i~`GQ+Z(cy z))ki6?HxiK)h$o|5{d`Xk>@GMOI~lkF-L7S;#?0!g43Lp(}9c|Zj?ya1oKIuY-5A_ z^+hLO&;5&@;}`!al-KpGcC6kwz`WQk=%{1?K#`kLo9tQm%cjN#%3kw)WU`c&iUe4P zzC}HN5u(-ehC8w|?4;QGLE>s6^zOAlm#MDyK5Zk*^04JuM3IURn3gw-fTE{~J|R&$ zj!MONo2=c=e4`p#k>dkci;HP7w?qRw0)20)lSHS9YtTKl33J)qq&q9q*aphdPX6n4 zbn9+zn&vQ)(U&>YDFM{ry>flH0kLYi59epLo)F66i zi_;ZZUwvEB`j+*Cil4+0qwDBYer+drol-2t$6XYda5Lol6CwbRZ8!}(ED22Uod$YN z*z~cMuJtdw{rjaDH-UL+ydLlZEAsz|9)bct(6XlKbkj|BMIx*w=%d2 zsH=AH1$KDDAR>E1#?pbbnXcjM5Lm}g+J2@l0;8{acC5>pxQIj-G6&88is#jp#NhMI zbD_a|=K~t>h<@7z&0VbF9w7m2pdj|X5h4NT3chiPk?*UQZ7UW^fg``=KfnD||JKP* zz|ZE~q*PaOOmzuM-9~*V>uYO6nq4?|E29)5F!$l}_v&DKeH~u2|5M?i`4K%gT2-$l0FFW_rHIm== zvBGDSNj^K_b6Ad+{nH>5FEVU^XJgPC`I&zU9{}c}z}{(M`Jk2g6t>=Qu{Mk5j)$D1XfmmIQn%%7At8HxAg`6BG!*}1wtW>G$b&-;uu5gd%#E=>`7?I~|~j(w~IiNB0~Ug|(56mtU_>Xr3N)JVAUS)-*S1+|** zfS`$cG>%{LLh=__<7F$Xm9}?+-YnV3U|^jNeyKsY)V7fg$G#l{T?_~y1FlWDkrY@S z{D8T%Aw||CJxCBc3P0(fvDNh%Gc|Tw;)`wFQ@#-kq_jotF>*({PC>j_BUc`)ZtY8~ zjw3U*n^%4$W7F%|dg#4kXlYsI%|!zqi)OE@vgDr$Q#dqk=<7R_D?eyxwFHWke3SxL zYHI(eQFF9~b{g(aIb9Ay7rxu&L`$2#--gri?AH9++KB7^q0}|MtB?Nn}XP3dd!TKQ+AU-fHr_7THJq)V3vM#lR)CSQO zI|L%v)Rl#u$2p?Q!(*!+Y)=VA<##&>O!kX*4)J``UeRov1+wA~Q3alR8-N&0>F8Fy zjjW++g5bOVax$D5a6e?1IaG{LNO=eOWGV1K%pd)3O@9kbDliz%KIZ$2puA|w%~o-a zyXdX?J$7AZ2Q(~C!gjuDPH2FbcWIBccOr4a($Z|ujn+=Rf8d_cKy0!x1CajrUNMl3v$q@VV z`(Em3HkjSYPYZHYf0?xY*p!D8wNCVazM<{wW!q5@Qk4W3rDqj)7 zF}ca|S-r;lHpS#j$uNf3f2ZF46WgO>^x=b|NRr!-wn0^xpFB5n;|FK4MNec@26jS$ z(R81-u8*+-B69d)pM{rw!d12pG=su1B(uAjE#3LB@#ByjVk|It}6lu2n! zYP1M`b7061P%TYvZS2c6a$o`G^5v}lhTEOGa7Rl8KBr6NQ#KJVv*xd|~ z;_&ha8bD9iQm6Gq9H5bCp9V?k1LQ~09N2BNNNu*ahg{t!{^Xjo2p?DiIxspH zc=n9(Y-Ee;$fxHnpM$xXPFaN~!`5*$xXrrEdsgrDW>!HyPE2z#gM?yDQ> zGqR*FC>A0MDjgWlN6uqfszQtxxcAo@+-nES^a;S+{v8imn$yeBbtuC7sR7Vp3(2gN zAYn$6h>LhcY+ezI$?C%IwAs>A>`g$u3*~1U8v!Y-9~x{y8x^@C@Ax)Ewjr~b*&chZ zg2t2APOZV6UhMj-vE8TI**5xeGdoc;B1)o$X>7ej+zjW=no%Gfm}lLd?VtU^DzBM= z1*bf|BfLt{3!^d|VL7nKwm85|+!P_0eyz!IY~9Fc)6BhK1+i#qOMYvHp_M9KdJqRv zYLW&hN)F9I58x8>Th+@i8 zCnP+l#6lh5&T%%b0ce?PkE>wL$Upg?RWlfkq-T5*mi*i+npF?^KSf9?C_>cXT5v<4 z1^*4X&+tZ*1(3^0ylk93RIpN#Sq3`fcqgGXHFGL^}XSd2dV{`R8Uwlr)*#uJjfbpgC^ z1}88RtmeZTOcAt znhGrmwTDPHoM{V;%h*DcG*SzmvqH(O*@z_Z4IMFU^XR|x!dpt3Io~eAFqx|?8wbsA zU$qg`Hbk_QJ}o1B_@q*9y7ryLiZnb_{R{QsEe4qXo!rm=sKESh9Q9rr@RbE(Hqsel zlGZf20U6WYQCrC}!e-rv3qWJhIYswL44^O(vOi2A094=zFbDru>~I>YoyeO8ylHnX z+*oj~Rz>|&-hoJIADk{Q9Iou%`isEAT8H|S*zk!Mc0_@VIKSe%&|nsFXd6CwZC8aG zfaIVYpit2idMPI(${>CtEApYS2>s~_Ia$T|Ch~dIw%@s;y-PmF4?e(w2u6?7xc#B*f9+0iBaY+x)+s3dg^lisu3kj)`23p5Qbr zRPes5aC@U0B|3>aLTaO0zgjWY_e*jJ86Wd->!IXgyKjeMV1BlOrmT$Gy&GKeNjT3C4Vpf#lPH9s zg+!V0fcOP{Kuu;`i@>*j`3z^!8}aLQCi|$B!|DeEqH1O-$eaK|zw;{Z4fB^7llotv zz17u=S6xU>^mFxj+z*4Xqm&UUJpJ6Eo&n;cHLHL?=?nP|nlI;fa)bjEim`5=cOl^$;jz~!1Gy4 zE<47PZGz+mhx*zy4%M3_t$qQ30x1b zmI>-9=%3_;CD6B|)lSNNI}*zM1arIz$fYonY$Mb^JL{>grqPj*Wz!~uUV*H#G~I@m zi>bDg)fIhYZMJJd@3o~uQwh+;&@396QsfSZ)9(Yex$N8=75w$1YcUX;Z+htphisWVaD`^^r^`<)=!P z_R*?!J<5e=37hwdv7occQRr=9mC*#F!}IfSM09-kPCB3KQkE>Q=Rm`hjS$1DI7yS8 zaQdvF9e$$;6lm0pPilw~>Dvjm@r%i?!Pys(xXS%iz9x35WJ*v*FRKcSy;U1#)@SXJsHW4omr9snlHuG=o{H+i ztO}_+$q7;T=Tuv*Q3NEp39av?OM^cwozFb^T>Z0#>&AKcDyH0mP4x@l32K@y#5Td!Yj zgU5EjeN2|XKpA!BZE*f!U3d*ps-^s=qJbyeuO>ep=-U@#!2mny@FKMld>$14-)wL# zFgG(wlswP+hl6E@HA=*ncaM6qzq;a`rt8=Qaw&|X%pDW|c=Mc6gG;j`xL_yT$6t&& z{%cKSe`))7(UA(pkms|50ol&)pHEeP_Ys=0S-)gCalT0CZpt?fzLl^;BshGZhk9A( zU_57D!C034OJQxI#H!Trvh>EW;rMv?2Gp;n_T3Ra6H)plR##sAW~FHt4to~r9Npz> z0nTQ^mvg^+>O?GpJUhMT4c)Sxe7w4A>!qAcyG!@P9h2*8+cmz(ynmUvFo&8sGqwDy z=v?9tbKU%nP4RI3n|948Ro*~buku)yAIWf~N0dtFA6vpSzJ&OVi<&m-WaA=9MA=fISYbs7NiM5b9%|)X`BcQv#oKx++ff9 z9{9a$;C^rWCAPGGf;+!(r&g2n0ey^G3=kOI9jbvRO$<<(lL~?~FTl`Z=NQ4~9Rykc z+z2fZ5;{Pwd7$F>p>bzf1uTJfupj+`p^iNODfc3{d@G0CZ#l47OQwr_nUY5EUfpX; z!~cZRKs>|b{K?V|ztkIEVtB!ePpruIWlv%AN6C>odud`}a!b-CgL%-mWf5Z-tQk^X z!13Y;;Th$sLaKblNg|y5ZtG_Rh!$TV3CM9Ea%UlmpjYG|Vn6`Nw=nx^bJDzZNpbAw zMiT}#r6IH8!SUE_6+{Ffde&pfmr6)DPYLTB)X>{7U-$>~*KwDn0*g1ne{wf8G!->3 ziurH36%My@rBBQInp0Dbd2qR(TaTOJkm^W8ofca{K1GC!a9FDu3e=XB9&;l)vKuL* z6*R4->CzceZGx48Nt@nekJgV0`Zu>|LGb)sLF;jWHcuoqB8s6Yv=hT8CDJ5ab0DQL zoUL?Lj)a8cks>($W!cF>8Uqb8dO&R_;3D9(jPMAVnG>0V81Eg4s#3cQ3-j(`#vdk7 zh_b*VKx#2DRH!$`K#Zg2$3c|dTOPyn0EeM(SW9|w*=1zcJ75z~BcN$t)`%^zB6sYF z;3B6dKwZUGE#f1PQ%OtALfy#&^2F9I{U0Mdc~lM^B3M>~>-_wR_s0h|L+TmncDE06 zfuXv##;b1C<(b1PMJx^rRyKV#pu2C%EfSRJBme^bZ-Zi~2bh_xet@%v2=`KO59)vm z4mT3F^#mK#62N_vFbPTt=)dk^Vk!?hBQT5YgD1YVJY>n6^>ma|ONIZ(+2wP-Vsy?+ z^G*lEAWahh1MonYCe8_aDhDxFQ7S;Ut67+O@nt2QfXGL?I=CF8OdfSeS5=h}vX8^P% z)U$2eR$A&@`SpaKEk~N-K3ycZfox51CcK-5Q+qi~Jow6u@*Wopgzz;Y*?Qtp%kC`N zhF}CC5exXE>DL%N)#c*qvzrzK$U?*)r}HPTso}6jcy@%Jlc@5uzL4+Xz@9_E;fSEW z9W#%I4vsO3OrSUxT67iqUe@Y#zynf1{x~lg>1Ii%jrZQ%tHjr*6Kgj|nf6d1@@#Ct zs_`l*6?L9Y1CZ7GuuygUZ*@(T?6LYDlIP1|jsk;|_cWrooCzd+l<6tDntsLr>TD6_``l z?DR01XUWWLaUHBpRnNwG0sH}w>Ua&cWkG?VN|3drprT#u`R?dL+{c!$$6oPPR>KNw zW&8qxU-}bA5X%{uxGOU0#N1gZJ$ab8Q3{Vu+uo-AMSuZFhWre#w9_^$(w^FOt`(oe zu<;mm^8Nb{=L;=$(-9rfgFB zjGO?`9ATObV7_LaF-9F^UF-H3RcJOK{p`z~qd$q%uUzZ>W1*?GU#RAIl{QmNFMLf4 z;n{FoggxCT4xZhtK)2Mf3sk zg?AWVw4h`-d73Ps))NzE&0%xx(y7z1JV3)kAb+6{P*YyQjU}#C1>VK@SH8&4kRrYt z4%vu{t(Lq@8cu2@&t+!&knkMoF)_cOd$;jl1RV5OmKniUW!5p2m|oLnM9>ldQ>69f z=pu3^5&BiWO#l4TLVnhzqwk{u`2_Ys;@a6vlqBm3@^p!t3hd`j4n0DpKeQ-ZvPuLw zNNPW#nyzMXjZBHxV6*G0K72}`{mT#UXe{1Y>q(DLtCtXsyhigE=xk^10C1nqwOetk z;R))Nmqp(=xiW?}%(oZtXqs>4X(dP-jbuy8+|GGI(KsdP7l^)$%w5j5^cVHUtI%b=zSTcz7vLO5kAjhKx)U>gSu(N6tQSRSA8#vn)> zPTx%1s^jzwl_0;J8E4RExx1%~jW1Wz?WWhzE7;_wx8+izC5YS!fQc&4Rw81SE=(Kd z%`<8KZ&Q?BSIV?f{A@y}jF_Oz-nVvCSl_v-7YQ%CEip9)alh2BT&~-Dd11bg>Psi(bms|_mxvlt{?of|6D9;r0*e0s!FUeI8>W+c}S$2 zDOM>ko!y)gv4=E@k6L!`SuZN*_&$riy#$gb=Uq8ZT2OH=GReCYNO=Gx6TQ-rn>%3e(w%zc+PD~%_ZrrHgDuSycD zH!M4bST`-A62RlZkR2%YiI;r>LEmx%s*-h)OC%&Po$nzMH-;#y`P>VlsY(39C>8~x zF=}avtn?1kRCc~V@5rEXzR`MEqP>4Wmwj>E1h?+YjNyo%YZ#i^CWiJen?bmY>#B^X zOw_V%NG6)+E#CcX10E*|W~7DRb1%LyEqB*mqXq4CZ+Y669z)JBbG@>d?4jw2BXCD{ za14RJEEF}I+*TH3WX`=7yR;iBG!H~Rdo9Xx`o-XvqEVK`{{8(!!LEVQ`HYE>jhDv?69N;k8A52%`8b`c9^zz4atJC44{aCk}W z(?zC2OAQormJpV1U3-&QP8v20_15ys|!{=|?=tf?mA1JesGXL=Q#pwnI9 zd`DgpGfO4bQtA{7(u@b7bQaa)upVm0s#Z^MFZeLu`gKQSZPz{8lqiCz5)`5TqHw$_ z(`<$Eob5+UjjS9Ds4f<-^zuytrW9UJG$jK!K7_2rrGlAAg;-hUya@J;7QnVNAWcZB zH64`)wYO~d1*f>pn0hYq?m1pMwQgr>@{8ipMiLU5OmbV{{W7y`hqhgrC*vZ4p+6$I z$SZKoE$}%xR%@Vbm;1~)nJ#Ucl@S+?!e2VBVU*lilKL?nU#UTA_D*OqWmD<0;cj8@ z%TbY9gjbvhI{MoIbZEY#U*5p{-eBb3mfsFTo3_UhU`KNk5=OOeapX<4bb$?eieP$t zRD{x<{yvr$RW+t}?V za8bWYMp%?#85sIf-oPbJ_e_R`!mcgFw^6nsa4gk-&VhDT*iN;@DHZp`x{BN`JAG&w zZ<&%5^h76nnC6Kc86DPJnwc(coz`KHpZ<#qD1gT+geiMXP!9 z+btDqcGkQ&xRZ$+0hrAD&;rNNouMY+#3Jdesbp1Xa(E3J03Fz1T6HJ6)Aoz!6;8`Y zy49>N_U_A~xI4zyvxD(MA{&2t@6lg>JBtVU}RHiF5ne-TS;3&h%4Vz%x z_|5YQK|YvYY|XI3?8v?a53e8q!sO>!=B-U-!0v=K{z-CP6aV+C4Sgc@18lavzr%lp zobGB67C}AJ#!YJqmSBW+_QM>WE8T|^lyYV&AY}bc7zDUSnZ5PlgCB_i@#)tK2)&Cv zA_H%0s*#X8m_b3%8=3FAyY4dU+a``b41B5{~(#I2j> z`Ue;uP|UQ22{_h7(deA0Y&?P?$XhVJa4#iGYRSr_*1+Ws7}c}XN6xNE44bypyt6jl zfX*l*FFpi<+Im4LUhc5!B9Q7vn00$Udk}FF!7v3nV->aOMuY6DM=`*9q$_3plBG(P zp_~e03bG^D2CjcDjjAY2XsQ$5%-G@77#tB|_PvV>D&I#+Nh;v|}&vlHtHVq94j zYFC=xSh)<;j@U!gt9GhYRH|atg1i$J*2u91yxr6!s1yXgSh$GACDgS_+hwDw7yy3+8#wu>X};swyBbs1 zV1br)#wE1YJCVzJ)}8++636ZYkWrLKuID=Ap)2nIYQxF2PrEY2Fw?M6qQvZ!-ks-% z!i4!1;Z=!%KPRzQxKG-{%ay|ONLtqmR7zpgC%;z+{vuQt(!Vo>xeTWhtpg?QKKhMa}#_Oq}MIN#p0&v>%Tm|7;aS@nloI13397b4|wLUw-mc zQBnp5%=5HOmH7|GJIEX(mQ^Ocd5-=wb)acg>xo>dfs^%zAct&h52LLo|OJxh2o(j}HV)9?WhXoLMHIq&BQ0IygXVLk1x5V14!hCuC5@+VJlBBuT zbX}G$s#X`|6xLm>y6&c@XuBx2*)e-7x?>@KoV3`AEe5eZ$jsN}Hf6O9?+XViH8D?% z=UK+H{SvMiGA?yyzFT{|l}?hcY&zr7A+jZTbk(n!zUAiH zBtCNz*>zmD6j5icI%E6RJVov`SQR;sNmk_P$BgAsQ~Gb1nX_AXIdI~3wXcF>gTTEm zYI<7)({MJ;3&!5Qzppl5i;6>m$5V>^jMNkPMe$f0smQ6LWBDM+ICx`)v*EYxAUHYm zY)%CM=ZH{4!?bzd^{c3o={$Abk@3;$8o7U-&2J~)cQGJxJ0k)oC^~+s0ZWLA=V9#X zQNqWUvK_MsU1-At5ec)!C-bL^63Z5{t`M@9z1ebyA^wU zR57GRC}h;WzLQN$-f}5Lkjqz4OCnH;rSt(`w-~k^6FVS|XsTC3=7io*1WIw}Eaw}) zPj6S*8^7r3=T=8CY2|*gU+eqS2UB_o)Ub&QtuA|`5=N*xAHXQIVV9IE^f)xa4E-2=_pQN)Y9OkjTuKpWW-)bqrG9eDt9T;OM3YE1&>fikk<@n$(w1f_|7;tmGv*`W@zjT zZ^rRnu5I!cfg<;@spCUD$NQ$34Ln>ZM3t>0C$TsA7sr+ano-VDqA*KHhEsm7?#2U&C6IlcGfZb<6qc`~%fe4v&))EQFv+P6hk@JJA6girI5#B&YB~|j>Xg4UW!MGy1h}- zsB(HnZlwl;uWi$DE1o}pwO8k|#Jp|wRGI+*$q((KKv^@W0ZI2rcF#@-1axQXnI=-M z;ie4KBdF0T_OuMOrLfc`e!XeQ&TOjfWyu*Cd}?YB z=|~@S!@|-u@#e}e?2@EY(IkAlbW4`lpeeWia`~KKe5}pP!$AHIl@IN8I@)QZgxHbH zSuNt$KV^%Hj&tXzI|HbHaFxr@$D&gct&J~cUQ2}#hYQ@VP8)$kj)hs@knmIhy7KXG z*dg6{Luw{BTcL(|PX0~RUIuB_oC=2!zTGfP#Nk;&;KB6*-&!D8t5^t$!`}?Ads$*b zWMcdWlwKg))v1ht=sAryVvRHn9hG8-oe2O;@vA2$URLdA(0_o!*kNt9CFM1b?}}=8 zbZhk%@2#PDFlG;i~#${`v|p;Rs`2;2WL+>|A8qDeIB_l z9261mB*bEmO7Z38?=P=PaCrfSQeQ`_^+OS0y4p5}&nFY_kLvQ)GIS0g#@`=X*_$~# zn{Q$Y(oJYPYhI$=vF(2eKRPsL7TMNlG1i44FoQYYy;Bb8N-_B1(@$#p1it6>Ncl2Y zkmp|3veRmulv}FaT|K>CRD=$g!~3|4>nkMiO0EX9{hUS3irgpn_Iz?f9rn3pxNG|r zp6e(29U){bw1e0hL&ET9(47?10nwcss|E=WuSzMvjz??68B~0lDG+oIHu<8bd3{m=Q#(K)$;0AA~gysFJEC1^$^t);9yets^YcY)yEJT5gY zs@Aiu^57%aC{)mXdyp7-Q=ajrn+QD+M1oG%^eT0G+L+e7_=VaGG+h7p;!Y$c<1fO4 zs8PtzFz%{B+lSJ>0K=^rHZyfJ?aTuxXKv#e<(M{1Uwr&r603YY2Aoz>n6sR##!Z|q z{A}yW1cFvupYCgn_2u3MI4!0y-{_jpM3%MlK~m}LYlY2Bb3mRwUVqX2^yW6=>=D(c z?sU}rdS!bxORgVAb?<~MvO0PtqD^yjOg$Kw^KqLpl<{j^G&A-MKZ#*$C5)#PX>dj| zn$G75Y8Nc?ftk__$Mv6z2cQna$nkj<7{>kIZZH|X8=R_lG{fm?iqs^K;e%x)x-%=# ziZy-{6v1?J$DQc&F6F>v&p^r@Q(4(_Mtgy1$!O^cL3`X)NI&YO*}7WyqNqaW3ldn7 ze(b?5r|x7ElpuHeRn^~_lEMILO@BCT7i5D#(B*}$-B0#FR%T-Au1Ll8av^{fJA#Y@ zZ2Hy>&7clYrw!EpD8Qhbf16LVcoD}Xo$OT#fkATI4*0Kj8rqTKlB>3gM*##*>p7|{ z4jZRL9*GVMSgS1@Q3pwg>ubhaStv>dm(;n;4tHqdeswbO6|A~B);6Bct^Y2wUKXM+ zekSpr`BOc3899$J&St?j&e_M=^D}?dwDyd0ek*u8``t(N*6QEX3_C5(UG4&^P)Uu$ z{ntx?n8Fz8;H5dg_BqSIJnH(o0&aa%XyrqemLbDQb*Bds)LID(bK3dMo9U^9c{n)_ z3B@E6x;Aw)Oq6^iAQ;%CoD$ei=ZvwqG0oJ`CZd#;eNKB1?xkIEOs^-ak&iEd|~)~&=eoC=0lOSftk+q-+Mph(Lc$ow?;7^l6BYZ1zQab zt#ok?IM|KGTmf+|)Hi)ya|l@htYLbNSaQIQMisyvX%4qBs;3Vbo?2{FEky*@Sg92)Jxy|f##?&c0DyYqn zbXq?7LTY}^wd`rMjHGGN|u9sj6wVyQe;_)sjdjqk*FbNEGJQDNew!E{Rxx<&i@fzqqsgPlLk2u zgNH2;5?;sMwvWS4Aoy&W)jqri!{;x;9au6XgDIs;m5ga7`lAxUuc+6n|K#QJVt8H6 zf{lQ00uKA|Gr)JX_RIYZb^zC@&_R`Y6T~oz`e)B3k8tef)NsT2^jQ7WO8g zx)o~T#mB`y{VbS)srF%;d$;ozg1+f=!%6bj?iWQ%&mcmcO!BT`Tg3z#kSh!rX4Ysb zqNbUgEMfeb7=9A0O0>+-xA#s65XHg>Nep9TaW!!1>zo!x9(H}G+@=eKSEz;q7@18j zMQpqsF`st~KTdzaAmP9=C3(~|09LOv^tSJXWEo%wcl7Bx{m>Q+Pf%m=zAicaaPNokkt#_k@OKqgj2d3*T^xIz^ooM^}1aI($+iVW?Ercm*_V)?biO zTe`vF&j)sd`1@c-7?0H+WJx{OzJJn5M$RfD`J|N6BDpQ^)f;&9g6C3^TLnD*y>hDZ@i*iLu6-rbl<~(6j zM84JV8v81jpm!ng1);&rw!}PMvIe`NQaM;R%R8WHKB^MsV_wp)-oi9ZFKz{IIZOtU zMf^#uz*^?M11+`~@zn-dv@h5*h0WDtI!>v7y61xKbq@J_%`!=I7Ul`)bdEAc=@0j7 zwHs-7Jc;4yIRrvN?~dwQfq|V}w+iU;vaaI=z9CN)Mb_6)y{kU1azu6-mOo+tX|UZa z(PmIlrxBhT$-0Dl+HrNl($ylcH|YP|6u$hL_CW36rJy^^0Nw?Ba}zmdpf`cCa|q!r zBN1wSxrlVykxk0(sdL8ApB&u~uL0lT{r-2(etFEUY_BU2xV6afKq_wFcS{=%PbBht z=CMCT_wBghLT-ymDz*1(9=;P*nn%$OCMb_6cY^2!(y9m6A0T^4%m`|#ivXOx!d&-l zdAzUkKGyE1@&2ED<251^>a3s1n(NZ{;|DJd>l{`>l1*(0Cup++&W(w*V9sjx=9k1# zjM1?Yvu+;x%s3PvwAMOsqo{*R+GDRsXsbF`#^3FwW3$2Am#2*GdGMr=s(WGm97~d@ zJD@iYcLn1G$_o$6Q!`p>GkznO(bOouRVuNxo=M9PGHu+YGds&?Aj`IYVpwMUq>Ndt za+;vDhA8`r=zl}}qU*(jEGd|?J9(*Y>l`%$$3`;x>34-~?czp{oKN|rXMMEO2PPU+6+3YbvY_^|lc&Bn$Fsw8CTW))w{ z9J}g1|MXcW5s`(Pd{0Z#@Pl0?I=-!T;0m?t?m?C7XL3I`#sJegiMDhq0EcB2V1cNY zB$V|?JAWCL4s64^k^2J)plWqpQK+(qqnnfen>AVfGi!26B?PNe3DW?VT5b^M0GP#f z#>`lkbKJaS>P7hc z*WsJ!hxoenq7I`YPqu~9M36H_j_Er3F$VqF*>iO`R`D!LG%9-Z;JGFT!60=D>8(FEyh^%b#ea%qTC@ z_Ns(`VV+6M^ZdHxE|}L&Z%z7z`dKgdFGBKri1vbV=3LevyPG^SP%y_86#T3a{55(m z0lowH#x|E3`#z(0O_CqG7LM!3j*|W&?39dJ-hU~H=ur)DlfG;?i=_-Qty$-r2*x+; z@)3Tw=IrcAF-`m1HkjUgZ8CoAo6O$<1aW)>Bt)bK$f!uj4<8_cKM3F>1pJ2t{K$B8 z^n8SmWp#9)cnBmi$mu~}5fO(ZF$#JX$y+!6T}D7d1YaP7Ao1JPTb;EIlX|}V^>qBu z58LdHn*XW4wMb7h@{)Io+RsWOWwvKleKQ5ByU9U;c}d`XPiQb>25;h~=>}*L*=q&Bdc6?v|uaVoa{} z`K?t?Pd3eOrHMMmo~hg@HwhGkYxPj0aF%hsI5^kkW=OxmgVBtMR@i&)?Jl`kdbp;!IT zQ~azu5IwPEY#Q~H;XEa)=%KtK(Y1+{VXYEk33*E9HqZ!^2zn7y;SXKJPeXT7z7WHD zg(Qdg2cwquA|1u`pioVcIDC<6V5O|ceNmNKHL|Mng!-nPUfzE2i{q6wZQ<;sB+HoC zcE38WF!7&G_vO-1mF`BjR}ZK3gn#NT>NaR+`F8&irie z;^a^=C>QyNl&$T^ioYFA&*yN6aM-2z@=u$)uHL{YrC2)!y?2^#Wt-FT8HH;e`b?U3 zq(82d*pEznm$Tq%3?dVQ#M00)UXw2NSE~;G4JMY0`>x0cL?&(=WG3^1n2T+8lRtXV zv-)D{;~Dh zVHttg+yarK+KPE75BoyP6-{SPf_L)h_k>~x_fxe{YNJ@S}nF?^!d^aMqgQduNT z!SUD814(JyeM&TTsA2dt{#pJF!vxG!WTm*6IMkWBS=XKpG$d4HcAq&CxV-jX-K|mz zyW+d+54Mv2sPTa6GjWKOnkN{~gfb0>1c~_-dmC-V3()Cq^~OE^(T+wcQu;UsT&328 z&1tC~l^v~0Aw+CHHd=NNqP7jW9#`&|%yNAHD9052D?wOqjL3hMua+~-aR)-miDM`f zl#_a~qhqpY@LZaXYjxa)Z!P2@0CJ&=5VIf|X#8Q|-bb~1-OG@!BRz`Np%EW!i~`gyNK|HkGi7-uwHN zco}XPVHLin!O};L=sAzjj21#;*a;(9D!1v2PYbyylqIFS$~iOGj&FMFuBJz3?l$mN zB{N@ag)#D?>`6c0G_2LymOyPxY^sURUF|hKW!#5(Y2U;ME1XbqB`iq}i{d(RL#oe; zCRJ}MyuLzOrJwlTAe+~5My^j;sWEH}nlnkIKBm@2-!p+dhhRS2qnS|Ta(!%K3Tu5t zBI&tZ76;K(6&xKO|3&sfzqf+lYIS-;)0*F1x+{uGP)Iw=iOWR~+r_aFpREIG()HB! z+E|NDrIv@=o^HA7{Iv& ze@56d2?!sijB?cWVx*#!c6pt8=-=3kZnsysxzv32^)(KUC(+Z{qyFXtth}sQ4+4aa zT8*`qh_@bOiOROi*B&;f^snu^OsGuSK~}}iOI{KNa$`$L8qsEQS~WQK8C+; zT%A*GFy}RPyuXtEnC`OYio8jj`b5CdWGp_Dm24Hi-Z0k?xUCZBtxQpFW5Vi$?1Dp{ zE|H-;1EigDX z#gvmz#UqKIZuRr=h9@0n_TbJN0p+`E!-O{eYFOw z&N{BdlBGqk@H?n>e1xRCNv@6NsO%8QRFb%;#NA;}dHIkkEB&w!AtBd`w5rCGc82vY z62GI#-lR66tWSlN;VGX!#+;|X$AbDddiymc3sGMx{wctCY13&u!X*{SlH_Bf@pVJD zN0uc?I>qU(Gk6Z{wzWAwf!~*S>1B$Oqphn+LC8c8BUiZd<_~pVa7nWYnqI z8jLAuODw?oRlGi7IOeKWq}Z-<^Lq5aDp^k*eE*JAVFBVh!~)wVd^d!ToctTlcQwNF zHw<0BUZ;Tf<4*VB31JyAwDM39{)oE}aak`eKoq#U7%^BpRi;$&s(i29Olj)XUOG4EL3jH^L)F$c}x5LSsaXz$5w-_EQ_DJq66g%fqQaN@!RUZBB>kTZF?UitW74_QpL8%22xg%0CTe*(K^gT@vY-M4%{gg&Pl=#;A4Q7*}2 z3fu7I!Nz*DvG7{P)10uFJpIkT+ZmBS0|%cVkQe_&Fjt8?;E0K}f73*97mBNvV}Je8 zA+&rb8c8#PWg@L3-(W>Vw+JPV96QtG;-Q-lku1gStK&0k)#LYx!o-XR=U@Fx9L+gq zb-7fC{oCSxN+thA$iIf)3jC{MM3!02l;4qlM+mtU=(HFP6PB<}tWDqHv_~PVG;rC?&WW4^Ab` z)Ho}HwXldRa^+`#bfW5k-mi?T>c?hpA46PVKGh4U+^oo`C}afqvz$^6!MKGYfs2Gp zsbiwzB_mEVcS4IS$`E)k>lCeeuW_leHOCA*hQ8?XH%IWyR}&-SzL@7lf&Nw>^P%fi zCa97$P&D*O@0vjc?@cgbv@7nW;gom1&S4Xz*@zfN}wR zmS=IePD#Hv+Y{MhE`LziFa!sEEeb)6Mc@_Nw8JW;q2uEI@PUsp%05>9&fnZZWpk{}|a zy_RqN1pB`F+sY_2x=Gq6gBX!X2G>d5cG#2;j)n-Le694@FtHa~&;=2PFrIpJw^S3E zIGU*mlXye^ zb*ZZtd?_%U!1%?g0rp^89H|^W(zug>F^0Hy5)#V^ouM#7wgiS%onfXp(T8VfJKX)v zG>7_8csC68n;*I%Q6$V~3PWLNH$|3Q-g~d^e&fIO!9E_0d2!CajvaqQB@sy@`AGAI z!{dQde19Qyr#Ci*iOXNM@x9Wv0*<6VKY?Fz`j)+XqnLo`iglg$J8U(sXX$i zubI6whvKd?NKpTg_&dteP}#SYZ7GOPNz0d=Z;Zo^(=8@yuWbZ|7`>-=tSKxzXu88dcq>BJ#p;d=|!9d6>Wn+cOn(Z1T$n?*yOr za@7!|J7w#0W=M*0S=n9Fsy*a;yZXJ7=VM=^f661TNl&P!J&kf^y5{XH_LVhfi~gTB%;_I%^EZe{N0aVXGl7^H_;S$-?;k zUAyte{ekBIo)i@%yo8Gt+?oX1fk+p~@AG3!CJ}T+NGq&A-Z>?Ay_j6?c~fv1{6l}_ z%-iOrSh;`vW;7ecmGKaYGMBdVb z{Xz_tPtuv>Aa(_9w9u{g1-H83h}%Jec)m>Oe?QCccejss=Muk5*_pcEt;^v5mW*LZ zYpRpQ=<6_!ffzAy%?Z_Urn_ArA7Vb2#GGc)?KB>9kt!#P=WNfor2VOoQs0Mal}4cM z{C=mqK!WhAt=zXXXY42wl735u$E3os16eugVeb(Gk=7?8xOkqaUF}NSOZ={WV-)tF zBT*Pnd4lPd9Is=fbDk7~&T8W|b?n4*p_zX^A0|kdC;G^awAlTee_`*5N~y<6OqfQ* zOLysy3OrtKS|j?Rl~0Be2KT75o!8UczY*(woGtE~)vVg!KhL3wc~aqy;aVUzX$gON zm?cnQHF--$U}xrYYd8HxkT+S25vJ5z48mCg9b z&cYcp!UVNy=cDz2JjWjcRjECryXkm=`04i(x*J|1ZHI%Q>9QVN>}@{%>J)YyE&v;% zoRc4#@l;OuK+k1XMz&R*P+`d|293gggoBDp*FpSy1}0HS=7Ii)$u^@cLoTm)XY6nj z#mh%~FlO^wPJG0OuRdEJpor8Ze-RQ;6@5pRjaVLF?rlaga)uKVsT1s3q8C9jI1Qq0 ztm^=v5&G`wL1CFralaOp9}(|w*qy&erp+VoNj-+bk>dWBoM_FM37QIcF8&^ietES* zl?_va7x6Pswln%ZmPZu1)D1qw6@)m7_^4lcmoNRu6E|W+`|)xop3xD>^Mp5yU&JfHWM&D50cpI(sYZQ6;||@~BNU(ARI;|5S`gEbwl&^)}1X#Zwae zI#^}JFAvp6j6w!E7-2k&a#*2{wGSTT&W|#;XP784V4$-goUkt)F_b?MDv=9hvED{` z;P6XFX62|OIs>s#S7P0X5ZXJ*EV~a5_l6HPuf$xZwnFnYaZ?_KofV)#=pM@QPg$RS zUx+$aJ8}|3RvkVo{)l^pJbV|9r4=WhX7M41%AnsBYjsf|ERp|cwYQ%+l8C_1aBXZ& ztZp*07{7B;Jk5zvIgGCIa19{DYF_6*hoqT(-$o>WjiA4^yBy#9R+pK`vJiVhn(w}l z&ffXFKapaVYEF3p9I9ws-=uM?cfq&_7TCt%;fb_kMQ%#WUq6 zoJVW*vLt_I+T636esX>ojjeEKZC#5Kq95&1*oMPr-FxrS4FKdc^f}AmsWJv4uJ%&` znskmCh}ZK%pOa%cv!YKVSO?4o{Ps2AxF3W57tQOtua)SUnib@GMl$2&>O#I;z)u1| z_lRCI5YWH(TpRd{Hn~JAzMOzuTMRf$xcVM(-2{T{fvCS|ZC$5_gkmqtV!Fj#8BsqV zzlb1$F28>9>RVL+<9oH@@ncSKobPNTa(!u>Q#m5Yi zxRFHob_Q8Rds+`yike$Lq;9H_7WDz|%u}3JAhWasM+Co)3F{ReyugbWiF13K<5jI4 z>VJCh6yfCCO%C}s4RbgDPb99vYCCQPy~&csCNV=?VNMV6#i}(Qlv3*%c<_5ohOnl6 z9dJNU#12+*D4!pC#Sb92f!k?ajvqiP6PZ0y+@#_^tSB+m6Z|;y%nZdDL{i$v^R{9ybZ=WQ6o=T3QlM@DUO3{v?l)bnY*?Au z0Fja~kkC$Z%T+`?D?-$}|C(?uSnpj=eQQVptLoGw6{Dw{DHc>p&4N=#M$mf$oDw zY>)0Qo8%VboOZ$p*X-gi$=G-Wg8nq5N4|MaXtK+^9@XUMXks%l>39`hL?a!OLc?y5gt}D9k6s=8bzw*7llf6!G2B+2qEWtb|u+ z*?2fjMQZTeaijuSz$4{_u~gHpqWsgD;=2v_u5TLP>}@3r?-(4NG~Rvfd1JsDxiCaW zh2!rsti3RqVDvhR`aI&6FK{2XxzKHwGg}$ zyHd8X*w>1uFFo$7&7M<6TGI{Di5aq8C=jOm8Rc6Kcg%jvGSq-4tt;mu**gOiq}uF~ z5*NZc5uV66*29O9oq|@#=lRdxq(dpN$M5H)CRJOEaEoIG@;ZCy5>lE4rsCj0L#l%^o${aN#rX1JsUaY}1<%IvRV$8l8<3R=wnov=npgy)9>#VLfeD*^H64=kH-5UK-aE_PY{5bMFZh(R z6n9J!eFd!?MiT4AA-z!_c?v3<-K^T(Byo%P>F(Dkkjgj13_1jd!vYcFR8;b=x7J=+ z-X)cPt;8@I3E}kr(<4W))+{BvaX!0LPK&BARo4V9pD;c*{%W8kC&i_cMqMfLKHR(_EXEqkY2 zgJIjS6HJEAOnN(+{OKHv?YYABcD<$ha<9)H>;Hr|9=f*ghSHZV#0XReJYExO#Ku8( zoqg`8EDY16h2Y0=QSe6#YRTa+dFg+nYq5Av(yzrZ>iSaSy!uE5WF`jj`Ts+Am%={9Yuo6MKU~c*6 z#dl+2{Jut-lYlKEiU!#(WKSa%uJYMh*vTMmu>Qnd0FdKH#PY8+=1^l?xDq|4jk?2s zv>cbn%Ib3zV(An8IPDhC!%%9tYT8Mgiz&aO3v8X)vvc2IPj;l6H>98>#8ubn7ORzX z(*;waGe>6qs9*Pw6TwG8OVYw4dY2_y`2!KjW+i&Y!VY&!;#eRu&Z+195$R=R{T)L` zcFVor0$Z9b)Q8-gVLoh#tD}1!7aEnhnagn(cg7FlH31$jGrF25v@J9bS%5c@YqT^! zN76WY;E8lvxN1B&rSp=ojNY=t{1I#ho^Sfr2hrfuMs-m05N$D@MR_ zy(c8UJ|!aDr`yk3YEQV%cEZwAL?|GV&7kHsIp z?hBndbJzFOamLRR67XaAK_Y{d`q%VZOM7i{WA_i1TWTzC!)FazgeGIixSyte`TgKEmReM@S;f(SP``6{ie2rN z(L>EgX!d^3Q$Q+=0n&D8MrhYTI4@bT?s}mXEr2&pP&x7uANppgLR{FT(_gfv#i6(6 zI_pImgkxF{N5438Lmw1f@{HGtQt2rLFSCk&@#GULu*xMbFQTLX`a4B?PCr^0CYbiYn9qT9V31~D-Q3Jb?iLWGgN3#U{>Tse1=XR#_GNYSjF#Wd@_>nQK+)gh?Ix; z_daD6PrXar0k{pOVNXF z(_mj8;n7z@Sd?WB@Jo;j)-e3Z74l065H`rYPSoJVczM{w_UTbpCDen()FV+bU-kEG z*D1DeMCs7Tg&VoXpE}G*Ef>Huac)AESrCuJbNwBa#@ePYhx*Y~rb7kk$tU~N12_sp zGOvxOsIRy#ZdW+&1lZF;wP14AT@|(aH5XNX?5-YPHD15DUI6j?U$l|`-@o$#j{}?@ zy@?-l!LHq}1s8C*h`wIt16P~Ah<+&LvKWuyqAJD#?)IQdBS1}br*>!aitRl$_8SKl zVj^b0Ru*V*2ELGOS%%HHACKC*m4V8a&;41azdtj>GblD8C)#9VX1^}h*?)vP^r!NE zvR3u)7bTNsFZ#0-#^09(j7T6YUrxewIuc~rSu?gNZb;G|K>DsLFUkQY%r+|iUe~ed z&_18w@an0TAO47t=v_IRUXEXmHapPD0xu1C6pM{xRgFS}o_pfAuELPh+5dsBvFU-6 z(}3T(h}&uQxUcy*vPS}Nz(d%iDvi?_)_gH~aDITWtH(xgISfH)RQ!|7zFJ?sF)(GZ zfoyXMT``|diMu~jYLD-N-m=#x5LM1&S+xq5E6S$gmEnQXcml1>~EL z61&_Q2n}iWrN`n7gU~oz5paKw4ypGg6sxPl)%`6F!XE%2=dqB7dA;DjZMt9ZJ&z&_ zFWZV!S&B}K3ey$wKY03$P@tk1u&h6s&tgOBll$cQ!T_z!7X~g&d(`U6`P5#l&dYxR zxy_D-6~3k5n$}pY&PI)Q^sKJ4!K9J=4Y{E=UegcyP~3;|>%Ha#gIh9cp#ei5qF>q#AR4vsFb^X#g_m|aCfPnutn<`F*74H_PS~doY0lN!a(i2IA2~qkO@56`;6^yL3nd0(RfiP{3<}< zU+l}A>mBaZpD|El<;2rxKU#bAr>6;L+N%x^^Oj!$)jXr71anx}t9>jCX9>ZuDCyJX zMm?(9oyi~!#R6S+bIVfxdX_>=+(VH5+rzIhg8h;ZiYcFHL+4-G&PuqzCH?{Z4nJ0$l_-O7ujVhNzkJh7y&zU>S zJtVJwD7@Y~wxE0yNqtpxbsi4Lli=<(=s8+xEW@6P=Yg|h4*GdPQw!>3R{Ll-o_$NL zrov_bgp2g?yw{7pk0M$peG<7Pu}l2JtkT~)sInf4Wgf1w?jbM__aE@~NQ%9540>94 z^gXHH_USoHRCIMAIo=hJO@zhlHh2spmz(8(Z=Ev=?Usx#|bF0{JJ z6KAx);o5RCO6|;Q?hi|S-56XT%*r29wBmBZYA2&@A`xr?8wwr%K9XU^;Mk=r;M5pgpJ8?)yB^ao4{K9O}+ z4Bb#D;2q5Chu0b0dmko<2)^z z_H7fx43pu2)C^;qy`ic8=+ZL~V!ECL)u>5;9J@HcA=m#!-2U)^6#;vUA6llNnT$$9 zfMH3md^XXAGR5Nk8tP)2y5h)~Gd!^h;QGLG*8X6+(sQlze{v&u5*Wr z`A1Lwq7eodMvS&S9QqQle0wdlQ)c?<;aM4$puLK3r#xA zDgxT~bzbI3aD7=479z6#juOQ zwQurg`}F&!(QDQ;0yh!gHfwy&>|$3V?o8Q7oW$JFkP=$+OuGu%<;S=Rj{F6_I=hv?D%OZd?nkD+wALz;@F&P zd$BAngs@fO?qCdA<-wP#N!BN}*Nyj6ZHKNV`^PTg2%dr}-EeVNWQFC{Sz)8~RfQ9X z775F)x#a8_DgL7E6IMv*htFtH2t!j%!^5W{eitT$%!NaVKg&@N?^0aJ-^_vKm261m z)QFk#FcZxY)rB@&0o|ebtYKSl}-DFhd0c-z&ZPCgAx&Xe>4Glx~j~0yKHo z_0FLvD9EFB-|6CwBX{DJk!z7qPF0Ok1NPg1&(KjdH@5P=4z{tO@E&0x2_$dD#R=Qh z$R#808z~K2bFArq12kF>MWj2@uE-h7$`^XS#9YBJX&Km=yt6;4G!((k+h(3InU_|P zh1h!UiXEOS!8K(wtoudSN*8i!sexG<*4}jTTJ2R46(|jGaQUojUJ|iOk9&Ch@if|x zb(r_lL2>PPeJ9d6iEm=z)$u)jODoEXmv(bPbN_7;sSJ(IXM8ik}g<0Xrv%{d^` zU4o-_3s^E!po~4mpt&uh^buADYqz;9?h4ept3_5m%QF>%cKp`Dk<(A88z_VN%wzXm z(9OPnZ?dQx#J)%AeybOp@3458gSSRV5(u^ciH%IbZoiL@lWt6!#5t#|%nwP@c8A7IC#>*gq^1~L|E zFbrHL6A9DNTAwU)EblMy+p>fPw+}f2iqBuHN?oh3D2Z| zq%~F+3$$rza+71A;45xXCjv1uBxM3tIGM=T8|aG1Act91lJJg93j^70&|881I}?j) zfA=$A4}LK5dBNq~9di7l^yJ}6lrSHr1oK>fPx81-=Oms{Uxu>)W)w!{h;Vjut5{PG zOEfO$6=c732F&gLN36=_9DpEz-G-W4)WjZrd&_xq9#4a_Q8Qduj(Aw&SNy&@30IZk z(zKI~tVkUnbRQp8aB=ey;D3(gQB%~dU^%%EYGwZ3E@>fX-Cu$O!|KCTg+i+9_hEkC zs|rP{wS}(V0YESI7wy&gTAzDZz~KuE@6nYDua~c`R@Q@t@l@6pHeTKeu_IX^zFMU@ zT<`knOh?S|C4@@p*^)7T{N!KI`1R5C$-uke2Ey~>hqs0rl=mX9eviwfMV?9cN`&Ap zH{o8g6b4!GF6rVA>#TxpAq*ww#T@6NZ-^%o`5YkGN5tG2Za~>Aw3IV z3Ax4EF>zOWbv@LdWZDKW?DiRU%*Qf585G=Iu;aS2U~M$Nyr|3riyN5?QqTP(BP+B# z2{mUVs#8#_+Jo>F4Zs&KzzeabjE#)^{5T)b&dvx=WVId|6jFYFO~}QCU)iZ4F3&qy zmN~kaK(0fzBz9O~t@1?hAp3ckyNJr&q)&_tKx7BmgI~JzuVHco(0mE!AaJJh(sSdE zruJA#$YFj?lgE=UrpUg?K;W_VWTc&l8^WZVrCI!s8(De}xDoaN13=KQ8KwyST%-yN zSOY2?g0lNWoE-X(N8gv{nj2@o;vI-Dk0E>zcA}@tTC{C3SOxvkePyH!T;VXv;IBp zsme*kB)S%rJ@c}H&R}mE#%u*o0F(IT5v^JJ4%yH=CKA{Ps|x6=*sk5+FbF-hjdIx1 z>{o@aseYB2^=-!mspQ0I%<4s39<|PLn^bvgUvqE4AUmAtQ1VD}=X9+RiNGHx-Oy6U zKKHk}Tm47|M(h*!8~$QMTyQiAzpe6Dj3_%2MTVpXYG5LbfJ6kSR%`rq;?$aV=slfdM5`Rvv?;n#X_POTk_5C{TZ1{O2r~6F)$)T~T`VbtTfp9`C*;9<$U=z#fI~KrS!0^I7`7e{=T1 zi^hyJR8o9h5cTmvcJh5F@TJ@XP?X8Z#!-CWD=_{1qT&E0(F(Yf}CMf ztVm_8^fds0)&T(Yx))FDt_Cg2zo+nC3N{gf8xl7Xzfhb@fHuBS|b?Y&79cwT5Ez^9M8@&n;?d85nI)s=gCT0$Rc=3SgNZvqh&tr5xz8+UQ@2V;6+Nb(mo7 zhEBuY9ACDE;e8%4u80yOgci;0NM%?DIG@RWfXB;aRa$#%EFqPRCm~2D;OWuL&E*$! zPZ-%yA_sd%p+3iD(1S!ZYiW*);Mp?~oI-#xq;O1km4?raa8aU#?FmZ~aAS}&H0l8X zyPjlfsbY?=_?^9{=O_fiqq2B!gKMY1Dl6~|h`K2}XiH?6)1-uZ`{Q}Cs8~N-I-0LO zYLOC4R1CrizbdDy3pg4GjFnir6cb1a%?ui7u*49&zVFX0z^dNiW!vwH-espq(U-u$ zJ_B?EC}u`uM)963Ao=g4YnQ8Hd~FVuVI`38I@G@Xe5+tNCQyy~jGlmqPQAZ5IG%x- zTTh>jVNkY{fQ_uB?S5jlDXwhW?D2MAXtLEPO5fKp#OADIdfTey?#7T=J`4oFJaLz! z`FH;v3rdW7e>Q{<(QZsu98d$DWYA)DsLwm2<;QaO7~rqSczi-^({U99KK889pKkDU8Te4GQ0TUSz03O^?dVClzD_+XMblc|1`Z%&#ar_D$6jdBJwL%)I2QgdYs{@CL^n zrjd466fJe1K?{(dNNux>Vqk3eQEUt7M-5ELjfppQqb>fg5$j0&adH7QZ&#>4KK4Dw zJf;ZiHa_}v-A<;N7}KN`?VTVgQGyT7tv4z{{|8?GpX<<({MV{}Q}je$0XwfSP!Z#8 zCwVQls5nxbYyQFkw+-P#Rc$|TuA5c<^5y8@)`;xIWe<%NEkKB+j30A5a@=8G=5F2) z``;l&{JU|Kq5Sof>Qz>C6XtEa1+R}NB0PcT+;V0l&FKV_0~x==$i7+o$^L)M zx$OUVi($>KZgPjX@iwiryel9tS(><4qM!g~=aZm(TXsEFdFBN%2arju@XKcba%9pbvC$ zI8vTc<7n0~S04QH`Z>oN?0fw!Y?a@=jK(HIa9DfS6Dwbk7PM|nsdJC>R^5o_{d(@9 z8O)6NtIZikAS&;T4SS=18B3?8RS<6FNC@K{Pw9^~$^O8j78t7C+be8DQnW3R+DH9a zfsXF}@zlZ;{q5q0*EDdO5#jo>-qH3NQ1KPs({#)A^=PwHAJ__9w?jyPJzjbas6~o+ zzH=6^^ZYHM1W&{d()NeF{UYzg(4M}avfaeW&$U=HDCO+Ly(1A_E@w!|YwT97ikX(? zLo10E!9P0%(x_b7dOELrgyJFXC`t2V54!>6YyAiTP68%q$nk1l0iwUYFoG$%lAwKG zLYcSQ#fkt|!dFBl{W`>d2DT9L=V)&L18A?$OYwmMI!wE+f&tzf9CBMK$DS8est~@X z6P6XY-dEuLSaZK5Z~)%#!S7m~f;Kx<#jEo`FPdT`fhZi0B3(_y@^FU)OTtG$kxpcB z?$_NfqZEd1=sr*B#*lU|-E%c6U%C-$00j54vA*bv`P*}8;dw9kmV!kS&$ExkugaV_Eq22I~3*Ty&?2EEZkdP77;hte#7%)4$wqEdfFKpxoQS0n6j zWUunhDI66xN&|E-z%6}lQ$Af(l7N@LS1`#{XP-%bDn8WN63DKKhh*2Y>Z?s3sBR<- z6$T9e3hM_y0Q+N}&}X~$BSb+_5q0w8(MF(vt8WbwTJWIreRKzM)V$>x=MGJi=&TMq zKb(n5zJ6Gr8ANK_f3#Y*_nc6*C+v&H{H1hKFmFf#dK5`=T;a0t4j#fD?)vSD4dodwmETr_Qu=`ADG0@Ythu}y2AEZTh{4*P{arw(?!V86^^#g zI8m#9EvnXA)`*jcMeLyxi?kpgb?%9xX~!*bxQ^rYVA*M_ZH7Vt&sGhl%bS^J%;Iik z3pGfi{M&-|jX(s_>)JH90~x&T4#&v?f?N#QX441d%KH1dYYf)!y>)6nSo~7}?qt?? zwaZZ;H~^O#cfk>zg%$EoVH{kq>j?z_=C5XZ*7~+>C842HTHQ4(S8M0!Ps}k~BnmOK zDL-dwQvx+pGauyl&ccPSUzT+DexNK>Fe@>hAB|qhG|j(-?*#-m`NOm4Dk+a^q=@xL zY-y(`Aw}Fy8xfu6hhq=jri-F1o>mP-4RGI@olO>w%j!TaFLOE+rB*5N8#-t3JeKcM zz2IRRa~Zee=dTUhfjvo%c@-=@7kflJ%D#S=F*{z0M9Fq&+jjrnq0vL-a~}GV>)@`| zPupA<$f}E-D~Ag}Zaxk$6y2@eMF1dAZ{OlmJ`tu;dP-%Kv5fWNV3odh0IjRM;FW3qbU{6C3l9?kM;1x7V)YBg*y zYKeR0N)@_sW~+(Fd}g0#ad@fw%j zF9_ralqKCGi^nAk!&1dQ$}CzXuVkGxB-E<##I}{<=u7f2;-_7(iW4%Y21Y&Y1>0ux znK0wnwb-ZP2pszc!>3a1u?S0d8{f;a)C}*+Mv7(%flue}!Kv$NwS$S*M+TlrZgsYWJ>`I?t1JBF0g?`lh} z7}CrQl~ASIdtU%Y`F6mzThg}I;hjCFQV$AaGUOQ!z|`zKBgs#Wne~;DJ98`PmTx~P zeGIdL9B2qTROwo-GIm0z8PfpXTCRrYs5e#xv+z7V%Tt(&Rvr}OUb9v+M%Eh2cRB7Z+9N`T4Em1a+;aT;0S?d^A>< z9ObCts>aSTofSk2f9J+-w1z1L$S7JDv-r$eP7~NFe`{p3C%cFyP=NbV-hM%Qy9q{Mv^{Xr})0^OT$?WmoMDy)FuUZK~W73_q75<~_FQXNkb?GFZGWth_&FebFUZZIJ2W7=ky;RvOsJpEg zp)!chuqk%ee9TLu+(h>QU9okUc^;VvHdODkezT~v^&89$CCqW*dVKQz_H;U<5ysaT z^cvxBsRqp-l;71A@{3P0?Q|CDDv}Bp@%)sR9SlS>a86cVLGBR%cunK`Gc9W#83_h#8Bn;l2dbyybRKWYGf zG`9&((APq2fz^!%(HXYy@!4BYfsIn*Jihq1da9vJW0}d2J2$d6$c4RKp7rQ5ft2JL zwZT(8xN;IGJ_PhDis6K&1X)v79%(__JxCUatf0a#WBZNMNDY=wSpX2IYoF}R3fw)@ zpU@w3F*w|L5DEykFk)#8-MJ*QqIh-|F25aIlBXh7ynmXu4pg_2MSUqTvtF4clV|t( zl=x;jpWdn!-U5Xlum6yF0ek1WdSDAmF@G358*12Qz5$DDSTAy38b#CmM#SHO#xme#=sY^S6BHY2s-8uw~51 z6Aw*#_qHj#w;KNsD1cDIJrh0{Ux1r&f!eB$Jq(YMP{LOo-|zvAn8n@ipvK(%E6ymJ zRQR`1u*MCJm%J2l`0U3No=RQC3!}{2R{c>?p)+j*+O2C%nU}!yweq z6IH(QiQIU6S`h3Ax1|F})+g_G!=KbRbN7Op%0lBLC(+q@lQ80@Rh;F{1wGeMLwV^d z3XZ;P512WMvdi5$0CQAViyT$kwPL zWl$9${+QcaN0HK9%*1Y~C9jHNI^BF7)Q)ST4p5EDiwf3x6gsE^!Vc{5jyvB?kX?6S z(n+sbN=C^6FJ@9uoQyx)@R4u!_2CUjBiHE1NK6~O2luuLDqc(tly%+*!URB;*q;9f=V$ITeapE9_@jSB(#_{z zMj+_d-p8gZp{yuVkxH3PCr>pD(+KoL~DQ1Y6Dmy&)^igK65;yBBvRpnrg zkU-?`{}ihOAr|8P#!T${=kU!q+nbryez|Xa-I1LBjSO#rA3e}@x zO~^v{=%@qvV`Xy)11v^Y!1AT&PfFB)vH|a%A@Yyk`hy1Sj9eqV_apIWkBscR)K-s- zT?#1HO!f)GDPV^ATboFncYWrc-pyP(Hj>8`1XVSo&MrNS8SE#SYe!B%Dr>jFv-hIk zPEE81gXrJx$y<=;LFJJ<_YN6mMi$(SGZgN;$1>3X9ZY!O#o;~F83IrW32e#{ACkhC zcoGhOo_l+WmZK!p9{dIh>3bLYEVmeBhq;v$=?IjY&D{<5I0tMr#Ho}Y+Hrf-?%Zv9 zH-|z-a|wt@=pQO=>3%Qvcz~6lNQbG~75j8f6z?w6+lWGP>nFGpwtMr($84Z(KG9E{ z>Zw3(O#wx8&#zl3N6ViexNMhN$>~W?8cQxfm(a9!fupFBEbvkUI%zo~rDsszcJK;J z*R|QrOr6vLgpNq^OUela`3|3mBu8ESr?*W|QsuT?$t_?Fll+uCC7-epjJQKnfvI;T zvmdl{zs8*Tlxj9^8ND=)cvhS%lrA-*4|?2mgGzL0<785KQ?lSJ8f{5Nx3BI)tB*jq zw1g^s0Z`dKyf|#|7gt)?fW>_wDa*;Y5i#>sv!$XY3_2MT`k@x}bKxPmAlt|E!;>#KTA~MXvdcTAR{O2Uy26y{>YMQ$v&OZF>MOK%J zgY~UxnPDb4veX2cbY8GUm{lt%_yM}*$=)?}!q+m@rb5lAVyI_>5}bPYGXg-d?8BzW zc_&Y-LnrV5*0F1uKM65B3qj0m{Z0{G8CxLvhLCUNz z?yW}LDs8{)>%nQnG1-e=oRRO-vKyj6<{qp0%W17*nn|x(KL*DSl=muK@7yrB8P%VC zy6VA*enuWI?f6?(METpe(-Jf5b2@X<7xbm(>^{(u@f6)oB-9AhN94q*kPSNaeM4m( zPy5>P%80Q7hS>6Q9D5YTEb6T-(>#vPASW+S!*L&mM0GV%jO?iKi~qF!Tv^1mkGs|) z)CvYJ5!Mwd@cNcFlivK9sS2om=?LHRc~bTHD&L1lfh8O@j1n*mS7@2zH|4h@&Sjs8 zCJ&R7J`c>U6pd7K_m(YO3jo~+sPF7sK59au{A<$A_e1EVTfkdUPleG%eJ=7DMw!iR z3BM)$X+=tpWUCF4BA0y;V7W(#-Y)`dh~k$;r4t7Wep?QYQ2I5A!YSd*+BC0GHk|Z$ z*9V;at2dx%I|;OaxrdDIqPd66?O)7l@D{(RLy}9tNlm5VZ{7Y#stg9xEq8AsjFtgRXSfWeZXq)MM(cX=}e2HLE;E;V+ieJXp~ ztk=m&>80B3&fXYPtUoSU_LJFrELU~cbCG;^hkUx4gP4|d#LU~3e~vnLT7UcRtUMmH|ZppuMBJy>V z+;}VyxPt-{l*|08cGt-8aZ95NSed=&5d$q9AMh{lS*UFF0I9^+ZV)5U@h`K!LWnWP zUyiRym-&4&CSp@=oGu(x;^QG!^&?dQ`;(V`?IPkm3&`n`{Cu_w>6}=sjQY&=(RaPJ z`dLwNpErp6f{7WS0Peh52Fdn!6s2j#zKS&(BxdHEkm+Rp_gTR|wC=jB3d{l%vJOfN zl~==eSh@t-#eR++u%f$bZpQ!keA!IkFf@EZ0V?n(Pqq_r>njiOmex15Xca*av5P&J zx?~23(>aM3-80a~6->(dpN69Pt8e|TWVNFe@(!dtdBz7D%DCAGzcGgO)3v{XT`*ZU zGcnBwDL`8~4l5dHx+ZHbU;6jpOO^yKsGa&ST|%@9`3zbiu-B2FS+S{tHG678F_39m z-c2$t&J<#KkolDZ=-OYYL#fLp8Y_wnGEn8D4!CuQ*@LI)PJROl9gAYe0J}_9|FCXI zZD*z1nPhBat2`aqlFJM!iRE3Bp3BqmxF!d;{to7xmjAyAk#^Yw2ft zR9D;MeBE(ajvu*;y)1nuy0a|&N`~LBy z_tLd%3@#;H*`IGtb+4}3p73{CvKVY~c4DH{VaJowWjRfC_a}d}srDl&!iG7=;}DW3 zAzXd>nc{V-$`zl|sbRnHKDE#uCx_$p_t#537TpdcDqrHM{4L?SlJ!0L;R(Ik=gT)7 zc`P0x*piGX$H3$zeVUNdHP7Sm_$_v0@oEy(4_Eo`bm{6*^$#5k3h zWB-dLuyjBUV}<`IM7j72RPI%XqiVb0H;g~sw>FDL<7|UpBT?FU*XN^$ zA1ak+Rh$^0Fp5leR5-i*EUA=xXfW+_mXn#nPh+wZFI`74_PVgq(jk^OIOjn#IA)-L&< zsKCBr%it+If0A7hYkhm|&3 zi9l3^9vQ#xgEK;^7`v?ThQOzV;{gpOiR%=cAbIz}?EL+NOoZg%4R^_>UaCc1&3n7_ zQsbi?s`=Tcct2HHUQb}1viA{@5>t2T3%I#Om64r$@Ayk|ye6M{d{fx&EsMqJjpmbbZ21>S$)vB{)hfFQHCatriKQ zH}3Uex+EY;$>XVsj*&3-fF>O$av`D>XkM3@&GIo_ zg~LA?_%ZiQ=z=lzUgQ2nTPD@YE;!-8DMEaHS-jFSZ)>aRXRBToa;yBdf)u%hDnH&H zam`B}law#k-_nvgxmbMk6;G?l|9**yj=D>|1xE zTPuoUep)pMw(*WZwQCA^mn@J*B9efCe`mEJb&IG^PS(0mtdMi^nQs&mEKMnndMJ!K zJEng2FB&ne?g6vPj}-r-fcqfEDJxiHAPs2OC*UnF8U~@o8Fb<({-&kH*O3L3;Oi{3 zm&KoL>yI`BKtNIMA{GK#0$b(qik7Sa`nKF@DVY4q_rQMbq)uD)&tJ3m|DxIN50$?B zVbcD^x#?@o%eD6bi|^fcOd3EBs;10~zi4-ibq`H0^B$NAd5RE88mAni`o0w%RmJdk zYBY@3&w!4J49h|EKU3Y7>B6C{B`?<2W5{9+yosz!(n=gh{gxFj$Ju|L$8WtTieg>* zi-vb8t|>QOf~e?!0$Ft`H@Gy;cki!UWt1pBWmrvBfSzrk?@%rr4+yX zj_;l7`oE?l05N0lPlR2&ak#b-lU`IfFocQ;l#^wwDWKylIo2SL0QJH(& zWOArQZ0&9Lo=~#umUHssD0hKsO##Hl1L6lV2<5OiG%OTv8vu8zJeNHsPU(wFmIA$F zTm?QAZcTfEi&9oLd(R1>*hijyrrQ<#SZyCwqk~7p4CU}?(uHUZ4z3%A7zNyQMvt53 zk&}=U6d8;{k&@My!t=)lXD{ysutzZLd~AybsoRd^{kW$f(>2Lmr!J2I2HeG_CoI`S zxPt#9B>VKf!t)1h+Dtp`@*{qmI0>17Ds?5=|Ck8p=JHi(zZ_EG3fBWvG*GVMUAZF| z4)BZ&n<@Yua+4~Y5nJ6fr!45^Jn?@`eZ+ygRihOJ_y; z=u6FwaSSng$xWPsYV6|*B8*%GL1o_ZQis`As+H_xP|{&=$txLuqo{o}s4A}q0pcET za13%@cM+H!#6UzJt|c$UqqL^L1u#No5CTdWSzm6VoNE^_+CVT`R9fM=aXFwMu6CN2 z(`vhU5h0#o(|)4qakECD|Ai}Li=$W|uqilc;t$l2J!hgh9&s#fQvvZVqcFy`CHYIl ztA}Ca8h_E?`<3UmjQ26)IO%-L?;|+5)!nY{=W9&eOlnSfHmzQ!o#m|eF-kPM_siL3 zq$pVIL(&vVC26j^{&AC@R7*%Ho`Y}rzylN&cxMyyM?V@xU0cP{{qnn$R^PKpDHxHs z{Fls%de@JI^}8xz(HaUW4LR;|K3)r;+swEQ)E$U^n_d4a`c?IFyU&WSSIN_TB`LNs zHhhrG4}@?1_{dNgaOD5IUBDK;y+1v0UCaZY7~=*M;^UB_EYcw}oWv|T&n#X)(9692 z1kA|@h$rnJ5JO?QH#~VUV@QA&SV49)qT+dgFwKRJ2M2vS#6DjAYe|9#i3>k$^Joa3 zHG`7(yy6bX(WpH4zt$!HNjYuLQ&gT3ql0QEbVf}P2Bklqd5?Ak+5x#jK;TdVJ(FotVse_GvS*4{`lM&z?RM8v8ogabC}8U(sp%0( z$R^BUGeHjKgej3@l=eAncBT4=%c z7OIeAY!KEdpLgR)uNBJ{36@gQAl%Nr70?Q>E zm6fi?kM3=-Cwp#_Em@{t#v`Qras?@*^osgE!SHDSqt>p%HyrQ)ltKJc>4O19*Zur; zBclfu1R|-QJKqOz#oHw8h%ijCq(moBkY_U>V8$>d{M(;xzne>uzx43OoLVUEso0wX zWs0D_)a>i#Rn^69@UP+-+iC4KTkZad|18wwLs9rx0Hm-%(kOgPi`4enU2^{aN849N zMYX^Ef+!#eNGn|;DbmuRq%?>K(t^X#A<`kCbT>$sf>I+QAWBOpF-i$2C8?AM66Zb} zJ-_$8_g(9*`_EmAb6gCwXZHT)^L?IARK?JwPZ9_R9tDx+3E%7mieTs&tm@l z)c6@OS?WOtlIR$Ycz8580jIkpG@U4lN`MAAtm1;4@TY@+}^WN$qd5tNSuy8y2`<^ zq8|CmRRoRQpx&84`+U{BQ&Bj&r*x+xyu!aYP(VYY9O#y`%sS1S1CLgE61}FEoY}o+ zw9CtPqOF%`OS^i;-AWUtv*>@m`@uDDcUvs$@nx*Rv)9T6Z9TKm^}@xtjzemY51HeF z@{Vfj_vW&`g6MBUjh^{(WyL94du%O&YbDt2HzE`d$nK8UM83PFT_>=>&09KT=ek8U zm1Y-ET-?LavhEq?GII~7NDs+jeG_C>DMX5r#b)v` zrP0sh%UV*9Tul3TQT&U{Kvwx?NE$zuuj?~0yWmzAOYc!VoxanH_Q3_jxANjMMXUYQl!p<*NI9~_-$ALah@ zU!jQg7SU0G0G4a!D?-Tf85}A4NM_~!ldqhis5$uQ+?GnAhucgZfbs+m|~{h zJVnEFgTajdZ=NQ8pmbr9FT*-242V${mglduIw3u-sW71RCJa;ZU-l{7tFAP6kd9E)jj+i*b z-)erQpK}Ut(ng62?m+zMzELixnmST7X_zI^2=nbB<5ESEz&Lgd^YyIPruWDRhF@Lv zlu;#{nY^+f^X%R)Z=6AO9{&WNmb!?|6suQy>ZFbE^aX@-zAtGuEdW^1$OtM+@DkkR8LFkPd=h$#6&I)y{ES1-?0oCZ1Iwj>N< zvOJz<_*j^wxJBuT0doinp)Ev2JpM60Emh77%d2%Y-TQuHJcv zJs>oo<6iZJ+>j|GDzB0k^BvWl1NSs2tusMs{Y}B-_6d*T&>TB!-RA5|b;FdUo0bff zyiZ+>T%_~u(qFtDmpmZV(bZp#f`oqH1>mZzVvuw1y*%fpf*jNvY2Iq~=CF(EXRAM@ zUZBFEAHP90RDGnySHYzvZI97L;1Z1ng;&-~60#;9nmnSRDmQXId-t>&y{hRc*X+p_dR>9a zONW6|iOP1nU^U>498s4jDt5Bsfg)>iTbk`f*lo-muDq(a0 zIS&by90S+Vf-GiS)U(pG{Mp#k7wEMZ&wkUVH_;z+no-sJ_>2LR7^(uo-9e?J_PhG) z)w)XBo$@BD%Hz4=d?Zu_{2Oj$%+>7n>tnh~s=Jl&rpo7SMR-cG+$W~346z6DdXLy= z44AEKM`qaa2K6^6q7EY_%p(Y)$!K=H0MNP*8MYZWP}yCdiSm!6*WXanL6x@gNC$NA zm+w|Y!jM^i5_K4vrN7~de1j_SVdRAVMljBxcF3D%T<2;Nbbv57{DDu0W}il^bXG5K zQ2T*_$*S>qZY+`RNk5{e&eiVd07)LM^4-%)uR9=6T@ONm=Hanyb{uSE6hthRYI9EbFHxJv64;m#Oel+NoFMCvk)oR-Jkk#W@S zJ*9M~pmbb;3rDtVt$fcR$o>MgY#&bM=^aJ*BeJoTj=m*1#e7E@d(eS~t<**~fNDTt zN5xUQ?-N8DhWZOTuo=bG=%WMdk%%ZIdCyZ{fs5rSS&cn9z@-X#&(&Mn3G<@y1L{4p zJ(}fv;~$d^6%c|WgeNgZKUdLzDTc?v%RcXm(%n;*hSdN0ajvCA2du@E@4pZ${XROL z+i3m&>(_d{_ReTN$)4!(n-*9Fx}P_$+nI*wbDR3)nT7Ieo;Ry$?abt4YIoG0D4}k2 z&IlCO#kWSEm?$=>{9V?dR1fE^<<=LpQ!6Qz*f8f0e!bR#mM==zhH)2^_df96V;8f0 zebq)r;p*c}C!YlRXM36x<+yXod+$R=9n1GU9wM8RSbJLL9hSI!BKm%8YAb~`G5P>DX(Zr zNp+;+)M6nS>1*Zfl~C)i*T|n6aZBpziSDqY111HZS<9Pvl&7UHIkzknZmtq;XQ)m^Dotl1nso?EZMB=zmLPlCU-@8QL=EA(bXfvVHuAF&~tTf4p_ z7&#|Mq~|%my4l}-54XA*VMr7Q+)^B|~%;|fpB59pIT~0YKCN<~Rg>>gV ze0Fs{t!4|=g0+>A_fyR-tJ0{%dn?DUzJ?L>KYL5|9Z{EpY0~eTwo}OlF#&TVC5f>E8F=zIX}*!ZFsy7yXf^-Rfh%h z_!}11jX83>ZbUAraXH>cgy#$ z!855hn0yz3x8~K1M^wR%JseRnQ9^5SSp24i^*SNlV3<}iD474$V>Z5ADM`KDMdM`K zNL3moAo%f`fFgCt!w#P(0Kg|Su-7D9FW__VhX%G}X`n9=GkcO1HB4N-fBlU_(reeA zL)DH^=Xg_X9i1tqI6YRIX|CFPEDRCTR|fV;FtV*t%k-rK_pE*sj9bxEPYVZ_70?3! zVUqWjPuW=5FJT+n<<=3JskMyf*s#i8zkYXTm};ZChgUs*lUDd8`zdKZTTUOd%U&SD0|>$am@gvD($^wQAK_$Wkf2dPY!tZ)2II@6$BTq|XzfC?__c-n~lTPxFgP zc@-}ZyO#<&lE_TPdq43_x)K{bR^RQ=tm7o`GD}xnMm1){FMJIfwCkMxXEGG$eu8u< zB=~;nSxL~Xbx5Ty7lql^8+#MqL%abfBkdxFpO7>}QvM#+Ub;4oOospGg?myx+M|%3 zw5HsVwqfID-=YSW3LQew%nlP z`n-JZo~72UdV~eaH*A|_s(qIupx|F!i;wct7I9dqMEjY*^VdUn%--&i>KEq8GmQ*dvTq?1UNb!aZC zmt@|6bsBlLo!yg5iZqb%t~`aO4zxsSF*%oT?7j;-<0(S27{X-dONE`$vu|`*q9Q%c za3_~n?}xl7onV7BIg<#va)_%~Ay1@mF43hf)5UpBSX!vM&*=lgC>n$PbGVqLy3>rI!7Tn+q?zcWxR9|K-G|EByX`ieFv(%KAUj=IzU4|!ch)D9ylm>uF>+T~ zR@Rc?HGxNhS6uxp+OO{f3T~IZ^Fc6D>5A^*>g$5F`?VdzYm!&0&-?sePv|e;o?BAH zn^n9(b*i3LxBR$Wm?dIO+@z2NU}6a)Ys_Y?NM=k}sL<2{C-&B;>X8rDkN`!h#XEbB z+R1;y_)s1$9FfmPB&fdE$DR4S>d%|{`|PiotbHHP`#+$(K&Gt{o9kPWpj|S01_}H%+{92A0JWW9HXlXf?mvg zu~&Bes%$8tU7OG|z_La4CvjR|i1z&w6GJGYNr?4w7Ah;0E2g!cT@!JuBV?P&!6O0) zL%@_{`41dQ7=;62%5_vEe|8;ZTS@4HomUe2K%wXm!iUXeYu{U}^i`;JUOw(dK1Iwt z)@v|#D7wP`Wh^pQdysK>hbLf)zx+E=Ao@Q>zPSr8HBu5n6o$0Iv?tzTWGsqcQb`Vk z!6?iEAnW;uVdv8aIrbC&4C_ZHjfV5h>wVEaR${VLP;X+_ZR#$FK6(%x?LYMISd9~y zXuwEYn1%8o!v|?AX!L^UuGT2Z=Z#QwElLtSOQLq(yxtz|b)tGGl%O+IoeM{tR<{x< z$QbQ+(;K+i76|Aa55&>&Omab_Td*kcjN?J*DVghwP&YjiCerus1>w)Uu~)XC0~|Aj z*6aOPWM_^1+%-{NQqQVvD2JoMzsESFG$T6+X9*$+Khh<(4Q8is>;b{QL#$y!f1Sf^ z0!Hl31=-L2<-0Tzj*u#r+M+vbfU1m$o6VfZB!_oH3@Xb1CA?SK%_h$odYf(9i4%K3 z&X9pRYc~L*>g+pT9kt(b&7;mLbx0Bv5Q@n;;bRY|VnHI9_}>KxvhQE&+)9vF?jTFj zx1A}tCbHvr`2n=?aK8S|B)syZLlY{8RKT$@cPZfSsV={ly3&%QSx?@H>V7kjrkd*Ig0U1xK2m*zj5l8LTgx&yXJd^Z& zd$H25M)SygZc>@JfsrFt5eS~-Fyr09!n-zlzuZ@&-ivz??5Y%FmZiVm{%<3Vg$02I zVfn7@--cp#NZdAhEQUQ0WytVm98#uF|MaMSf~uK9TL~ja(#2_h@VCJn*bd<=Bf$`c zq94w)yhh%A_`LV`J^1Kl31cYIY6X{->s#+M30#|gHlF)1p(hgxaNGlzky_N6n-LMm z;~98)@XyQ1e_nRbEUT93$H<-Kr5369cN~uow3Oa+)Nbeb-Ui#>lt;*z z*TspV^WfciF0eEON6vFd`IzJyo;H&?#!{@H{Z}gXK$WDNqaT*mIDs)o-K-_r;FYGG*5k?|Em8LrjQ z*wDc->$l}E910al#7OUbM3vL+Ilgqn@=w80mJ3OP|AW&A-z2zWsCowxpRzsXwIsxq zO(hW%p_;pcyy^TH1fC49zTKnC#S`)}2TeO*_W5CqYd#rcj4OC1dp@G8p5m(H7*`rT zy$>T?8=-~|sW@4$7BkV^LTCjaXyuj*TNN_}e7rsaTBT@guwGRT|#4Qo{}CI zV>N$^J-zYdBf8!cBS-aT^1vs6J`iN;lxlBpxuc^_Q~8jwBofa51_-fMb>?yL?VzO!CHaBds83j!d>YFRN;Lw_|URzE@f}I97#hN;obGIcADRV-uup`}n)y zl6Tk5o5$hKogB40bdjM)8+n+>`u3fG%&Duvk+OF)R_e-HbWdc_pEyEGsk7#Zc;*3Z zNwoysNW0`ob+FiScpGJ=tfWAfjIw|03!Aq!a?n`wF z{6x&uR&F$9LzJ~igFU!;yd#;X@3Vn!vy*jvnTxK{2YoCjcDGyKuyovdlV5fqqi$Xk zG^GVsO4tyVNOIvaZPB={IF?_HM{PT6dp`IAjivsVsY}-Bn-4w}IM2bHtT~<^yjx61 z2DU?yDI*ot)j$H>vm<3v(@ZuvM>xCi`GaOUV57xCf!~pY>Y3L5Bg%F^j$X)X8j8mJ zMGv7|q>6wkxYyMWh7(F-3MGuZdBsZ;#Y$&J=jvhVZn@L#ZzBsh;2HD~@IjXLd?LF< zO;l#cUEKHPKjlx+Fmk)PDwUUeCOuZ=*IET)+%yCq<(R8=rT|+#uKzFgQmFH_mbOaY z{>h}=KUZ14`$|G+Q_?B%@;K~{)2?b?;3z{Q(qph)_#X_)KRA3YyR>P5I!7SQq!Cc< z%0ek;CuNkoy7iXN&(TbhN(?8tQ`4|X1SAc%e+d)`T;<+GXD;N z;Lpg)$E`mQE43vBwlKpD)(2IQ7nA1|jQog{`WqfcfIxf6I9F5QH@y!WEw?stt|+kO zb=7PJSS2dC0tnH{1y;6hz-#x6{~B^sdOo*SzWWv_BWMMOomHs*^;z#&=QKtrMOwED z0EBrAw$ghSD7Jn&jCsoy3W^Yt=Bpz zn$?_y<~-6F&yCiF-5kP7B2CG5*+0p5P`~GzvlNbl05e@tTjgbGs6pCbAf%-iZPGfxmqB9YcAsMeE;C!2cK3 zYXbM<4%S+nZTSo4kn7n6*8O}ja1{BPPun88BD=qm5<%pHz>M3B{a%Ia1zVcLLZ~Nji(EgTX zXq~QiwcT969yk;sK{-~Qtuu#cf97u|sfqUgEt2QX1GhbW)K2G3{IeUgcM&pI`)qV> zm;@OsUbAI2C#7{UJ3g)Hm7XPyWX2Dys*zDCf3c4nWP*)$b1e7!#5h_5(T1d#L}oHCq_|~*40~k#jjTS{i{6M8 z#fy^rBnrK<`=R=u4woi}M*TAh|H0v2PiGgH@#mJ;wd{)QtS}Gr#z@s>_j&K(FoK%i zqszJDh`RNa>a(ZQej(eZS(bP@bbh>}ZZ|y=6^Q&w{tITy>1E>jI|yue0+U}#(*Sfg z=ZvA;rqablDnU%ZLVR!C`YV#}5 z=a~=)FfijFVee64DAK!2sm+Sly`KK8Z_e?`M!NGqI7;AZgm3Sig$|I8HTe^?HU8J) zvR#n&2Gj-l0AYTl^QFrCvDPta*3KwfU&EguK6vh>v}Oxf4s}Jf?c5bw^vbAQh$-LQ zk#L64O@RFSj68yp`^g3$lB+$BPkd@`?hjB$`;m9%H@KB|>t5Nj?Dp+F=cq-cIWN}Z zi8g)2$T6!3gg7DBcO(aE%wtyg`nc0yw7ff@Ap>>Ke{i}Owkmitp4esD_Dv}gB!hx; zg~-f}Z)G!?>_PHbA@({1cX8r^&qr^b3SHCk915zZVLw~N{~p5;!*1*7 z7fN>N?TipZO#TdLvKytJ5!h!2U|6^AyR?L1kA#H<(E|P*idIX+a;g|t=^=7$C1N_! zk<~4~b%u%ka`*U#=GhdXOb@OOlYSHZO$IH67fY|7SH*&4{;1vY;08%3jefnJp=#UB zv(g=EK-AEb<>pbnnnWY&ee*JSS z-q}||C_me&zU{OurI8|w|7J>-2|4#GP!g+Z8C3wT@29GlmL~!Zw3Z_QyQs`sYM&z= zN+xVO`JjDHg8piI4+FKN!FqZw_ZCE=56{+MJ9~G|zP0pa&A~`t3jJVPRY<{brxw%jNoia8jVJnZ#+w86ryKgBKh=eO2Ll zn`ZpLlE;?8=s@n$VBm)gxHqn_QK$IHxKSyBaADE+4}$Qbn4>-cFjrQQAfvjTiN>Ay zs5AKFZI=X}4uvr}elnPWb6m*t>=Rt2RR3yN5M!PFV5BVVMHS}bN>g+h3TmhIg8kNGras9IvA(yaQQ$Kx*C8INeWMsG+H zFec~P5!1F4m2;2DVmvoK*~qw5lB~)JkHm7kes?BODdxJUwy?%t9OiV3)_D!>biFJ0 z&b)H9cG;tsT=Z+k$gzOhgh$ER&Kbn{pkcsuR#2wa2-a$7<(8XxkGjX8nHL$=F`DEN zJ-L^l%`TJP`3_#57B35gUfuwhb3D(6^@jP8+7XO7VcV52)r=m+$;m#Z2}%yqE`B`L*jYjZf>S)z@pl;oo=GGycs(s#&P29EAQ zokCv0lfFdUxytZAz7A2KNpHflC>`XTMSoudpKZ3*d80!_(SXNpppe>`7oO)V>HW`| z{YP(kAdPC7ceccwi7((H*XoG=8qznf{!I8gEpasBB;%KCu-;I4k`KCtzG@?9QJEWF zwPteQYIX5!3EGy=otXu%F9Jguuy(TZVjnldl|GS~F3Xz7gC4R5&^2doDQS6|tWt)w z?R@y4&<+H-3XO%kEf102oNltHmLOFg*nq`e^w_{+6AmK*1q&0%<6J|5M`n4Ml~Fv) zOxKK)FG!!r$`fSNnm5B$oyu5OO~T`uI%d)XTgd_2T0;yx&^ZQiTR7-;M7Mi#_v#~! zChn`kH5QIJ*?On%O0}2MNB2vG#~0uMX%qSfEwwk^qDs?Cp_k3ergf#rSXAk8LZ6nt^8!}P?5 z!Q|&hd6v+FcZDht-d%qKV;0-D&V$2pS;1v_r_DKJiw9%^eoratG({HwD z?7b5q|6gh8s%UBboFSniD&;A8D9DLQO+bthdJC;@bA%5ndCuzOG5}Bx{`su!*RwZ1 zBNj6DRmQ6{ji>(o<#44+76XVT?OXIi6)M&Ih8399<3lzaPm!Z>FY-dA;jS<)OoE@t z8dAV<39WV}`W8lJmrT&wSp*4`ZyTkpzi7H+R(*x6pZRwI;SY%G*NKS@z9}3KoCtOB zNy*u`Sc>r2Yi zg+LG>9O+s2avJ;Y!EkN7+ADT!4<$9F4|m%rww+H8(&!(@FrJRL=xW4^ZDdod=dZyA zkr{$+opld5ExM>3ruHx&H2q_;nxI(zvSZXKd9o!4(sddrg=Lg-VOx~Y?-6v$1ivTP zPk1gg+CKZZf(bNUqyN;X{IgL)nw1-fM9mAuRnZRZ%k24U~a~ixAGt5 z2=e(CPj573LMEYBkA4gI-B-E^jJ+KD{YtnpZxUg^CGV6OtgipyybJu`@dp@zHv>(g zSjTRz-Xr;mI>n#2)_66{^Trrm_eU$~AULdVMPCvZ_?j5pLJ#Kw{V&qi|KJ!H06Mb2 zeD^zUUnVD3dmV@S-z+)-ZUR(uI?nf>Kesz5^I3|Fj#BjWq0;Hp5WHihh^xwCOq!5+ z=&dx|(Quu}7;$B>*F-Y0cXmq;*D@TM)g{XPVJ z)9u!F^<}?A=;Fxpe)sqIdq z;^S00H0kr?aCUXd%TPT>U6yoap%dgTBqrf{Al30?$`@TVO zgx@(}tmmFk5j64(oKHK1Q+jN46+*o?&AxY4o3iU&SYrr4K_E6L7I%J}N^!3^=BD>O zQ@hgbf_cmqE;|vW&w$G@(StO3@bY)hr@o{gon^ut1YQ|7)N658zgSA0IZ`>vFFa4p zU{4o@j9`cl%$XwLfpHKv2#_xZGyJ&vIwLNcl`*agQgMiIP?7u^-?paGiLJKZ$3Jtu ztt18i0_U(<0?vw_ML{63{^~bog=T4?i&)9Z^35GMt`*{+|MuFPH2EbZgK6>aD@Iax zdwn{-hMqL~%oIz1B2gtL79--HmAt*Eobg$pQnPl@`hvFL;M=dEtIl~9wp8*8rerE4 z!4zHDId&uL)S#gG;BtxYbm1|j7j4w1rL*gyn0T6r=_bxM|Mt%Z-%l-B{>;nwm>Mc8 zNr}rMummnLK7r=E!lz7Tb*`Ic7|46n=WtbF1glzZXm%`xy=A%v@N+|YQm|g!u&O=* z!6?9ay@D>P8>xLt6*Zj;J}w*>{lbwBlAz+qd-H=Wl88q|HEaJ2g+ycslM1)Qv8U=! zW-`jw8!adi`&>j|R3g@7nZeUy61Uam>(`Oud^t`9YcC zcJ-wj2x|)Q&n@b@&UQxz>V%$MOm}^H=RP$%?7j&2V_8hA<}ml*{xbzkR9zNVqJk5Y+njaM`Er z@QIG}R5XTX1OxVnby-uC;P2(?74?8T!Yg<}bbNr;Vlh^vqY zIeUl=TSkktiL*LKj{l=)y}->K5dW;S1k5?Xgy)zw!!4Hk>X%BNo~?=LYWcEWV%vz~ z!hsF@IY0&f!IAnTgssLsW#I8llUMY& zoHClEwsl1+Q_$zYBCg3O;uBRL>RU<_ohrZ+RcSKyCO?x2a&A9U;>%k>L`tH7w^^$@ zCIM!IvNnKl9%9b0a~-IUDYsD`*oI#2A?7Oo!0R_vW}I;1JCu_*lS*se%#bRb#+@>t z6HHjk^0t67xI^oHkw){m*?yn}HdDF>{06&tpv|@uJ2PFpr{JzPb@%=L*hj!dHsLOu z9FH;&5~S1Xk-iTMxj`Rar91Zq#=|dJ7V32MaXDVxp!zGmg*ogLxN82H?Qms3)Vvw? z`!HIuNx=hiaSmDj=6L`z<@hHPsKP2m-xH#Fo@uN;rE^bfMnL;Coof-t79gxZOzbs4 zS1LHE6ze4)Q^=RQTDYm-wG{_g=e?5j9I0+53(c~u4Orf9DU1NPq9i&-rV0{7thA1O zPHKDAIxmtR(Yji^8tyh3lfUsQ|50%~Lz4uXh#Z3>C|2a z>s#J=m_=$z^|o&%9m=k5^-6gO%C=@^-Z*obFkZ4Kc(+7w=pXBd6sV1i$=^TQu5*0% zk>qPxH=2$qrg+ckkB6|?;e)qx2hPv&Ugb3!yex6L-tFuyKa>$=KNYlf0ycVZUruRr zM!g-1gc(JzKUZ4Y&HvNGr8yTZrOC@Uc9#*1z9p}m$$8Xk)R$9xXVIc&XC*VH^8Mqn zn7T!W&&?^;j-#T#$xS2|hGspnm^2UtTFYp@Z_PjP!YrI<^1*nu;i~ab4&hq5x#on{ z*vLqJQ11ls@C0{%sfz8LMxRf^@9zCv{3=(v8tZEor?fA1=GE@6-Hv2~&fYB@S}2(U zo4YhQM<)3c?j#=hbr#7VTwq|2JZ2t+NWL)9TEFK4RQD6_{n+KBZkbDZa9f8VDF;l! zq%vBERZW_MVN6D}xZEN{5Z^3xsAidx@!TsXV&gz_p zt7MmL>)r8F%}rN>%j2Kdndomc!4bTFG&hq1q$(J~zomW-qYQ+b{`jca<$j$7paQ=b znZ8cA9-O{woMxL#Q#`go;$-Ji^(+e54y2odg=ns?tYB;P;nAXM$yn*z@+x66;$a20 z<jRR!^&Tv zj|@xRsEd5lJQGp2MeIvP@ZjC_xg+LypLr$YZ;2jzN?@b$k$A@IoXXK=({*zB!p7P=oJz9%$EXWol6Ie)UNr ztnByJ@9cJHb8F;&SypYa=>ys4d4V&|KZzVps%RPPOF;g+S(e7&qu;BK&a&V}V5D(2 zYU4GcL0R0f%eh-s+)&S|9;_6m{RqsUjZ+O%qQrgi`p!3wa@eV{NR11SuRDedKSgb#Ci_fi0=U-l7w1uXl}eF@ zbD!fi9Ir{S9R)IK-988$LIr# zG3QYaUUOGS$^pOb7k0QS9v;xQQcD10-StrRO!sN3AIwJv`bD|>t+#IKtB{}l7{+i% zw$62f%vefU4hOYH{snW`JBV82TsJ>fG&#g?&`y37ny*gh%N-W=>alMXnc)Sjc|H_kogDK0}qf=XHp55NLj`nYHwr}Ud z2-X~QJ~BSmY}3YtyF|nUqwv_>oo+BuaI811G?nG*V#Fj_OC=o(rc>;y-Nj>sh0)IH z?RxM;0XZAD(ym^Q%J4v&7R>7UnC73y8mCcGqOc_UQSEU*iHBFW<-o8E|Hg2RP|95E zlrFkH{c9D+k%Tu<5(Sk_Y{bQkNm8nMu{mx7uBz$Cjz>xl#Y#O9M{*VzIZYW1NSNLi zT=qaFc0Bij1K*R3?)kws%S`v4>MNX~w#{Ag#G7S1=u-zip9F|UnT(mj$~kJX1u|Tf|YTDtD=AZ%Fr$ z=NQ$c`EFr^oFpk&ksu`T;9*xn@#39Lwc(6Jw!t_1roq~*m+lTRRuGzLiE zA&mC@tS@r2cXlWV_3%+;!{b=Ivk9hV)i3K%o2<>h2@z>`6&}@w%Sv*ns zld&mxQdhoqk|?nxT;&JFYe|FWIlVp`t4k-|Sky+EE?>S02<>z50s1>_h<_Y~W2wr`6$JheVQ;whxdQS>b54At^R*ame>j-Jr# zi-k;*oF>(v)L(Fmm^9Qmq0PteB2$gBu5$A^8^J5Cdfj*2y1E*ak+lD6faSG*dEAD% z7S__2>|ww|EqKEPhz%Hd%hE8)OUDUi6MX#cRL-I~9^ZY!@e^WK9+mhIw8rgsvubtP z-;6aJ_-Dbv@e-MfABXl=?bpWFE@4p6HAs)(nCmKdxtDDGljAve zV;1P~&44k7l(H2U82%1KQG?;?Cg2Ww_~2a)$ws2WwOQ3IO2r9bQOpuS?wk?zeOzH> z#6bO?>cea3!0X+Pj5+~4-T}}I&+3lok9nfu6RRqqXEh&4f1gD)Z`NBL^*}mW(99}{ zUTAkJ2^H7JEhs1(^O>29Ay=n#tj$1VS3B=SNO4k>MP*n1tQ)WpP}sS+oblYYU3gG0Hd>sg5V;s zEsebpZRDaUsaTIF0Wta9_tk-P@B$$~*zQZ;UyuR#c#Oeu4JmE#zwXcV+FdXze~3dM z!NsL(IpnP;SB6dh2j?W!CWyWsu1Zi5f)zMbebNIJLAB@%KWDW%gF`E9Qs+N7YAZDe zE#B{pW+{(0Jb?wL%BvcQ4L%y;F68UEbvX-{? zWX4^51BBdymfTk*=ZZ zGg41PT_x*lE!`?j*65)TP(%)^jIv~0J)yxcWNQu()(VLl# z`z3nml9~icI+}t@?%8J0;7M;ibx`Kkb0k1`tYVxaDF94nydN(9J52V&RX9t2xd6)@ zy8tK6=Jgwm$u3PL-8_t$h1ucTCki&_cpS_hI6oxP76%n*2FjTsCgaS^`{|R7l~1Nn z=ELt1V|yDCjUw-Tbbtut!yzMb=}D@{6Oa~(3%EM=L=stFBSTJ>_wRv@U0qyiNpbr- z&ZdV+;cOvzO{K+l^XSzk?06D0&&vBG=JUTB^dwtE#aBRfsq}5@5l!jXbbk4I(#0@x zN59yQsg+oe$jl@rin`mGJ&^%-M9tC5gyHMweB~4iMEx?C6=oT2Xx-};m*xTa z4K)l+OAc_A?^6T(<9RMj5G5L#@((Psw{_IOl?>Dr4<5ew`nGl}Krw;(RI-Ondr=^0 zOKM+Sm97wkkyq)%J)f6Q%qe7mto!;uiS;z;4==tH;&nsD9sj=m>cT+@hj23ptXZ}NSqR#M*AgMO&ZpyzX8p|le^nmAV`Kd0{NyqnQ}6o z@=5e!Y{%0m_JexIZCvRvA)#e(j-l$ibP7>Io0%lE@Qz81?eld*1FoZ{YVm6Ab>ePE zJ%{%;-!K zJ6bdS#Q}Z}k(l8~>^U>Tp1MXs$Ns0}4^YaMeI6`rOB(gN(zOwe*b2xVRRFfvC`ObT}VkU&>J+I8&il2{bKe^xPzbl&l$y!&1 zqoh~Ik_K#-7JH8krn(w8%@k`h-`oFvr|YdSTk1d#G7y%;8B~;R78EK8PeL74t3`qa zaYusDt+1u_;{${9(!bL5xjOX;B}^)Vc4BsNw=gOX!lVVDs8F)UY4o%FuAS(x8vxa? zS8TNIW_-z|WsuwwmA$0qjgs6!DjzPIWtf9Qj&)d0gi^LTvA@m==yh6Kl@^A+<$ISA zqseSLFC%%*tGy;v#3eqZH#Ntt+FUCf|AK1phN#GO9%`rX6PLH#*C%7-*Rwzv@eu`e zeJsfFchbk<1eegRPuIm0kgRkC$ybG}w44pTV8ftO=1uLdb)bhI7Q8(>_UKGlv-p|_ zZpzCYH(ZiK(CMfyyUag7vZ;;Sy>15bT*Uh6Y)FL zE0-%;Yd`tCx0k5seEvo<-H%eOe~$=J_;3ojtm`R8EjzFtcQ^>y&r0`OF?U6?KlyyP z)nQBRI*s=mGH%rDeH1sfi^h{sSK#m_I4ITxisqSFzc|CiKH62C&5_V|m{$IClnYO} zhiEjsf!ab?MxC){_P1rRqOpw_?;!;`fA-LLp4;XRbUC)93fhFXoRGPe<~N!?gT;<6 zam+P6R0fbI0yFjg3V67;Du27^1@_m=(!@)ujv#XX_yPF0yoz)z>F^ei>nKZ(hN(D&WMJF*|%1P*9h;?SMMgU622n6jM&8pN!-k+F5gIK7i~ZU zfL&FsUD{gHP>M<)csgc$-Fp=V!fnI0_|@v7_>+yctui3u&{N+Ovz2Kj@A=7ElbbpV zj;}?2uf1Jwb=<93sHJOIAqC`RPeIl0g}AIOne!Xv%oi5Ww-Ei2<)7&=(^jrjv^C-> zAUn___C5p(-`Vq8yl9+vFN~Az;$UMwZAn}EJzW*N)9Zz`NpCWxM0Q0Pa|Fr?gR_QW zDJ=KwtJ1bJ1+QQY_1ml!#Q}hyyjT)WW4(v6u-(qDE!toU?`HywjYszG*TarIlXFhP zOhd91BbwdO$gw9yqF(s*?c1)qpRq5;nB(VUQel=IK8pKt|11g2vJ&h*VfUQT<7jsX zupPA@r7GAu1p&(Kw#PERPwL&YtgLM|q#e*wif*DMw$`2tKIB%#(YLgDl4wO9v~Mmx zyJSN{a*Qz@6q2C1*gtR#beJz2ZvTFth%0Lk({Y#jacyS9_mE=z^9ypAt3=oSz!yic zyIpDVbJDR3wV7lJ9kz_!^g537C=i0tWb@}tLaEB;`)K%SKIc)>1zGmr1g@ZXqc?Lv z5%GGls^VZGzDWK-uLkH%UXN3nYg)c-P=ogNz1&h-J$L|^G$o-FSvP=fCf}a$=v>?E zv&%w^c&v=3`pKu-q(!qD9>O@#|~Ibh58A?5Y}(rr&;t2lHl z?k7L>eqv>#Ntc9bS)e+Ox)RwBIgj)&v05MYtMRIO|2^l!k)a>L3TbE9$fe_rA1i}% z{f?ytSGDZB803ChA60LKV-IWy8=b7(w0jAQkF}0G`TQC$SNu%hlLXVaPgSF=%rgOZ z^ZDLUOg`~5>FrfmP>8vkH}g!=@(~nNc$dDNev~4D*34(YnkAuF;b2LP94rqaz=-e3 zZCxY*X&CKpeN;C4h$hB?d*S}?xLP#~ZA&eCAYMb-OuqgQgB!YSX zG$ME)$ETd3yu|#*TLxyvPxramD6%lSxV*AiqY<8s+EcWSyp-Veq94DtlKCDbW6PlM z2y64U&Mj-1v#_vxlw$5ToD( zkJz_F zKYr%dMjRp(a1k+mAO#-~rSZ~s>8{*rVLBM0x1CQy*@yd@$>;+WI=Z#_L*;NbbFBUE z@)qzr{$rY9;OY)u870miO`BTE22-y-r2}T@i6r$PXFHssh>K$#VKf)VAMMqvrY%T+ z1mdOOOIr3q1`0K>G!-ek)H`s)R?N&c{6l(V8X1SV(W27BMDrruv05^9uPI?$nnjfd z869hAzcbw;E%G2XeTHhz&DiU)tQP+u@zM)X;uLO(f@$qLHpopI?KQ%S+xP z3AvH0l+ok?)C+c>8~VogIky=Ge9mx*;x&~Okktk?^93}H1(jI&XB!dmX=8#hyted3 z+T?(+{9$({(H%TNL#zi7LBUGKj0+ebA&ssKw5_h+6af=EMLFDWfQpv((h$sPSmbuu z;HuI!$|jPWJQa72cHYQ=r?utvswcU62BmISa9f1&8sboDz5Z5?ZqaM~r7KauH`DeL zf1OhwMiG-aaw0pd$fPu}kjLntY@{%6D3d4+DOYD2=x1@`r;75~UgYw-@+GXq@9Fhg zE4-Y3t14UO_NFeyb7r==@8MSEWsc1 z9kil>g7h7hm%Rh&R|eW=pYH-5AzXa z^G=hMUA6pU%!kvWjmq`qGi`yNTYif-*JN$1_Id)o^#1JHs5q6mQA^pE@!Yh74TnZs zr!%IFp7k{NlMjA$OjO%%ka&sZH0u6?lWipBx$@fAQ#0^tSFPhjV9dVyWc}{!m}jF? zr%9FlwwP&+__I|Txb~`T%4!UzvNVnD_qI#v8P)^OmNQm8Jk~Z}B)m=L&kCqEC@(P` zG=62#_2KjT3e@&mc{@r~M0T6FtNUsGEAPC)}z4c=?)&CwY-V;qw9U}bIXyR-%E z`>yoddG{sfW$%nX-l+kF&5zF&7z-VGD;bNqY37mWA)Fa?=k_xJy){;QWv)cc4@|UY zE$nycZr|n;$gIBd6OYgD!&TzwTS{3;PMx!~0=5t1PDPx>WL=dHr=|8al%nF0pj7Az zZI96F(uHbT!%(&U&X9Rq6p6Ss3tHvo`83T@sOdG7a3pHe;89Q>iA~3~Kac__owOI9 zPJ*IXp+{nceMXEncS`T$3$XpQ%?w#CqIalcI>N#BsB=LKLYpW?%2?aZ;;w5U2@T~8 z-5pu_U1usO7mQ6y85=^3DsJVbhU8N{r?fTpFXSaAHKn!%V<2S56kiVZAAan)XDCuH zGb9)E<65xNV)d451LAmj>FhOOu|Kkyy`#qmYfuKIF#UDEb`dpDe$>(|1p@UyiHjH25xteJ%zE1_= zb`pEyu(MG)Uf;m`H3tp3-M*=DeC!2wV^Y#h+=7R#5$w7O4|9Sv2@g@kK#aSyy<=y= z)$ohK89?g`R4M>toh3ZR^7ceF#NeViv0Z}Si;zc`^@%izued}7(wnpGGlt~*2;E?6 z3aXIKJ{Dl0 z)FUo+`W z|D1`JhVA@KW6*;5uG4O(Xl_hOhN~oEwOvS0vKK=DJGFH32{50>^IrriTum>Lz_q0B z9bzIRo!@Sk_Ci_MPjOWoGX3)$COLg$DlQzz8&;)hC|TbB-k90&kMDUk$dQ%n5zZF+ zx{gEtjl77Ju^=-MSDSx70c^vh2ULioGOnxAhd-bFS{gSO^)goa9$PG`2!tR(u7W%+lih~s<=gEx_=5Stw;Z|h&1&JPf}Uofi07En zrCxh?bQT_m;_ui{`YTmU*=4JX_LRrRRM)Rn{a{*E_*U^TV35ZB82F!j;w7|PkcgEQ z!!@u?%E-(2CQ2irDon3XX3Vn(TX4Hvt}>VEb_tTvXd=~1O~Bm|lQz;|w%^TCS51&j zKpzv>s=Y4t-POFZ{t~B6q-8mriM1dy3zstXcFZySGnORF)tiJdhs4Uo@qg8H?(s~2 ze;i+K%P@qwY$&(n5^{~HD7VU88j{NxTdpZBNombwhI}Kp6mqN3+(N#&%&f0QNQHzU z5&9w(3@$kf7|880Z}gcA;j{ZA({6XN&j=^%ogK z+R=tXa`QRWh8|4s$L0c3ac1s-O9*o6?wq2){XFJ?mCp|>)1U0{tNnXZGmT0MZdc@t zH0id3Eb8*bRH)Gm{34(IH_yTqAT2oT&x z%7yUkI~Yt{)ZkNLEiHeO>tibZ$JAqkQ&4<< z(~XPcENg{bS54|;{rtP<+G>kxDBn4!w2nM z84d~3JeAo~OHa-UV$aO>rS8xy2?Yk%-Cwsyw@s1`d^vQ27JJFes{{knnNL=bWWP6s zfe<}rQb(eVHXgu`e>SK%-7d4YJoR91?oA!$6xpjd%iYi8(dQu#a!?^_>;bT}i1cJG z*AJ|~RoUKmDK>(MV&**w^ekrf`MnnQv@iSmt=J{?$zR5mfFk~&z)}1;{K_+^EOUQfe`#{Fa(zvRqn2-2#MfJ-eXj2)qCE72X?QVKO{0=mGhFR;hTlip7 z#<#|B&t&g}S^E!3At%_7aMARPuwWr)BT4&Ts^Hu(WI~h+>e4U}FFW;yDxN4-vHs`O z_FJ#Auk84_`i;kRQo|L|RPVxf7r#H5oAY@8AIhtzZdg0|F_=C4@S}3zJ>G*=Rb9#L zce2*`0F_5+rOR#2l@Ob@t7IbOznFQ_G~)=$KEuS}{xGbbp=JUrxZWcB>8>8Bf9G*?y7%;d(OU z>@Y*FuZ-SMIq=CFiV%_*1VtKn*E?r%n7jIJ{n=+4Ct4@kc#Pl286(63yon&#-W`dk z5mK;k0y9_a&bLV&vZI?Q+wGD|LZV37^dhAl=g&!}@JXg_EHN~Xtz{Msi|ekRq1n|c zIj>&M0oT1X#;EhP_SwOqN5js!PK<`xq|GREbJLCX;}F^(eNq36*l#*nJsnwyiwEfE zE}C$%)Ws)gAy^>F^(1{i*5zft9&XhgH1u5QODgN~0?=h9YTjWNkA;VM-HQ^{2z9J} zI~4a90WZH<6vyq4WrkSO<$Kc|pNtitmTgv$r@w#u1?m_egiA;r5Ylv=n2z-SD2^^l z!=7Y!&WC@FplTlvX#puDX7`#+Zt+lm8$-$Scl8NGuxfDSpYiwgRP za2tnOCE7z@s#Ay3k;lvwW`L}OYr{1;B`)P}ZOx1jr~St{u~%v2E7s4djDD!U&F{I& za{`f$iHG@gW>b;(Cq22L;q+zPz*;Nc3YI+ei+}Ey;Kshbv>|c>_nuwaAXo480Lb-3 zF4ujr&DYOhHjKA67wJu@hrDdID>n*C0yOTBCtAcJ+QX1X8rnHcFN5b-%{4;v+|KI9 z>`qY!9?Es_9?*es`x<4_T^g~PjLN(SKb739{)AWG33r2RZ_M>1K0{$HtN!Abzkj&c z^Z-)#*^%wsrsWF=XV-l9wS!g(pU<;~iNZ$MVI$J55$oby3s*J{P#6cfkJ&^b{aJc_ z>E91`nKV^^I_8J%y#dV{3ZAbANLByfT+PTr{imk}2E0uFz*sFAX?6BOmP1~t&>Jp| zQx70h8o|ndbmJ&U?#kCvQ>>4Rfq|Cjc`;cP_(qTUpQqg9IVVEFxR07mlW`|29LO@| zi=0+YM^$uh1Qtxyd@7r0YgKZH$rmYt?tgpjwXk0HncYiez19V%?Y{z>MfrrD?P&@W z8oJkFyJj_=^N|6bZR>SeS@LpYv<^E?`3clfSJ0ey1UU39f}MLjS*+4+_(K3?Wm}R zm?>+l=Ps`SANe2TtEW+>E=tJD%>wpaq9cKTkz_72`gyl${^nN zB!Z4=n08Km(q<_MUp48|r}oYlT4U4^=&wwg z{^^YJ9bbmC^TJMyccWY@eltaP+@zW|1^Y5D^SH^KLL4$>CYRsZ? zpzr9NCo*RuumOUC8*35cD*qU!ro#LFGHASN5*?6Jx;CC~feLJ>4|$flw^ZPe)AArO z(pOa!;UnInsBW9Inva&8ux;J0h`9ceziQ8KHWN=C?}~RQtRk=`_#SG^n2KS0D;`dr zlSn;D#!fpPb676x<~W3u7A`+u#$HRap#b`hOZnJ&H6!mFp=*E!vS!2 zrfI(FrlDq_fym7DV1Oe>5@PS_d%mAxCTH&Pz3e(U9eECr;Z!-spfgiUG&Jg0@zeu1 z*ed5~*%!;AZ-!{C(@-Z(r=Dtt_W1p1=J`4D%P<|84T^Lx6{pzcxn0kn{v=oja{2- zf7qmS7{A7Er+IuRmnNS!?TS5$KM5t4E_BM8E6_%namhGmL`S;Eh*C30i;rmO>)cZ;Sa``zx{dcZ3HXU5! zC0xxc>t3P0v7Y-b^heSuxPHI?zK}ueP>lF^Nt~}|O7~rGYj#=b7exldd^n6{=JJ}Z zf{b&8>j_8M`#}CHKnC68cI|v=>U15NcOF(!B2$z~!fnJiRl~p2b5wH)g_FTsV$5LH?dx zDvRCM&L{zqq~lf-AU+0-IRoJZZOwJww2!x1i>Rf_031k+$Z|D{>fOHC7Flf;i|{s_ z04PeV*<3R)c76ldDtTH3@vf5&*)mn70&ME-IQe3!-ovGE9SXawK3g>LX~fPVh0?hFJG6oZB00M4k{dmrtuA&kG91N|Ec1wG zb}4;ib{p8Xcev}r_8h!>w3iaZ^DJ%Pw~5Ad@=`013)@#31hb<&vtg);Dpqk>dW@cG z_fOk3o4VbJT^#O67pLQ-QgR*OOMXASI=p@OI`GMStPTNBt#SaI98)P{Bk?#cMY5?|IDaQc25K78xE<_{isY z@nLGrg*_T7{3}l`&<%|EBshI11Y~PhALcsy#~d%Fl?j1frZl8;6ReKFlb>C|16mtf zWU(GgdlK6CZnDLww4sQ5JhwAQzlz%yu5wSt2YKam_>abU!V@G=VgczX8e%$G?)tJH z;-ucB3MS4g<|kxiFb77QjsAm#tN1^WA-d^nm1kdC5Izz$R7s)+ImjN6w-M;e)8EOW zz+rxp%`0d#Yu|sZYSho!e@0@HJ3FVUbFKrnJ?e4*VSgagkV{bTia? z7H123n`+rJjZ2g5lkfL??4w7-$G)X9qdx;pP@peB_RQH*RxL?`3g6Rnz0Tos{E4J& zYp0PiAThA4{x-d>=G+vtUNoF`EHF(K9LPA#*MqFc@~^zBBecjSD|*XSu%~Dx-?ytn zS07dbVxDFPNVGD_%irzRFdKk)L*ug02fS?YyNgmu?@EVN$wi-7WY#BHVAi;huKdk4 zCWwoB>sWvYU|PlyNU>hS&J4*}^(J``VDbNw*N!Du+im`=c_ajMNt{mo!P5>>{uJFO zMuw`0Fq=4KnKUW^4?LY=GE>1H4h;P13FDzz;9i&YU5@F`9--`EqG(8*Cl$X(F&Wdx zYMXOi*wx;*JP80Rh7X5b;3st)YagQTc!HDuy%=5zU4$?`JL@CuH`{Unq;emYmmp}z zJ+zCu3UDe5-uK{cJ+VZ3O*G&vUD~l8=1w26VwO>XC-k=y7*J2jio-f;whV;#rd-BO zRrtJj{8c`6X}WWRuj6==UP;ICVfqg~Ue{xTu@}4^Ju*Du|aGnGb z3k7~4tZTn#{?uVwpK-$MY1Ru6v6Ho}3Z{8rQ3_M*|K7yC{i!4%jL=@Rg$yd9$B&VOc56^$+*pg}J{S4aQ+ z>tjM4^B|7aTIlKxrIu%}XI+jh<(fQ0$>7y~;f?&`u-q<2!gYL#l09uwc&j+%v2)1G z``m8^yAy*8??Z*Y)ZJ<`IC|h43KOy;GRNT$-6OQ0`v30!yMj!uPSg=z{^6WiX!o@UtmgmFz@O^O z=l7YylbygglluHn3xPPSpFvJVab?AeV19MSYIpac?!*oBBccML28fBUB7;2caGXmU zs*tTIk)UhXZ1U8^V(;WtkRxZRnfzqGrgVZXh+Kdpc=bQDbD8Z^XWWfN2V1m7A$;%T zcEG$?6j`YMdMzjqW;X0$xb%@Pr)muitoQC~t9iQq+#O_gm{|%{5e!i#!n(Y5p|K`v z|L?5^BE}=Gr+_$+&YxD1859ksA6qn>mq}_1k{vtlc8c2gCWYqsYwyOv`Um8J%B0u`N0ZLUU$IW405NO)%0u zDjeQ>_$L)amN<=fZtzlg*BT;Qj)3p)d{GBtOqeOX5xy@-TaaeV*l!bE;9!Q!w#P00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPvpp=YXi~XlBA-Tt;PP zGA7OuG$PS)i2;I&BM?Ota6?c8MZ+`=&DwO+-7mlY>w0Zdu@7$_Yt1l5B9Rxw^qN1W>h)?5r2_dj$o7ClbTAu%0 zP+wo4Ow(o^aV5W()z#H)Yu&na9eEWLS<3J2ZQHhGC{^o9OG~$zzaj|CApj7f_1?XE z%Sa9)3b&h-z4ImF3&#SKHvUcltPO4e!W-z8ch2o}Z|QP0Dkxp^)#`Oo6Ut7kCm zPU88Lc?t=C2NnOOISA0A1THTx@6@3~hg0F|e}KbBG1)#+$GH$POj@H z`i3SNpNX-8Olx!)GvvaEPW|1~d7ZEjmAY}HPI@WvdI(iT`V|QDzBve>xxoyhuo*swx|I=lB6(eSbP{nZ zU#)v}W9JQ_pC-&IDJgl8a{Enzq1go1yW0TB0A27igqrJjV!(2*qmkuV=_f0^)x`5OXh zH1KsMYJDtf{tR$4jO?`SV2Fgj3ZZ{&Rd>C~6LKOj9d}?I`X}Nkgd@U;YoQ9lE+@<( z{WRQoNIC%yG{|zt0F}{pG2v@uok?E1FzL3x>j+O0uISvk^H!4wWKCd6Ee6zVIv?db z8x*u10kobz%fsOX&)e6XAVQoP+3_y7~K6#_6$POK9!%sF?luEEVo1Cn{&~Iu>{uo zfl8hRab+R53fTfwVB*hYZJFJrOPB5DFf?%X*7JpTyXjv=)5mO-M#J*ev+k*>|A zy+{JnP*2OGi`Whc$ar7522s$R6&|=$3r+Z8%Yi#I_QL2 zegVn-VzQ83XRT!{sU61}yT}}d76piW1kt15d^ALDJlX{6QP)4kc>UK*ZKM&H#!6Ak z&(hc#LHfzg`|MjUW5Hh@*4Xy#+xwYj0PBlFCCMGRtTXg0uTmG&LcsDPQN= zZr$1wLFkX5Xq(hVL_#?B@@z5I^v7joWuJu9I|}??Ouc*T5oK?LZ7%gkdi2->u7I&f!BBujo(K+(Y2E8e)e?;JDwolX}M1Tnfp6-?AUCqAr|CuGGyEQn6RGo$F%t< zM{kd3A~yX#K-tSP_3Q4>-Ml!k{_kIc@M}yKpmh@*UPL?|Avv4&OS~;)DqT)^6TJR` z_U9mtn~>P<-jlOqq+7IWFH0O~{pLIy_pg8AI zE2n{x?8*MwH>N=Lhj7Wa$j^9Hg)-GPxfG5|B)n50JK0|{`0IS{j0g>b9f|j5AQQQk ztgqU!=w#|Yk>rVt@sc>#rZ^cSSJ^$eo1g5P{E76v)Wm?8l79Ym zkpwQX1L;UXE!e)q=^S%HN>yYF@^~@el8}6ZDhhSIiOY3##zdZjm|ugjra_Q|^L!|6 zE@SN)9@jT@Mg|dw9kjd5WB@TKWBe^hzt~E)ICV=@d8uQ@wUFe1R6mwbpFr5}!cgB~ zSz8fA93XV<+O-mkcn0&G?D!YfhN)eaqIs07^4y!}nHWeC7^GcFbVkTl=zsFDmSL6) zf(XaD4!kqfm$QU^Z$pj!#8b7sX#0Mg0$s!ENzD^=vu*hOzmbdK2BSUCSgW;bfHB?; zE5kS@!BF$G#5iNu95+$#EL7*?CQG1?dv#2zw1^m1rg!h&x+L&~n@2xK$F(bc-x{%> z7{c}C4De2q2cWV(7bZmvTq-N8n+zfboP7uJQu{mA#>pV?=CC>-{3yx|40}esl_qzX zMz|wP<6sb7PX6s7^Q=UoWv{F^IRax$3KR2N6;+039|ke!&uMKU_NNdJ@gGp}aa7D& zlLs)+(Oz4rkWoc?^=g^WRU~)0)-Mb>o^-Ka9){@Z8+ML5d)4F!Xpxzy&@?7zy&Xuq z_tIu*BK;27^=zy1VJ0mv&&hs3OGR#dnEUcX(+d)@j;12i;JL(2kY%?9512f_TE#s= z@)f;nas-Gb!mMzO7vjz`g#5A?XJdShc7CrmSpW>*4NVZct}&O{MD4uxlR^Pg{I|&y z!1-%L)6kq7qRJpVN4R~WEf&YN2}ca}2dd3DYtWxe9-!ke+B)9Pw^r;DlLydV(wpPv zF|ks=9CIm6_2m(IH{t(Hc76Sr`f|@68}=NlcNEV@hSb}SF?B=GjB7U-ck(05h${nu zb!8~krh*6)q3*JY=RrZ7sU^ZJLG)a$8IufJM8|SB1ve4?1v?35N>z4y%lM%k`|lxyf2^*qUP3?Z=o0Jm2=%v;NNf1asMD+&tfeY}Q>OdcSKz`{H)j9JKA6Xbbqhl#XBH8r^~4-uMp z*0lc0XX|StS*0NV5!Cz|zg^Xly}`ClZT~&>`x5VlS>6j92jxeEXgkI0uvsDvqe1`< z72R0If$4 zX<7(a@UNksfXUrN z)W*qLhV$c(ZW%EZ<@$xyM{|^Cvp2>2RE`v%iBI_9s4@scsE3NVjWjI)2$^1TpU3z+ zsC(>)TcFqf=F*1VMi5urneYz5`F$xavy*dZOLb0&ILUbnqU3yc3(NNgka~e_BgrWC zbgRip3y9F`Bi%zRWJS+s(N$8-+EbrBwr=1vIKNjX(hu%M_}*xMV@&}8wR}G9F0fm_ zIv8~ZcE_z@Wp$HA+r6-7No$z}dp^-74?(RV@XaPmu*eu5k}soeXON?Z2h}XA_S)dn z+Ys8$T@MGRsV6LKt^4i6+JWoy+S7yJi5OlRP?3{Tc}VI4w~XUD?ZViuFa-c@+teq- zoo9`zT@ZIN0x~_MY=CR^JB;i1)Co0=i|hc)A;N98QmV4T7%E<6vV*cPN59>w{GZ7I z=<_0o_G`yrlNan4sL}hv%0t9K5o@FDf|pDd;7V*oMa79kGw8D?>s_PmfFQg_KfjOY zXA)9;oM{HYROd4H#o$Yq4LVuh!8nLJJEHuBM8eaCFvb@&?swG)1z+$G)rQVysbiA? zP?Kp6`qVy@c%#VzKyVM#@_$h0F=G!vNNfF`1af~8RS#}IE!Cgb{~qR*%VmXPB;q&- z`>dpg@I1`3+G%eedDC?X-RnnDXP9ycMDA~LfJDPJqfzv`047<)?-9v?6c@hEZk$g;cw^g4zHUt}har*#AgwtLr@teKzep&t z<4oae1vt7JYyPPqB1p2nML|2%XHshe7`dp zAab7zBCn#MJJfiP{x0h?NXD!D*5`xvBcX{@TOg+KP(X(mJlFRx>Xp_rU?bfBK5J_7 z2Bt2%qjoC0b?cVZK3T3s80?#jp_@LkVj8S#^<8g2y3&X>yH;up@=z7)IZ(-3sVl5I zXeX|#N?nM{Vmx{!RPPa82?2EBuhilwl!+|SwPfiGU=dRIUl3M)`kJuz!A)Pv+@;q| zr7DOk`F%CE#e+eP*ObaZF%>2=w^Y0zGnBgf-lBrQ9i2QSHs z@3LzkjE?qd2n%?=9-`{A6_ID|TEl5;JYkyl_%>VjslS^^ExVA>Q-!pRqq93m_Vf&j zRFPFk!%rdfvq5n9CGSE2L_Lw9d)6bI_4y5!#ffOc-0rnyQwS9_Oqb8;sEM=P>0GLJ z5u7!h0sQGOp>qeRdWhN|Jl_B=b>A#yg==}4%aSIi&nLOIo3*bQ>rJn8+(hSBMj0yP z>$Q|+Nc3zZ`k}*w&JMusDd24~xSe2}w@vg&{%0h2X1=)0`5Fh-+<3Mnw`#AL%1ea2 z2gEuf2g9%Q9VjF_uM2#iWw3kUOXUIM=Li>v+A4y-=h)s|i4oeYn<9DL)3KJ_R0i^G zd(x2_blNrnkj1!+{70zs4BYr}(2TFf{58Xd4I4_z%F2!hFB1q~A?x!x3Gmrt1Yz%A$gdQFQ@gM$5cGmC`myX;Pu+4gc@Rs?EgVt8IWy4rs&nK;m z3%XM5pHd}b@bdsdaATZjDpzRsO}j+Hm+me`)!eA#!epaaT;Q|Lgl)u6>(T-0NLN7h z{?H-)g}ZD(E=$(cvvtFiCF(o`AbBOqF-l#c>bB@2G~3NlFV;5)3UigxG`ysYwLOkW zO-@{)fVAx z9cM!L&9wQvzMO{|TaJ2v??77VI;TZb4Mo)spnsh`e>u_cMfyQv?$nrFh+t%e`4~^L zXlGeV+am=hunS1E{?EeIBz1|em;A);@Ka_WE( z*af-akeU&MOZYj;*kj3Dh@36t!$1Y-Pj4LP`y}%??$q_(tX_I+DLCK+c0rqc)c99W zf#;Au9b}x~9+dl1o{a=Gb39q^0GzSu&t{0Kuh8p5El=h9;n0?VgGyi*wB}*N9EA#( zBVaf|?*Ykx(eazE&jdlljS*YF$?qKc4L#b6$g%j}-Luhmn{u|~y8foXWfF{`8u}6e-=p7s{9cK{ i_%`WHE&U!+A>l91J^7N4B%ZDS0000; + +export type UserRoleDTO = Augmented<{ + roleId?: number; + isRoot?: boolean; + roleName: string; +}>; + +/** + * User + */ +export type UserDTO = Augmented<{ + uid: string; + userId: string; + gmtCreate: string; + name: string; + role: string; +}>; diff --git a/projects/manage/src/environments/environment.prod.ts b/projects/manage/src/environments/environment.prod.ts new file mode 100644 index 0000000..744b0c6 --- /dev/null +++ b/projects/manage/src/environments/environment.prod.ts @@ -0,0 +1,6 @@ +export const environment = { + production: true, + clientVersion: "1.0.0", + clientType: "web", + host: "http://47.109.27.8", +}; diff --git a/projects/manage/src/environments/environment.ts b/projects/manage/src/environments/environment.ts new file mode 100644 index 0000000..53a3573 --- /dev/null +++ b/projects/manage/src/environments/environment.ts @@ -0,0 +1,20 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false, + clientVersion: "1.0.0", + clientType: "web", + host: "http://47.109.27.8", + mock: true, +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. diff --git a/projects/manage/src/favicon.ico b/projects/manage/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b25db3a67f8ecbdb34d14305bb17368aaab901ec GIT binary patch literal 2525 zcmbu;c~FyQ9tZF@1mut_AcrD?s00uYP=ux-8C0NzDu)WlVG4)=0z`_DC?Of85H*T} zD2N9%B1Av|IYccckOMr{B1Z&64LMdTBJ#!~ybC!tZg;vf``6C)_ssLx^LxHCpXbm` z>ZE`*E<7?EfWZI&rXPS#3!t~hg@x{kjzhT;4*298$|SfR@%Qy}^&l5!=M!8baS^V# zn6L=fBU=MJy860~`mDcJUqk*{f_}HIA3&G@u7E2X<^~ub zU~mLXCjeaZN~1rrfqxgw0B&fs%-F=#Y`MOn#~Ltz!Qlpma3do_Lw$FNejPAG7}>1# z4_#&(n`Z1*up;1iCCg;pwmSoMaU$NmuVkQcP8+xPGUhe$3rWjVW6Y8)IW&Op~~36$-a#(6r`#MN@#kS`u1`~ zy-Wu<>?BD`@bY1SZBS`DI{S#k39PHRm17^9f`{6f^aECt-IR@Tq>wJYqBRTE0Y(6H zqTXyhsOCBlpi1SioWOU0GLg&=qhtJ}@O|RBsk~XGY4swrEljYA6Vl|hkPD*|} z)JtEAojHPW9{KX^{0b@tVm1Yp1r8Lmr&4n|q2XjvcjRY9Nuva{gjCzvN{0uB#U!o0 z@tHnnuux%$F@Wx8EN#?2eQ_+l7Mu{Gde8MmfKvnb?gLyGt*<&;NjmX)&UWtv+D_VT zDkQL=i~*EG#bKh=O5(%jCw5f)E<1Aiv)!nijZddafO3Ce9?UOtB&}Gist$(*L z{p01tzRn7#&6Gt5cWLoUVTw;K-@jp3^`<4vS+m0}vW@~iuaEsvxE;OJj@;#6Fw7)N2+DZ)?L6a4vG8Zsz z9`fM6A8_D3wB>O;lw0a;X+F@$;r=8{ts-^%zEL!yWfp5m&&HQmCPEy(;K2}se9bAe z^!rauF9M04TZrFm=&RcpsacS2nqw-T%1A=4k=k6-gid2oY2YS-Gm*F70*shLveeGX z-uFtS6Msz*R7Q|9r^_*p8WzWpGKA~s8uQkAaZ9PO4HUSX#Ah&h3w7&9u0JPFn`iBw z-Rdy(NC)JEVCDN8+oy9HEO&B=W9x|W=g5+|jTB1j*V zHO$ljuq{?*>LBIqwwi3k{Bm{7sJGUQ;v|?hp{=8)i)i-4t*Qprlf5C;LOD#`L>7h@_4N@GJhK!8Vl@cu#RAJBT1H+u8};mW8$R#4c= zZ0m@&z3_sCvs}TxFK+tIDgCcvRHN7~$zi!W)B z3{|8KIMGD)9dGLk1UGBVZp*l*#O^gj0y$6071yY!AfBlvvSx}#_YXAwHp{g^yWD(9 z;R@Ep<)Ks_fgyO@or({|%jdg{Df!!|8@2m)q@-W<||^V<8>ct+9)r!Zeq-QnvQn z@dM8}n{~iIjM`IrJ2+`7l_)`IYOx1N<%?Elnnvb-f6!b0=IM|Qu*p|vv_Pr(O! z9U>pJ3;KLYQp(AExHuZIL|2hCS1_j9;TIBb7t1y>eI>MzGM<;K^`<664E^7h(+BZR zL~-Vgg!m&|>%QXlRLSfvab|V1ouo<@Y*{7aT8iIYQDbGV+$Unvu%8~w=vLZMydhWG zR*mt49?R>UDcgDbG0>cxsPVN(mb1^1tD#abW6-7Bc&ZvdKzH z;RHfE$poo0c7TTG=fPv2Q=^N2hEQ;M9(~^;L1Fwp@@Lv3Y|jvXdMa5SA&9nAZ-b(g za22nFI8-fW_gfJ6LABsgJjA>X%_cwv@?`F*B!>#>cY(}QTSdq@o(^EpR(Flj5LuPk z55jw88q{F2X*b0;zw=qZ%-*X3i?u3)Yu>b2b3UB$=pNm)jCEPTdKPpsddY3Y+S9j9 z + + + + + 东方电气 · 转子检测监控管理系统 + + + + + + + +
+
+
+ +
+

+ 加载中... +

+
+
+ + + + + + \ No newline at end of file diff --git a/projects/manage/src/main.ts b/projects/manage/src/main.ts new file mode 100644 index 0000000..4e0605c --- /dev/null +++ b/projects/manage/src/main.ts @@ -0,0 +1,8 @@ +import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; + +import { AppModule } from "./app/app.module"; +import { environment } from "./environments/environment"; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); diff --git a/projects/manage/src/styles.less b/projects/manage/src/styles.less new file mode 100644 index 0000000..5def5d5 --- /dev/null +++ b/projects/manage/src/styles.less @@ -0,0 +1,43 @@ +// Custom Theming for NG-ZORRO +// For more information: https://ng.ant.design/docs/customize-theme/en +@import "../../../node_modules/ng-zorro-antd/ng-zorro-antd.less"; + +// Override less variables to here +// View all variables: https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/components/style/themes/default.less + +// @primary-color: #1890ff; +/* You can add global styles to this file, and also import other style files */ + +@tailwind utilities; + +:root { + --p: @primary-color; + --p-rgb: 24 144 255; + + --border-color: #e8e8e8; +} + +.danger-confirm { + .ant-modal-confirm-content { + color: red; + } +} + +.upload-btn { + position: relative; + + input { + display: block; + height: 100%; + background-color: red; + position: absolute; + inset: 0; + opacity: 0; + font-size: 0; + cursor: pointer; + } +} + +.footer-wapper { + border-top: 1px solid #e8e8e8; +} \ No newline at end of file diff --git a/projects/manage/tsconfig.app.json b/projects/manage/tsconfig.app.json new file mode 100644 index 0000000..e4e0762 --- /dev/null +++ b/projects/manage/tsconfig.app.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/projects/manage/tsconfig.spec.json b/projects/manage/tsconfig.spec.json new file mode 100644 index 0000000..a9c0752 --- /dev/null +++ b/projects/manage/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..4ea57b3 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./projects/**/*.{html,ts}"], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..634614d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,45 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@cdk/*": [ + "./projects/cdk/src/*", + "dist/cdk", + ], + "@client/*": [ + "./projects/client/src/*", + ], + "@manage/*": [ + "./projects/manage/src/*", + ], + }, + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": [ + "ES2022", + "dom" + ] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} \ No newline at end of file