From 772a6af503ba7002f3f0e1344923df22b482e8a1 Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 5 Aug 2024 16:41:22 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20Quellcode=20der=20bestehenden=20Angula?= =?UTF-8?q?r-Anwendung=20f=C3=BCr=20die=20Entwicklung=20hinzugef=C3=BCgt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ClientApp/staff-db-ui/.vscode/launch.json | 22 + ClientApp/staff-db-ui/.vscode/settings.json | 6 + ClientApp/staff-db-ui/angular.json | 302 + ClientApp/staff-db-ui/ngcc.config.js | 9 + ClientApp/staff-db-ui/ngsw-config.json | 30 + ClientApp/staff-db-ui/package-lock.json | 16517 ++++++++++++++++ ClientApp/staff-db-ui/package.json | 70 + .../staff-db-ui/src/app/app-routing.module.ts | 21 + .../staff-db-ui/src/app/app.component.html | 2 + .../staff-db-ui/src/app/app.component.scss | 0 .../staff-db-ui/src/app/app.component.spec.ts | 27 + .../staff-db-ui/src/app/app.component.ts | 58 + ClientApp/staff-db-ui/src/app/app.module.ts | 144 + .../app-account/app-account-routing.module.ts | 19 + .../app-account/app-account.component.html | 22 + .../app-account/app-account.component.scss | 9 + .../app-account/app-account.component.ts | 16 + .../modules/app-account/app-account.module.ts | 29 + .../department/department-data.service.ts | 181 + .../department-content.component.html | 100 + .../department-content.component.scss | 52 + .../department-content.component.spec.ts | 25 + .../department-content.component.ts | 53 + .../department-detail.component.html | 59 + .../department-detail.component.scss | 46 + .../department-detail.component.ts | 109 + .../department-documentart.component.html | 21 + .../department-documentart.component.scss | 19 + .../department-documentart.component.ts | 28 + ...nt-windream-index-popupedit.component.html | 35 + ...nt-windream-index-popupedit.component.scss | 24 + ...ment-windream-index-popupedit.component.ts | 57 + .../department-windream-index.component.html | 115 + .../department-windream-index.component.scss | 23 + ...epartment-windream-index.component.spec.ts | 25 + .../department-windream-index.component.ts | 101 + ...dream-search-item-popupedit.component.html | 34 + ...dream-search-item-popupedit.component.scss | 24 + ...indream-search-item-popupedit.component.ts | 57 + ...rtment-windream-search-item.component.html | 117 + ...rtment-windream-search-item.component.scss | 23 + ...ent-windream-search-item.component.spec.ts | 25 + ...partment-windream-search-item.component.ts | 94 + ...t-windream-search-popupedit.component.html | 37 + ...t-windream-search-popupedit.component.scss | 20 + ...indream-search-popupedit.component.spec.ts | 25 + ...ent-windream-search-popupedit.component.ts | 34 + .../department-windream-search.component.html | 113 + .../department-windream-search.component.scss | 23 + ...partment-windream-search.component.spec.ts | 25 + .../department-windream-search.component.ts | 121 + .../select-department-popup.component.html | 40 + .../select-department-popup.component.scss | 21 + .../select-department-popup.component.ts | 25 + .../department-filter.component.html | 24 + .../department-filter.component.scss | 49 + .../department-filter.component.ts | 61 + .../department-list.component.html | 86 + .../department-list.component.scss | 39 + .../department-list.component.ts | 59 + .../department/department.component.html | 7 + .../department/department.component.scss | 22 + .../department/department.component.ts | 18 + .../modules/department/department.module.ts | 57 + .../department/department.routing.module.ts | 19 + .../src/app/modules/employee/Page1.drawio | 160 + .../modules/employee/employee-data.service.ts | 167 + .../employee-attribute.component.html | 20 + .../employee-attribute.component.scss | 20 + .../employee-attribute.component.ts | 24 + .../employee-content.component.html | 147 + .../employee-content.component.scss | 97 + .../employee-content.component.ts | 33 + .../employee-department.component.html | 94 + .../employee-department.component.scss | 23 + .../employee-department.component.ts | 103 + ...ployee-department.popupedit.component.html | 68 + ...ployee-department.popupedit.component.scss | 28 + ...employee-department.popupedit.component.ts | 30 + .../employee-detail.component.html | 47 + .../employee-detail.component.scss | 48 + .../employee-detail.component.ts | 71 + .../employee-webapp.component.html | 96 + .../employee-webapp.component.scss | 24 + .../employee-webapp.component.ts | 124 + .../employee-webapp.popupedit.component.html | 113 + .../employee-webapp.popupedit.component.scss | 38 + .../employee-webapp.popupedit.component.ts | 70 + .../employee-filter.component.html | 153 + .../employee-filter.component.scss | 77 + .../employee-filter.component.ts | 85 + .../employee-list.component.html | 86 + .../employee-list.component.scss | 38 + .../employee-list/employee-list.component.ts | 80 + .../modules/employee/employee.component.html | 4 + .../modules/employee/employee.component.scss | 22 + .../modules/employee/employee.component.ts | 18 + .../app/modules/employee/employee.module.ts | 59 + .../employee/employee.routing.module.ts | 19 + .../staff-db-ui/src/app/shared/app.consts.ts | 97 + .../staff-db-ui/src/app/shared/app.types.ts | 4 + .../src/app/shared/core/assets/flags/at.svg | 5 + .../src/app/shared/core/assets/flags/au.svg | 24 + .../src/app/shared/core/assets/flags/de.svg | 5 + .../src/app/shared/core/assets/flags/fr.svg | 2 + .../src/app/shared/core/assets/flags/gb.svg | 16 + .../src/app/shared/core/assets/flags/ko.svg | 13 + .../src/app/shared/core/assets/flags/my.svg | 11 + .../src/app/shared/core/assets/flags/us.svg | 26 + .../core/assets/icons/hr-logo_bright.ico | Bin 0 -> 15086 bytes .../core/assets/icons/hr-logo_color.ico | Bin 0 -> 15086 bytes .../core/assets/icons/hr-logo_color3d.ico | Bin 0 -> 15086 bytes .../shared/core/assets/icons/hr-logo_red.ico | Bin 0 -> 15086 bytes .../core/assets/icons/hr-logo_white.ico | Bin 0 -> 3098 bytes .../app/shared/core/assets/json/package.json | 54 + .../shared/core/assets/translate-core/de.json | 110 + .../shared/core/assets/translate-core/en.json | 110 + .../shared/core/assets/translate-core/fr.json | 107 + .../account/account-routing.module.ts | 19 + .../components/account/account.component.html | 86 + .../components/account/account.component.scss | 149 + .../components/account/account.component.ts | 80 + .../core/components/account/account.module.ts | 31 + .../core/components/angular-material-index.ts | 53 + .../components/angular-material.module.ts | 100 + .../components/grid-config/columnconfig.ts | 80 + .../grid-config/columnconfiglist.ts | 138 + .../hensel-date-time-picker.component.html | 46 + .../hensel-date-time-picker.component.scss | 282 + .../hensel-date-time-picker.component.spec.ts | 25 + .../hensel-date-time-picker.component.ts | 292 + .../hensel-date-time-picker.module.ts | 24 + .../hensel-drag-n-drop.component.html | 29 + .../hensel-drag-n-drop.component.scss | 110 + .../hensel-drag-n-drop.component.ts | 111 + .../hensel-drag-n-drop.module.ts | 20 + .../hensel-input/hensel-input.component.html | 77 + .../hensel-input/hensel-input.component.scss | 21 + .../hensel-input/hensel-input.component.ts | 316 + .../core/components/hensel-input/readme.txt | 24 + .../hensel-selection.component.html | 149 + .../hensel-selection.component.scss | 197 + .../hensel-selection.component.ts | 940 + .../components/hensel-selection/readme.txt | 24 + .../hensel-webcam.component.html | 36 + .../hensel-webcam.component.scss | 83 + .../hensel-webcam/hensel-webcam.component.ts | 58 + .../hensel-webcam/hensel-webcam.module.ts | 27 + .../layout/footer/footer.component.html | 75 + .../layout/footer/footer.component.scss | 80 + .../layout/footer/footer.component.ts | 64 + .../core/components/layout/header/favicon.ico | Bin 0 -> 15086 bytes .../layout/header/header.component.html | 33 + .../layout/header/header.component.scss | 58 + .../layout/header/header.component.ts | 44 + .../components/layout/layout.component.html | 14 + .../components/layout/layout.component.scss | 56 + .../components/layout/layout.component.ts | 15 + .../core/components/layout/layout.module.ts | 21 + .../sidenav-list/sidenav-list.component.html | 14 + .../sidenav-list/sidenav-list.component.scss | 23 + .../sidenav-list/sidenav-list.component.ts | 29 + .../login-popup/login-popup.component.html | 69 + .../login-popup/login-popup.component.scss | 94 + .../login-popup/login-popup.component.ts | 70 + .../components/login/login-routing.module.ts | 19 + .../components/login/login.component.html | 32 + .../components/login/login.component.scss | 52 + .../components/login/login.component.spec.ts | 25 + .../core/components/login/login.component.ts | 95 + .../core/components/login/login.module.ts | 25 + .../message-box/message-box.component.html | 23 + .../message-box/message-box.component.scss | 237 + .../message-box/message-box.component.ts | 85 + .../message-box/message-box.module.ts | 21 + .../popup-base/popup-base.component.html | 29 + .../popup-base/popup-base.component.scss | 66 + .../popup-base/popup-base.component.ts | 91 + .../staff-db-ui/src/app/shared/core/consts.ts | 140 + .../shared/core/css/0-base/0_base-dir.scss | 6 + .../core/css/0-base/hr-core-consts.scss | 47 + .../app/shared/core/css/0-base/hr-core.scss | 10 + .../shared/core/css/0-base/hr-spacing.scss | 43 + .../shared/core/css/0-base/hr-typography.scss | 47 + .../css/1-components/1_components_dir.scss | 10 + .../core/css/1-components/hr-additional.scss | 35 + .../core/css/1-components/hr-badge.scss | 192 + .../core/css/1-components/hr-button.scss | 11 + .../core/css/1-components/hr-checkbox.scss | 9 + .../core/css/1-components/hr-grids.scss | 3 + .../core/css/1-components/hr-toolbars.scss | 32 + .../core/css/2-helpers/2_helper-dir.scss | 5 + .../css/2-helpers/hr-functionalities.scss | 53 + .../core/css/3-vendor/3_vendor-dir.scss | 10 + .../3-vendor/external-vendor/indigo-pink.scss | 2918 +++ .../hr-devextreme-styling/3_dx-dir.scss | 10 + .../hr-devextreme-styling/dx-additional.scss | 74 + .../hr-devextreme-styling/dx-button.scss | 84 + .../hr-devextreme-styling/dx-checkbox.scss | 12 + .../hr-devextreme-styling/dx-grid.scss | 179 + .../hr-devextreme-styling/dx-toolbar.scss | 17 + .../hr-devextreme-styling/dx-typography.scss | 11 + .../hr-material-styling/3_mat-dir.scss | 9 + .../hr-material-styling/mat-additional.scss | 149 + .../hr-material-styling/mat-button.scss | 142 + .../hr-material-styling/mat-checkbox.scss | 37 + .../hr-material-styling/mat-toolbar.scss | 21 + .../hr-material-styling/mat-typography.scss | 3 + .../src/app/shared/core/devextreme-license.ts | 1 + .../directives/hensel-decimal.directive.ts | 98 + .../core/directives/hensel-dnd.directive.ts | 88 + .../core/directives/hensel-mask.directive.ts | 35 + .../directives/hensel-stepper-scroller.ts | 21 + .../DHR-2015-1004_DHR_Logo_Querformat_RGB.png | Bin 0 -> 29888 bytes .../app/shared/core/images/hr-logo_bright.ico | Bin 0 -> 15086 bytes .../app/shared/core/images/hr-logo_color.ico | Bin 0 -> 15086 bytes .../shared/core/images/hr-logo_color3d.ico | Bin 0 -> 15086 bytes .../app/shared/core/images/hr-logo_red.ico | Bin 0 -> 15086 bytes .../app/shared/core/images/hr-logo_white.ico | Bin 0 -> 3098 bytes .../src/app/shared/core/images/logo.png | Bin 0 -> 7009 bytes .../src/app/shared/core/injection-tokens.ts | 35 + .../src/app/shared/core/models/coreuser.ts | 75 + .../shared/core/models/generics/baseentity.ts | 209 + .../models/generics/baseentity.wrapper.ts | 895 + .../models/generics/baseentitydetaillist.ts | 265 + .../core/models/generics/baseentityfilter.ts | 129 + .../models/generics/baseentitylist.wrapper.ts | 683 + .../app/shared/core/models/resultsubject.ts | 14 + .../src/app/shared/core/models/serverinfo.ts | 31 + .../core/pipes/hensel-html-sanitizer.pipe.ts | 15 + .../shared/core/services/applogs.service.ts | 164 + .../src/app/shared/core/services/authguard.ts | 63 + .../shared/core/services/authorize.service.ts | 318 + .../src/app/shared/core/services/globals.ts | 249 + .../services/http/http-interceptor.service.ts | 157 + .../core/services/http/repository.service.ts | 93 + .../core/services/in-memory-data.service.ts | 63 + .../localization/hensel-translate.service.ts | 21 + .../services/localization/locale.provider.ts | 23 + .../services/localization/locale.service.ts | 119 + .../translation-loader.provider.ts | 22 + .../core/services/mat-dialog.service.ts | 27 + .../services/notification/uinotification.ts | 46 + .../notification/uinotifier.service.ts | 187 + .../app/shared/core/services/page.service.ts | 245 + .../core/services/pageloading.service.ts | 132 + .../app/shared/core/services/print.service.ts | 25 + .../core/services/serverinfo.service.ts | 176 + .../staff-db-ui/src/app/shared/core/utils.ts | 395 + .../validators/hensel-validator.directive.ts | 75 + .../app/shared/models/basedata/cost-centre.ts | 19 + .../app/shared/models/basedata/department.ts | 39 + .../shared/models/basedata/document-art.ts | 16 + .../models/basedata/employee-attribute.ts | 16 + .../shared/models/basedata/employee-status.ts | 15 + .../src/app/shared/models/basedata/project.ts | 13 + .../src/app/shared/models/basedata/rang.ts | 17 + .../models/basedata/webapp-to-webapprole.ts | 24 + .../src/app/shared/models/basedata/webapp.ts | 19 + .../models/basedata/webappadditionalrole .ts | 17 + .../app/shared/models/basedata/webapprole.ts | 16 + .../models/documentart-to-department.ts | 33 + .../shared/models/employee-to-attribute.ts | 17 + .../shared/models/employee-to-department.ts | 22 + .../app/shared/models/employee-to-webapp.ts | 67 + .../src/app/shared/models/employee.ts | 98 + .../app/shared/models/generic/app.basedata.ts | 16 + .../shared/models/generic/app.baseentity.ts | 6 + .../models/generic/app.baseentityfilter.ts | 4 + .../src/app/shared/models/subsidiary.ts | 19 + .../staff-db-ui/src/app/shared/models/user.ts | 4 + .../app/shared/models/webapp-to-department.ts | 23 + .../models/webapp-to-webappadditionalrole.ts | 17 + ...-index-to-windream-search-to-department.ts | 34 + .../src/app/shared/models/windream-index.ts | 39 + ...h-item-to-windream-search-to-department.ts | 32 + .../app/shared/models/windream-search-item.ts | 37 + .../models/windream-search-to-department.ts | 36 + .../src/app/shared/models/windream-search.ts | 40 + .../shared/services/app.baseentity.wrapper.ts | 5 + .../services/app.baseentitylist.wrapper.ts | 32 + .../app/shared/services/app.data.service.ts | 53 + ClientApp/staff-db-ui/src/assets/.gitkeep | 0 .../src/assets/icons/Master_Icon.xcf | Bin 0 -> 23887 bytes .../assets/icons/develop/dhr-icon-128x128.png | Bin 0 -> 11778 bytes .../assets/icons/develop/dhr-icon-144x144.png | Bin 0 -> 12830 bytes .../assets/icons/develop/dhr-icon-152x152.png | Bin 0 -> 13410 bytes .../icons/develop/dhr-icon-152x152i.png | Bin 0 -> 12868 bytes .../assets/icons/develop/dhr-icon-16x16.png | Bin 0 -> 4814 bytes .../assets/icons/develop/dhr-icon-192x192.png | Bin 0 -> 16035 bytes .../assets/icons/develop/dhr-icon-24x24.png | Bin 0 -> 5188 bytes .../assets/icons/develop/dhr-icon-384x384.png | Bin 0 -> 29615 bytes .../assets/icons/develop/dhr-icon-48x48.png | Bin 0 -> 6612 bytes .../assets/icons/develop/dhr-icon-512x512.png | Bin 0 -> 38893 bytes .../assets/icons/develop/dhr-icon-72x72.png | Bin 0 -> 8353 bytes .../assets/icons/develop/dhr-icon-96x96.png | Bin 0 -> 9790 bytes .../src/assets/icons/main_48x48.png | Bin 0 -> 6589 bytes .../icons/production/dhr-icon-128x128.png | Bin 0 -> 11771 bytes .../icons/production/dhr-icon-144x144.png | Bin 0 -> 12787 bytes .../icons/production/dhr-icon-152x152.png | Bin 0 -> 13389 bytes .../icons/production/dhr-icon-152x152i.png | Bin 0 -> 12805 bytes .../icons/production/dhr-icon-16x16.png | Bin 0 -> 4821 bytes .../icons/production/dhr-icon-192x192.png | Bin 0 -> 15887 bytes .../icons/production/dhr-icon-24x24.png | Bin 0 -> 5189 bytes .../icons/production/dhr-icon-384x384.png | Bin 0 -> 29318 bytes .../icons/production/dhr-icon-48x48.png | Bin 0 -> 6618 bytes .../icons/production/dhr-icon-512x512.png | Bin 0 -> 38542 bytes .../icons/production/dhr-icon-72x72.png | Bin 0 -> 8367 bytes .../icons/production/dhr-icon-96x96.png | Bin 0 -> 9791 bytes .../staff-db-ui/src/assets/js/environment.js | 23 + .../staff-db-ui/src/assets/translate/de.json | 2 + .../staff-db-ui/src/assets/translate/en.json | 2 + .../staff-db-ui/src/assets/translate/fr.json | 2 + ClientApp/staff-db-ui/src/browserslist | 11 + .../src/environments/develop/environment.js | 7 + .../environments/production/environment.js | 7 + ClientApp/staff-db-ui/src/index.html | 39 + ClientApp/staff-db-ui/src/json-typings.d.ts | 4 + ClientApp/staff-db-ui/src/karma.conf.js | 32 + ClientApp/staff-db-ui/src/main.ts | 69 + .../src/manifest/develop/webmanifest.json | 77 + .../src/manifest/production/webmanifest.json | 77 + ClientApp/staff-db-ui/src/polyfills.ts | 69 + ClientApp/staff-db-ui/src/styles.scss | 19 + ClientApp/staff-db-ui/src/test.ts | 14 + ClientApp/staff-db-ui/src/theme.scss | 0 ClientApp/staff-db-ui/src/tsconfig.app.json | 14 + ClientApp/staff-db-ui/src/tsconfig.spec.json | 18 + ClientApp/staff-db-ui/src/tslint.json | 17 + ClientApp/staff-db-ui/src/webmanifest.json | 77 + ClientApp/staff-db-ui/tsconfig.json | 57 + ClientApp/staff-db-ui/tslint.json | 131 + 332 files changed, 38857 insertions(+) create mode 100644 ClientApp/staff-db-ui/.vscode/launch.json create mode 100644 ClientApp/staff-db-ui/.vscode/settings.json create mode 100644 ClientApp/staff-db-ui/angular.json create mode 100644 ClientApp/staff-db-ui/ngcc.config.js create mode 100644 ClientApp/staff-db-ui/ngsw-config.json create mode 100644 ClientApp/staff-db-ui/package-lock.json create mode 100644 ClientApp/staff-db-ui/package.json create mode 100644 ClientApp/staff-db-ui/src/app/app-routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/app.component.html create mode 100644 ClientApp/staff-db-ui/src/app/app.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/app.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/app.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/app.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/app-account/app-account-routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/app-account/app-account.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-data.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/department/department.routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-data.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee.component.html create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/modules/employee/employee.routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/app.consts.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/app.types.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/at.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/au.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/de.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/fr.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/gb.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/ko.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/my.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/flags/us.svg create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_bright.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_color.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_color3d.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_red.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_white.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/json/package.json create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/de.json create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/en.json create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/fr.json create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/account/account-routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/account/account.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/angular-material-index.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/angular-material.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfig.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfiglist.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/readme.txt create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/readme.txt create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/favicon.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login-routing.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.spec.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/login/login.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.module.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.html create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/consts.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/0-base/0_base-dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core-consts.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-spacing.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-typography.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/1_components_dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-additional.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-badge.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-button.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-checkbox.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-grids.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-toolbars.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/2_helper-dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/hr-functionalities.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/3_vendor-dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/external-vendor/indigo-pink.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/3_dx-dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-additional.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-button.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-checkbox.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-grid.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-toolbar.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-typography.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/3_mat-dir.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-additional.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-button.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-checkbox.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-toolbar.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-typography.scss create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/devextreme-license.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-decimal.directive.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-dnd.directive.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-mask.directive.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-stepper-scroller.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/DHR-2015-1004_DHR_Logo_Querformat_RGB.png create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_bright.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_color.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_color3d.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_red.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_white.ico create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/images/logo.png create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/injection-tokens.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/coreuser.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.wrapper.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitydetaillist.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentityfilter.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitylist.wrapper.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/resultsubject.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/models/serverinfo.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/pipes/hensel-html-sanitizer.pipe.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/applogs.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/authguard.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/authorize.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/globals.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/http/http-interceptor.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/http/repository.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/in-memory-data.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/localization/hensel-translate.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.provider.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/localization/translation-loader.provider.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/mat-dialog.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotification.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotifier.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/page.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/pageloading.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/print.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/services/serverinfo.service.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/utils.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/core/validators/hensel-validator.directive.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/cost-centre.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/document-art.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-attribute.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-status.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/project.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/rang.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp-to-webapprole.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/webappadditionalrole .ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/basedata/webapprole.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/documentart-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/employee-to-attribute.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/employee-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/employee-to-webapp.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/employee.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/generic/app.basedata.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentity.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentityfilter.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/subsidiary.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/user.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/webapp-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/webapp-to-webappadditionalrole.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-index-to-windream-search-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-index.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-search-item-to-windream-search-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-search-item.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-search-to-department.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/models/windream-search.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/services/app.baseentity.wrapper.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/services/app.baseentitylist.wrapper.ts create mode 100644 ClientApp/staff-db-ui/src/app/shared/services/app.data.service.ts create mode 100644 ClientApp/staff-db-ui/src/assets/.gitkeep create mode 100644 ClientApp/staff-db-ui/src/assets/icons/Master_Icon.xcf create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-128x128.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-144x144.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152i.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-16x16.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-192x192.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-24x24.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-384x384.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-48x48.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-512x512.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-72x72.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-96x96.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/main_48x48.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-128x128.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-144x144.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-152x152.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-152x152i.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-16x16.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-192x192.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-24x24.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-384x384.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-48x48.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-512x512.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-72x72.png create mode 100644 ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-96x96.png create mode 100644 ClientApp/staff-db-ui/src/assets/js/environment.js create mode 100644 ClientApp/staff-db-ui/src/assets/translate/de.json create mode 100644 ClientApp/staff-db-ui/src/assets/translate/en.json create mode 100644 ClientApp/staff-db-ui/src/assets/translate/fr.json create mode 100644 ClientApp/staff-db-ui/src/browserslist create mode 100644 ClientApp/staff-db-ui/src/environments/develop/environment.js create mode 100644 ClientApp/staff-db-ui/src/environments/production/environment.js create mode 100644 ClientApp/staff-db-ui/src/index.html create mode 100644 ClientApp/staff-db-ui/src/json-typings.d.ts create mode 100644 ClientApp/staff-db-ui/src/karma.conf.js create mode 100644 ClientApp/staff-db-ui/src/main.ts create mode 100644 ClientApp/staff-db-ui/src/manifest/develop/webmanifest.json create mode 100644 ClientApp/staff-db-ui/src/manifest/production/webmanifest.json create mode 100644 ClientApp/staff-db-ui/src/polyfills.ts create mode 100644 ClientApp/staff-db-ui/src/styles.scss create mode 100644 ClientApp/staff-db-ui/src/test.ts create mode 100644 ClientApp/staff-db-ui/src/theme.scss create mode 100644 ClientApp/staff-db-ui/src/tsconfig.app.json create mode 100644 ClientApp/staff-db-ui/src/tsconfig.spec.json create mode 100644 ClientApp/staff-db-ui/src/tslint.json create mode 100644 ClientApp/staff-db-ui/src/webmanifest.json create mode 100644 ClientApp/staff-db-ui/tsconfig.json create mode 100644 ClientApp/staff-db-ui/tslint.json diff --git a/ClientApp/staff-db-ui/.vscode/launch.json b/ClientApp/staff-db-ui/.vscode/launch.json new file mode 100644 index 0000000..1e42eb5 --- /dev/null +++ b/ClientApp/staff-db-ui/.vscode/launch.json @@ -0,0 +1,22 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "name": "ng serve", + "type": "chrome", + "request": "launch", + "url": "http://localhost:4204", + "webRoot": "${workspaceFolder}" + }, + { + "name": "ng test", + "type": "chrome", + "request": "launch", + "preLaunchTask": "npm: test", + "url": "http://localhost:4204/debug.html", + "webRoot": "${workspaceFolder}" + } + ] +} diff --git a/ClientApp/staff-db-ui/.vscode/settings.json b/ClientApp/staff-db-ui/.vscode/settings.json new file mode 100644 index 0000000..95ff930 --- /dev/null +++ b/ClientApp/staff-db-ui/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "angular.enable-strict-mode-prompt": false, + "typescript.tsdk": "node_modules\\typescript\\lib", + "azdoPullRequests.projectName": "StaffDB", + "azdoPullRequests.pullRequestTitle": "commit" +} diff --git a/ClientApp/staff-db-ui/angular.json b/ClientApp/staff-db-ui/angular.json new file mode 100644 index 0000000..f5d8a56 --- /dev/null +++ b/ClientApp/staff-db-ui/angular.json @@ -0,0 +1,302 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "staffdb": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "app", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "aot": true, + "outputPath": "dist", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/assets", + { + "glob": "**/*", + "ignore": [ + "styles/*" + ], + "input": "src/app/shared/core/assets/", + "output": "/assets/" + }, + { + "glob": "dhr-icon-152x152i.png", + "input": "src/assets/icons/develop/", + "output": "/assets/icons/" + }, + "src/webmanifest.json", + { + "glob": "environment.js", + "input": "src/environments/", + "output": "/assets/js/" + }, + { + "glob": "package.json", + "input": "./", + "output": "./assets/json" + } + ], + "styles": [ + "src/styles.scss", + "node_modules/ngx-spinner/animations/ball-clip-rotate.css" + ], + "stylePreprocessorOptions": { + "includePaths": [ + "src/app/shared/core/css/0-base/", + "src/app/shared/core/components/popup-base" + ] + }, + "scripts": [], + "serviceWorker": true, + "ngswConfigPath": "ngsw-config.json" + }, + "configurations": { + "default": { + "progress": true, + "optimization": false, + "outputHashing": "all", + "sourceMap": true, + "namedChunks": true, + "aot": true, + "extractLicenses": false, + "vendorChunk": true, + "buildOptimizer": false, + "budgets": [ + { + "type": "initial", + "maximumWarning": "30mb", + "maximumError": "70mb" + } + ] + }, + "develop": { + "assets": [ + "src/assets", + { + "glob": "**/*", + "ignore": [ + "styles/*" + ], + "input": "src/app/shared/core/assets/", + "output": "/assets/" + }, + { + "glob": "dhr-icon-152x152i.png", + "input": "src/assets/icons/develop/", + "output": "/assets/icons/" + }, + { + "glob": "webmanifest.json", + "input": "src/manifest/develop/", + "output": "/" + }, + { + "glob": "environment.js", + "input": "src/environments/develop/", + "output": "/assets/js/" + }, + { + "glob": "package.json", + "input": "./", + "output": "./assets/json" + } + ], + "progress": true, + "optimization": false, + "outputHashing": "all", + "sourceMap": true, + "namedChunks": true, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": false, + "budgets": [ + { + "type": "initial", + "maximumWarning": "30mb", + "maximumError": "70mb" + } + ] + }, + "production": { + "assets": [ + "src/assets", + { + "glob": "**/*", + "ignore": [ + "styles/*" + ], + "input": "src/app/shared/core/assets/", + "output": "/assets/" + }, + { + "glob": "dhr-icon-152x152i.png", + "input": "src/assets/icons/production/", + "output": "/assets/icons/" + }, + { + "glob": "webmanifest.json", + "input": "src/manifest/production/", + "output": "/" + }, + { + "glob": "environment.js", + "input": "src/environments/production/", + "output": "/assets/js/" + }, + { + "glob": "package.json", + "input": "./", + "output": "./assets/json" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "30mb", + "maximumError": "50mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "10kb" + } + ] + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "liveReload": false, + "port": 4204, + "buildTarget": "staffdb:build" + }, + "configurations": { + "production": { + "buildTarget": "staffdb:build:production" + }, + "develop": { + "buildTarget": "staffdb:build:develop" + }, + "default": { + "buildTarget": "staffdb:build:default" + } + }, + "defaultConfiguration": "default" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "staffdb:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "src/styles.scss", + "node_modules/ngx-spinner/animations/ball-clip-rotate.css" + ], + "scripts": [], + "assets": [ + "src/assets", + { + "glob": "translate-core/*", + "input": "src/app/shared/core/assets/", + "output": "/assets/" + }, + { + "glob": "dhr-icon-152x152i.png", + "input": "src/assets/icons/develop/", + "output": "/assets/icons/" + }, + "src/webmanifest.json", + { + "glob": "environment.js", + "input": "src/environments/", + "output": "/assets/js/" + }, + { + "glob": "package.json", + "input": "./", + "output": "./assets/json" + } + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "staffdb-e2e": { + "root": "e2e/", + "projectType": "application", + "prefix": "", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "staffdb:serve" + }, + "configurations": { + "production": { + "devServerTarget": "staffdb:serve:production" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": "e2e/tsconfig.e2e.json", + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "cli": { + "analytics": false, + "cache": { + "enabled": false + } + } +} diff --git a/ClientApp/staff-db-ui/ngcc.config.js b/ClientApp/staff-db-ui/ngcc.config.js new file mode 100644 index 0000000..fb12d52 --- /dev/null +++ b/ClientApp/staff-db-ui/ngcc.config.js @@ -0,0 +1,9 @@ +module.exports = { + packages: { + 'devextreme-angular': { + ignorableDeepImportMatchers: [ + /devextreme\// + ] + }, + } +}; diff --git a/ClientApp/staff-db-ui/ngsw-config.json b/ClientApp/staff-db-ui/ngsw-config.json new file mode 100644 index 0000000..bbdf93b --- /dev/null +++ b/ClientApp/staff-db-ui/ngsw-config.json @@ -0,0 +1,30 @@ +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": [ + "/assets/icons/hr-logo_color.ico", + "/index.html", + "/webmanifest.json", + "/*.css", + "/*.js" + ] + } + }, + { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": [ + "/assets/**", + "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)" + ] + } + } + ] +} diff --git a/ClientApp/staff-db-ui/package-lock.json b/ClientApp/staff-db-ui/package-lock.json new file mode 100644 index 0000000..581c130 --- /dev/null +++ b/ClientApp/staff-db-ui/package-lock.json @@ -0,0 +1,16517 @@ +{ + "name": "staffdb", + "version": "14.23.33", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "staffdb", + "version": "14.23.33", + "dependencies": { + "@angular/animations": "^17.3.10", + "@angular/cdk": "^16.2.14", + "@angular/common": "^17.3.10", + "@angular/compiler": "^17.3.10", + "@angular/core": "^17.3.10", + "@angular/forms": "^17.3.10", + "@angular/localize": "^17.3.10", + "@angular/material": "^16.2.14", + "@angular/material-moment-adapter": "^16.2.14", + "@angular/platform-browser": "^17.3.10", + "@angular/platform-browser-dynamic": "^17.3.10", + "@angular/pwa": "^17.3.8", + "@angular/router": "^17.3.10", + "@angular/service-worker": "^17.3.10", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@sentry/angular": "^8.4.0", + "angular-in-memory-web-api": "^0.17.0", + "devextreme-angular": "~23.2.6", + "exceljs": "^4.4.0", + "file-saver": "^2.0.5", + "jspdf": "^2.5.1", + "moment": "^2.30.1", + "ngx-clipboard": "^16.0.0", + "ngx-device-detector": "^7.0.0", + "ngx-mask": "^17.0.8", + "ngx-spinner": "^17.0.0", + "ngx-translate-multi-http-loader": "^17.0.0", + "ngx-webcam": "^0.4.1", + "rxjs": "^7.8.1", + "zone.js": "^0.14.6" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.10", + "@angular/language-service": "^17.3.10", + "@types/jasmine": "latest", + "@types/node": "latest", + "codelyzer": "latest", + "jasmine-core": "latest", + "jasmine-spec-reporter": "latest", + "karma": "latest", + "karma-chrome-launcher": "latest", + "karma-coverage": "latest", + "karma-jasmine": "latest", + "karma-jasmine-html-reporter": "latest", + "protractor": "latest", + "ts-node": "latest", + "tslint": "latest", + "typescript": "~5.4.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1703.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1703.8.tgz", + "integrity": "sha512-lKxwG4/QABXZvJpqeSIn/kAwnY6MM9HdHZUV+o5o3UiTi+vO8rZApG4CCaITH3Bxebm7Nam7Xbk8RuukC5rq6g==", + "devOptional": true, + "dependencies": { + "@angular-devkit/core": "17.3.8", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-17.3.8.tgz", + "integrity": "sha512-ixsdXggWaFRP7Jvxd0AMukImnePuGflT9Yy7NJ9/y0cL/k//S/3RnkQv5i411KzN+7D4RIbNkRGGTYeqH24zlg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.3.0", + "@angular-devkit/architect": "0.1703.8", + "@angular-devkit/build-webpack": "0.1703.8", + "@angular-devkit/core": "17.3.8", + "@babel/core": "7.24.0", + "@babel/generator": "7.23.6", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-transform-async-generator-functions": "7.23.9", + "@babel/plugin-transform-async-to-generator": "7.23.3", + "@babel/plugin-transform-runtime": "7.24.0", + "@babel/preset-env": "7.24.0", + "@babel/runtime": "7.24.0", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "17.3.8", + "@vitejs/plugin-basic-ssl": "1.1.0", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.18", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.22", + "css-loader": "6.10.0", + "esbuild-wasm": "0.20.1", + "fast-glob": "3.3.2", + "http-proxy-middleware": "2.0.6", + "https-proxy-agent": "7.0.4", + "inquirer": "9.2.15", + "jsonc-parser": "3.2.1", + "karma-source-map-support": "1.4.0", + "less": "4.2.0", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.8", + "mini-css-extract-plugin": "2.8.1", + "mrmime": "2.0.0", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "4.0.1", + "piscina": "4.4.0", + "postcss": "8.4.35", + "postcss-loader": "8.1.1", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.71.1", + "sass-loader": "14.1.1", + "semver": "7.6.0", + "source-map-loader": "5.0.0", + "source-map-support": "0.5.21", + "terser": "5.29.1", + "tree-kill": "1.2.2", + "tslib": "2.6.2", + "undici": "6.11.1", + "vite": "5.1.7", + "watchpack": "2.4.0", + "webpack": "5.90.3", + "webpack-dev-middleware": "6.1.2", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.10.0", + "webpack-subresource-integrity": "5.1.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.20.1" + }, + "peerDependencies": { + "@angular/compiler-cli": "^17.0.0", + "@angular/localize": "^17.0.0", + "@angular/platform-server": "^17.0.0", + "@angular/service-worker": "^17.0.0", + "@web/test-runner": "^0.18.0", + "browser-sync": "^3.0.2", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "karma": "^6.3.0", + "ng-packagr": "^17.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=5.2 <5.5" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "@web/test-runner": { + "optional": true + }, + "browser-sync": { + "optional": true + }, + "jest": { + "optional": true + }, + "jest-environment-jsdom": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1703.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1703.8.tgz", + "integrity": "sha512-9u6fl8VVOxcLOEMzrUeaybSvi9hSLSRucHnybneYrabsgreDo32tuy/4G8p6YAHQjpWEj9jvF9Um13ertdni5Q==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1703.8", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.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" + } + }, + "node_modules/@angular-devkit/core": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.8.tgz", + "integrity": "sha512-Q8q0voCGudbdCgJ7lXdnyaxKHbNQBARH68zPQV72WT8NWy+Gw/tys870i6L58NWbBaCJEUcIj/kb6KoakSRu+Q==", + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.8.tgz", + "integrity": "sha512-QRVEYpIfgkprNHc916JlPuNbLzOgrm9DZalHasnLUz4P6g7pR21olb8YCyM2OTJjombNhya9ZpckcADU5Qyvlg==", + "dependencies": { + "@angular-devkit/core": "17.3.8", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/animations": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-17.3.10.tgz", + "integrity": "sha512-9fR5snTuG4aM2K54TG/6DXcKXMDKZMovZhjQOxO8l68/oqn6fKrHs8DLzckFs0XGRZ+2OyURH8WggFm1Z828rA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.3.10" + } + }, + "node_modules/@angular/cdk": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-16.2.14.tgz", + "integrity": "sha512-n6PrGdiVeSTEmM/HEiwIyg6YQUUymZrb5afaNLGFRM5YL0Y8OBqd+XhCjb0OfD/AfgCUtedVEPwNqrfW8KzgGw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^16.0.0 || ^17.0.0", + "@angular/core": "^16.0.0 || ^17.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/cli": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.8.tgz", + "integrity": "sha512-X5ZOQ6ZTKVHjhIsfl32ZRqbs+FUoeHLbT7x4fh2Os/8ObDDwrUcCJPqxe2b2RB5E2d0vepYigknHeLE7gwzlNQ==", + "devOptional": true, + "dependencies": { + "@angular-devkit/architect": "0.1703.8", + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "@schematics/angular": "17.3.8", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.2", + "inquirer": "9.2.15", + "jsonc-parser": "3.2.1", + "npm-package-arg": "11.0.1", + "npm-pick-manifest": "9.0.0", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "17.0.6", + "resolve": "1.22.8", + "semver": "7.6.0", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "bin": { + "ng": "bin/ng.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/common": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-17.3.10.tgz", + "integrity": "sha512-6SfD21M3LujymmZsZQIxAsV8Bj5u6He6ImZ+p2rr7FAhFxpVJyKldK8LCmJcFsBD4srpQcxEZ0iDxXvg+0ihAw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.3.10", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-17.3.10.tgz", + "integrity": "sha512-6Ce4siHyF0fCZBDm/cz+blJByGDu1/hbPkQVGmk5HGZTmCUeKkgyjoM6bZr7ssAsyGDRwxBh2SGHO4Ce31vuPA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/core": "17.3.10" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-17.3.10.tgz", + "integrity": "sha512-85SBphqRj3szac3FbeYgEZ+I6WaAlo5h7JX06BdjOLLiaoIwlFhLeAuG+jVekseV+95grFUxIsCMphWHi2e6hQ==", + "dependencies": { + "@babel/core": "7.23.9", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.2.0", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/compiler": "17.3.10", + "typescript": ">=5.2 <5.5" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/core": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-17.3.10.tgz", + "integrity": "sha512-ocEKu7X0yFCOvgJn1uZy76qjhsjKvULrO1k/BuIX0nwhp61DTGYTvCqKmwCBLM8/gvcKYH5vMKMHoQKtiSGE0A==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.14.0" + } + }, + "node_modules/@angular/forms": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-17.3.10.tgz", + "integrity": "sha512-0VZWSXDi2M3DAGJlpdV3lo73Yo/73GPRqmfTOrvIoUIenFg5Dz6oNGzvt/1aRkRn6HKccjix6iMpH91EN65pWA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.3.10", + "@angular/core": "17.3.10", + "@angular/platform-browser": "17.3.10", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/language-service": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-17.3.10.tgz", + "integrity": "sha512-6y0yEnjuKGCnH+YxmZZUC/KEb2ZuB5z7y0AOj4PwOladMWSwHv71x1rz5MokBVBf7ZTeN2w89f9jSWBzSz+fPw==", + "dev": true, + "engines": { + "node": "^18.13.0 || >=20.9.0" + } + }, + "node_modules/@angular/localize": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-17.3.10.tgz", + "integrity": "sha512-B/r+jsYiuxm2llBsOE2rKomB5vSnTnICWcfooBDtDUAfTZNQIoSdPt2SAIbRN/c4GLZsiU53k0+jLl67HdtO2g==", + "dependencies": { + "@babel/core": "7.23.9", + "@types/babel__core": "7.20.5", + "fast-glob": "3.3.2", + "yargs": "^17.2.1" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/compiler": "17.3.10", + "@angular/compiler-cli": "17.3.10" + } + }, + "node_modules/@angular/localize/node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/localize/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@angular/localize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/material": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-16.2.14.tgz", + "integrity": "sha512-zQIxUb23elPfiIvddqkIDYqQhAHa9ZwMblfbv+ug8bxr4D0Dw360jIarxCgMjAcLj7Ccl3GBqZMUnVeM6cjthw==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/auto-init": "15.0.0-canary.bc9ae6c9c.0", + "@material/banner": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/button": "15.0.0-canary.bc9ae6c9c.0", + "@material/card": "15.0.0-canary.bc9ae6c9c.0", + "@material/checkbox": "15.0.0-canary.bc9ae6c9c.0", + "@material/chips": "15.0.0-canary.bc9ae6c9c.0", + "@material/circular-progress": "15.0.0-canary.bc9ae6c9c.0", + "@material/data-table": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dialog": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/drawer": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/fab": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/floating-label": "15.0.0-canary.bc9ae6c9c.0", + "@material/form-field": "15.0.0-canary.bc9ae6c9c.0", + "@material/icon-button": "15.0.0-canary.bc9ae6c9c.0", + "@material/image-list": "15.0.0-canary.bc9ae6c9c.0", + "@material/layout-grid": "15.0.0-canary.bc9ae6c9c.0", + "@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/linear-progress": "15.0.0-canary.bc9ae6c9c.0", + "@material/list": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0", + "@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0", + "@material/radio": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/segmented-button": "15.0.0-canary.bc9ae6c9c.0", + "@material/select": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/slider": "15.0.0-canary.bc9ae6c9c.0", + "@material/snackbar": "15.0.0-canary.bc9ae6c9c.0", + "@material/switch": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-bar": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-scroller": "15.0.0-canary.bc9ae6c9c.0", + "@material/textfield": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tooltip": "15.0.0-canary.bc9ae6c9c.0", + "@material/top-app-bar": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": "^16.0.0 || ^17.0.0", + "@angular/cdk": "16.2.14", + "@angular/common": "^16.0.0 || ^17.0.0", + "@angular/core": "^16.0.0 || ^17.0.0", + "@angular/forms": "^16.0.0 || ^17.0.0", + "@angular/platform-browser": "^16.0.0 || ^17.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/material-moment-adapter": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-16.2.14.tgz", + "integrity": "sha512-LagTDXEq8XOVLy8CVswCbmq7v9bb84+VikEEN09tz831U/7PHjDZ3xRgpKtv7hXrh8cTZOg3UPQw5tZk0hwh3Q==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/core": "^16.0.0 || ^17.0.0", + "@angular/material": "16.2.14", + "moment": "^2.18.1" + } + }, + "node_modules/@angular/platform-browser": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.10.tgz", + "integrity": "sha512-LEhBDOKm2A7nRmZqsafVp6OinRDG1OYZBSqjnT1jZ+f0CRRFIXz6aJ0TMPoU6vq9SLRJ7vrGD9P/eBf2hW00NQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/animations": "17.3.10", + "@angular/common": "17.3.10", + "@angular/core": "17.3.10" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-17.3.10.tgz", + "integrity": "sha512-TW6G4+isdHM2ssQTRTobeAKtR2516pJ25BSwRb+9+Jw/ZAEYOOi+KQyofIFYQccaUjb3+LpjRcaZbtZ9m/Ispg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.3.10", + "@angular/compiler": "17.3.10", + "@angular/core": "17.3.10", + "@angular/platform-browser": "17.3.10" + } + }, + "node_modules/@angular/pwa": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@angular/pwa/-/pwa-17.3.8.tgz", + "integrity": "sha512-NWp88mGEJWUhCaUFDdDMeen0Y81hxZoFNPX9/VaTQ5a2kNUjvQ08iI4ceJB89R4sQSMnmNr30c9Rovo1gS+RTw==", + "dependencies": { + "@angular-devkit/schematics": "17.3.8", + "@schematics/angular": "17.3.8", + "parse5-html-rewriting-stream": "7.0.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/cli": "^17.0.0" + }, + "peerDependenciesMeta": { + "@angular/cli": { + "optional": true + } + } + }, + "node_modules/@angular/router": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-17.3.10.tgz", + "integrity": "sha512-HlZlR9BOLoEKGOSMjmL5EfYL7F7PeDifbFi0dYWNcrG8zFrVKFklB1cuBdJhfPZgYhDEoGms/EToD71tg5wliA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.3.10", + "@angular/core": "17.3.10", + "@angular/platform-browser": "17.3.10", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/service-worker": { + "version": "17.3.10", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-17.3.10.tgz", + "integrity": "sha512-tRoO1WrA4TxLyQK4DFtant3R93DQuGs/DIvhYZ5Tpevaj8h/gL1Uwxzj3GAyZpMSbXvETlHAK8HcwG4IkXkxBg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "bin": { + "ngsw-config": "ngsw-config.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0" + }, + "peerDependencies": { + "@angular/common": "17.3.10", + "@angular/core": "17.3.10" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "dependencies": { + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz", + "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", + "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.0", + "@babel/parser": "^7.24.0", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "dependencies": { + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", + "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", + "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "dependencies": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", + "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", + "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", + "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", + "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", + "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", + "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", + "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", + "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-wrap-function": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", + "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", + "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", + "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", + "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz", + "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", + "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", + "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", + "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", + "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", + "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", + "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", + "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", + "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", + "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", + "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", + "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", + "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/template": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", + "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", + "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", + "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", + "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", + "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", + "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", + "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", + "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", + "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", + "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", + "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", + "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", + "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", + "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", + "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", + "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", + "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", + "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", + "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", + "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", + "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", + "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", + "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", + "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", + "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", + "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", + "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", + "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", + "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", + "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.0.tgz", + "integrity": "sha512-zc0GA5IitLKJrSfXlXmp8KDqLrnGECK7YRfQBmEKg1NmBOQ7e+KuclBEKJgzifQeUYLdNiAw4B4bjyvzWVLiSA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.24.0", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", + "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", + "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", + "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", + "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", + "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", + "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", + "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", + "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", + "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.0.tgz", + "integrity": "sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.24.0", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "dependencies": { + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@devexpress/utils": { + "version": "1.3.16", + "resolved": "https://registry.npmjs.org/@devexpress/utils/-/utils-1.3.16.tgz", + "integrity": "sha512-4Az8FUtvesew89j6N7zmDGfZQyHicvSwVoPZMmxRPvz2u4UiLpI/LDD0zuzLYWsLa8pr+SsJ3JRIKmhlcDAsgA==", + "peer": true, + "dependencies": { + "tslib": "2.0.1" + } + }, + "node_modules/@devexpress/utils/node_modules/tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==", + "peer": true + }, + "node_modules/@devextreme/runtime": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/@devextreme/runtime/-/runtime-3.0.12.tgz", + "integrity": "sha512-a2VCfi82xvB19E2UpaziHDwvbwJESfxm8KUoe1QzQeOFZ3tcgBnWh+oOhf2EIFLCTU34amG7AGVxrSDz+b+ZHg==", + "peer": true, + "dependencies": { + "inferno": "^7.4.6", + "inferno-create-element": "^7.4.6", + "inferno-hydrate": "^7.4.6" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", + "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", + "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", + "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", + "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", + "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", + "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", + "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", + "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", + "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", + "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", + "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", + "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", + "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", + "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", + "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", + "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", + "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", + "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", + "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", + "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", + "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", + "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@fast-csv/format": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@fast-csv/format/-/format-4.3.5.tgz", + "integrity": "sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==", + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isboolean": "^3.0.3", + "lodash.isequal": "^4.5.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0" + } + }, + "node_modules/@fast-csv/format/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" + }, + "node_modules/@fast-csv/parse": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/@fast-csv/parse/-/parse-4.3.6.tgz", + "integrity": "sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==", + "dependencies": { + "@types/node": "^14.0.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.groupby": "^4.6.0", + "lodash.isfunction": "^3.0.9", + "lodash.isnil": "^4.0.0", + "lodash.isundefined": "^3.0.1", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/@fast-csv/parse/node_modules/@types/node": { + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "devOptional": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "devOptional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "devOptional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "devOptional": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "devOptional": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "devOptional": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@ljharb/through": { + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", + "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", + "devOptional": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/@material/animation": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-leRf+BcZTfC/iSigLXnYgcHAGvFVQveoJT5+2PIRdyPI/bIG7hhciRgacHRsCKC0sGya81dDblLgdkjSUemYLw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/auto-init": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-uxzDq7q3c0Bu1pAsMugc1Ik9ftQYQqZY+5e2ybNplT8gTImJhNt4M2mMiMHbMANk2l3UgICmUyRSomgPBWCPIA==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/banner": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-SHeVoidCUFVhXANN6MNWxK9SZoTSgpIP8GZB7kAl52BywLxtV+FirTtLXkg/8RUkxZRyRWl7HvQ0ZFZa7QQAyA==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/button": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/base": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Fc3vGuOf+duGo22HTRP6dHdc+MUe0VqQfWOuKrn/wXKD62m0QQR2TqJd3rRhCumH557T5QUyheW943M3E+IGfg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/button": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-3AQgwrPZCTWHDJvwgKq7Cj+BurQ4wTjDdGL+FEnIGUAjJDskwi1yzx5tW2Wf/NxIi7IoPFyOY3UB41jwMiOrnw==", + "dependencies": { + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/card": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-nPlhiWvbLmooTnBmV5gmzB0eLWSgLKsSRBYAbIBmO76Okgz1y+fQNLag+lpm/TDaHVsn5fmQJH8e0zIg0rYsQA==", + "dependencies": { + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/checkbox": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-4tpNnO1L0IppoMF3oeQn8F17t2n0WHB0D7mdJK9rhrujen/fLbekkIC82APB3fdGtLGg3qeNqDqPsJm1YnmrwA==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/chips": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-fqHKvE5bSWK0bXVkf57MWxZtytGqYBZvvHIOs4JI9HPHEhaJy4CpSw562BEtbm3yFxxALoQknvPW2KYzvADnmA==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/checkbox": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "safevalues": "^0.3.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/circular-progress": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Lxe8BGAxQwCQqrLhrYrIP0Uok10h7aYS3RBXP41ph+5GmwJd5zdyE2t93qm2dyThvU6qKuXw9726Dtq/N+wvZQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/progress-indicator": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/data-table": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-j/7qplT9+sUpfe4pyWhPbl01qJA+OoNAG3VMJruBBR461ZBKyTi7ssKH9yksFGZ8eCEPkOsk/+kDxsiZvRWkeQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/checkbox": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/icon-button": "15.0.0-canary.bc9ae6c9c.0", + "@material/linear-progress": "15.0.0-canary.bc9ae6c9c.0", + "@material/list": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/select": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/density": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Zt3u07fXrBWLW06Tl5fgvjicxNQMkFdawLyNTzZ5TvbXfVkErILLePwwGaw8LNcvzqJP6ABLA8jiR+sKNoJQCg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/dialog": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-o+9a/fmwJ9+gY3Z/uhj/PMVJDq7it1NTWKJn2GwAKdB+fDkT4hb9qEdcxMPyvJJ5ups+XiKZo03+tZrD+38c1w==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/button": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/icon-button": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/dom": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-ly78R7aoCJtundSUu0UROU+5pQD5Piae0Y1MkN6bs0724azeazX1KeXFeaf06JOXnlr5/41ol+fSUPowjoqnOg==", + "dependencies": { + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/drawer": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-PFL4cEFnt7VTxDsuspFVNhsFDYyumjU0VWfj3PWB7XudsEfQ3lo85D3HCEtTTbRsCainGN8bgYNDNafLBqiigw==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/list": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/elevation": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Ro+Pk8jFuap+T0B0shA3xI1hs2b89dNQ2EIPCNjNMp87emHKAzJfhKb7EZGIwv3+gFLlVaLyIVkb94I89KLsyg==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/fab": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-dvU0KWMRglwJEQwmQtFAmJcAjzg9VFF6Aqj78bJYu/DAIGFJ1VTTTSgoXM/XCm1YyQEZ7kZRvxBO37CH54rSDg==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/feature-targeting": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-wkDjVcoVEYYaJvun28IXdln/foLgPD7n9ZC9TY76GErGCwTq+HWpU6wBAAk+ePmpRFDayw4vI4wBlaWGxLtysQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/floating-label": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-bUWPtXzZITOD/2mkvLkEPO1ngDWmb74y0Kgbz6llHLOQBtycyJIpuoQJ1q2Ez0NM/tFLwPphhAgRqmL3YQ/Kzw==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/focus-ring": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-cZHThVose3GvAlJzpJoBI1iqL6d1/Jj9hXrR+r8Mwtb1hBIUEG3hxfsRd4vGREuzROPlf0OgNf/V+YHoSwgR5w==", + "dependencies": { + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0" + } + }, + "node_modules/@material/form-field": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-+JFXy5X44Gue1CbZZAQ6YejnI203lebYwL0i6k0ylDpWHEOdD5xkF2PyHR28r9/65Ebcbwbff6q7kI1SGoT7MA==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/icon-button": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-1a0MHgyIwOs4RzxrVljsqSizGYFlM1zY2AZaLDsgT4G3kzsplTx8HZQ022GpUCjAygW+WLvg4z1qAhQHvsbqlw==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/image-list": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-WKWmiYap2iu4QdqmeUSliLlN4O2Ueqa0OuVAYHn/TCzmQ2xmnhZ1pvDLbs6TplpOmlki7vFfe+aSt5SU9gwfOQ==", + "dependencies": { + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/layout-grid": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-5GqmT6oTZhUGWIb+CLD0ZNyDyTiJsr/rm9oRIi3+vCujACwxFkON9tzBlZohdtFS16nuzUusthN6Jt9UrJcN6Q==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/line-ripple": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-8S30WXEuUdgDdBulzUDlPXD6qMzwCX9SxYb5mGDYLwl199cpSGdXHtGgEcCjokvnpLhdZhcT1Dsxeo1g2Evh5Q==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/linear-progress": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-6EJpjrz6aoH2/gXLg9iMe0yF2C42hpQyZoHpmcgTLKeci85ktDvJIjwup8tnk8ULQyFiGiIrhXw2v2RSsiFjvQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/progress-indicator": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/list": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-TQ1ppqiCMQj/P7bGD4edbIIv4goczZUoiUAaPq/feb1dflvrFMzYqJ7tQRRCyBL8nRhJoI2x99tk8Q2RXvlGUQ==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/menu": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-IlAh61xzrzxXs38QZlt74UYt8J431zGznSzDtB1Fqs6YFNd11QPKoiRXn1J2Qu/lUxbFV7i8NBKMCKtia0n6/Q==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/list": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/menu-surface": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-dMtSPN+olTWE+08M5qe4ea1IZOhVryYqzK0Gyb2u1G75rSArUxCOB5rr6OC/ST3Mq3RS6zGuYo7srZt4534K9Q==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/notched-outline": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-WuurMg44xexkvLTBTnsO0A+qnzFjpcPdvgWBGstBepYozsvSF9zJGdb1x7Zv1MmqbpYh/Ohnuxtb/Y3jOh6irg==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/floating-label": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/progress-indicator": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-uOnsvqw5F2fkeTnTl4MrYzjI7KCLmmLyZaM0cgLNuLsWVlddQE+SGMl28tENx7DUK3HebWq0FxCP8f25LuDD+w==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@material/radio": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-ehzOK+U1IxQN+OQjgD2lsnf1t7t7RAwQzeO6Czkiuid29ookYbQynWuLWk7NW8H8ohl7lnmfqTP1xSNkkL/F0g==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/ripple": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-JfLW+g3GMVDv4cruQ19+HUxpKVdWCldFlIPw1UYezz2h3WTNDy05S3uP2zUdXzZ01C3dkBFviv4nqZ0GCT16MA==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/rtl": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-SkKLNLFp5QtG7/JEFg9R92qq4MzTcZ5As6sWbH7rRg6ahTHoJEuqE+pOb9Vrtbj84k5gtX+vCYPvCILtSlr2uw==", + "dependencies": { + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/segmented-button": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-YDwkCWP9l5mIZJ7pZJZ2hMDxfBlIGVJ+deNzr8O+Z7/xC5LGXbl4R5aPtUVHygvXAXxpf5096ZD+dSXzYzvWlw==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/touch-target": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/select": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-unfOWVf7T0sixVG+3k3RTuATfzqvCF6QAzA6J9rlCh/Tq4HuIBNDdV4z19IVu4zwmgWYxY0iSvqWUvdJJYwakQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/floating-label": "15.0.0-canary.bc9ae6c9c.0", + "@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/list": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu": "15.0.0-canary.bc9ae6c9c.0", + "@material/menu-surface": "15.0.0-canary.bc9ae6c9c.0", + "@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/shape": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Dsvr771ZKC46ODzoixLdGwlLEQLfxfLrtnRojXABoZf5G3o9KtJU+J+5Ld5aa960OAsCzzANuaub4iR88b1guA==", + "dependencies": { + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/slider": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-3AEu+7PwW4DSNLndue47dh2u7ga4hDJRYmuu7wnJCIWJBnLCkp6C92kNc4Rj5iQY2ftJio5aj1gqryluh5tlYg==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/snackbar": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-TwwQSYxfGK6mc03/rdDamycND6o+1p61WNd7ElZv1F1CLxB4ihRjbCoH7Qo+oVDaP8CTpjeclka+24RLhQq0mA==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/button": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/icon-button": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/switch": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-OjUjtT0kRz1ASAsOS+dNzwMwvsjmqy5edK57692qmrP6bL4GblFfBDoiNJ6t0AN4OaKcmL5Hy/xNrTdOZW7Qqw==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "safevalues": "^0.3.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/tab": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-s/L9otAwn/pZwVQZBRQJmPqYeNbjoEbzbjMpDQf/VBG/6dJ+aP03ilIBEkqo8NVnCoChqcdtVCoDNRtbU+yp6w==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/focus-ring": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/tab-bar": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-Xmtq0wJGfu5k+zQeFeNsr4bUKv7L+feCmUp/gsapJ655LQKMXOUQZtSv9ZqWOfrCMy55hoF1CzGFV+oN3tyWWQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-indicator": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab-scroller": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/tab-indicator": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-despCJYi1GrDDq7F2hvLQkObHnSLZPPDxnOzU16zJ6FNYvIdszgfzn2HgAZ6pl5hLOexQ8cla6cAqjTDuaJBhQ==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/tab-scroller": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-QWHG/EWxirj4V9u2IHz+OSY9XCWrnNrPnNgEufxAJVUKV/A8ma1DYeFSQqxhX709R8wKGdycJksg0Flkl7Gq7w==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/tab": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/textfield": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-R3qRex9kCaZIAK8DuxPnVC42R0OaW7AB7fsFknDKeTeVQvRcbnV8E+iWSdqTiGdsi6QQHifX8idUrXw+O45zPw==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/density": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/floating-label": "15.0.0-canary.bc9ae6c9c.0", + "@material/line-ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/notched-outline": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/theme": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-CpUwXGE0dbhxQ45Hu9r9wbJtO/MAlv5ER4tBHA9tp/K+SU+lDgurBE2touFMg5INmdfVNtdumxb0nPPLaNQcUg==", + "dependencies": { + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/tokens": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-nbEuGj05txWz6ZMUanpM47SaAD7soyjKILR+XwDell9Zg3bGhsnexCNXPEz2fD+YgomS+jM5XmIcaJJHg/H93Q==", + "dependencies": { + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0" + } + }, + "node_modules/@material/tooltip": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-UzuXp0b9NuWuYLYpPguxrjbJnCmT/Cco8CkjI/6JajxaeA3o2XEBbQfRMTq8PTafuBjCHTc0b0mQY7rtxUp1Gg==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/button": "15.0.0-canary.bc9ae6c9c.0", + "@material/dom": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/tokens": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "safevalues": "^0.3.4", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/top-app-bar": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-vJWjsvqtdSD5+yQ/9vgoBtBSCvPJ5uF/DVssv8Hdhgs1PYaAcODUi77kdi0+sy/TaWyOsTkQixqmwnFS16zesA==", + "dependencies": { + "@material/animation": "15.0.0-canary.bc9ae6c9c.0", + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/elevation": "15.0.0-canary.bc9ae6c9c.0", + "@material/ripple": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/shape": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "@material/typography": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/touch-target": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-AqYh9fjt+tv4ZE0C6MeYHblS2H+XwLbDl2mtyrK0DOEnCVQk5/l5ImKDfhrUdFWHvS4a5nBM4AA+sa7KaroLoA==", + "dependencies": { + "@material/base": "15.0.0-canary.bc9ae6c9c.0", + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/rtl": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@material/typography": { + "version": "15.0.0-canary.bc9ae6c9c.0", + "resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.bc9ae6c9c.0.tgz", + "integrity": "sha512-CKsG1zyv34AKPNyZC8olER2OdPII64iR2SzQjpqh1UUvmIFiMPk23LvQ1OnC5aCB14pOXzmVgvJt31r9eNdZ6Q==", + "dependencies": { + "@material/feature-targeting": "15.0.0-canary.bc9ae6c9c.0", + "@material/theme": "15.0.0-canary.bc9ae6c9c.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.8.tgz", + "integrity": "sha512-CjSVVa/9fzMpEDQP01SC4colKCbZwj7vUq0H2bivp8jVsmd21x9Fu0gDBH0Y9NdfAIm4eGZvmiZKMII3vIOaYQ==", + "dev": true, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^17.0.0", + "typescript": ">=5.2 <5.5", + "webpack": "^5.54.0" + } + }, + "node_modules/@ngx-translate/core": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-15.0.0.tgz", + "integrity": "sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, + "node_modules/@ngx-translate/http-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz", + "integrity": "sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "@ngx-translate/core": ">=15.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/agent": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", + "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "devOptional": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "devOptional": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", + "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "devOptional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.7.tgz", + "integrity": "sha512-WaOVvto604d5IpdCRV2KjQu8PzkfE96d50CQGKgywXh2GxXmDeUO5EWcBC4V57uFyrNqx83+MewuJh3WTR3xPA==", + "devOptional": true, + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^4.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "devOptional": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "devOptional": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/git/node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "devOptional": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", + "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", + "devOptional": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.1.0.tgz", + "integrity": "sha512-1aL4TuVrLS9sf8quCLerU3H9J4vtCtgu8VauYozrmEyU57i/EdKleCnsQ7vpnABIH6c9mnTxcH5sFkO3BlV8wQ==", + "devOptional": true, + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^4.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "devOptional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/package-json/node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", + "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "devOptional": true, + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "devOptional": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "devOptional": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/redact": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-1.1.0.tgz", + "integrity": "sha512-PfnWuOkQgu7gCbnSsAisaX7hKOdZ4wSAhAzH3/ph5dSGau52kCRrMMGbiSQLwyTZpgldkZ49b0brkOr1AzGBHQ==", + "devOptional": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.4.tgz", + "integrity": "sha512-9ApYM/3+rBt9V80aYg6tZfzj3UWdiYyCt7gJUD1VJKvWF5nwKDSICXbYIQbspFTq6TOpbsEtIC0LArB8d9PFmg==", + "devOptional": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "devOptional": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "devOptional": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@schematics/angular": { + "version": "17.3.8", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.3.8.tgz", + "integrity": "sha512-2g4OmSyE9YGq50Uj7fNI26P/TSAFJ7ZuirwTF2O7Xc4XRQ29/tYIIqhezpNlTb6rlYblcQuMcUZBrMfWJHcqJw==", + "dependencies": { + "@angular-devkit/core": "17.3.8", + "@angular-devkit/schematics": "17.3.8", + "jsonc-parser": "3.2.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.5.0.tgz", + "integrity": "sha512-R2h4JssvmY/mnq3iW49Oxas9BJ8CPR7yP88lCHiCHtwH/gHxemgCtq/NY1ptA0t45Eae+4ILU0ppOsJcDg9VBw==", + "dependencies": { + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.5.0.tgz", + "integrity": "sha512-GTLIfRKx2Ye0pIxhVUSxxwPbQfiSNhXpQMnSrSYHDo1KHLgbgZ4MaX2Qnx+CZN6mXDVVrtk1sqTR83ytFCwRcw==", + "dependencies": { + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.5.0.tgz", + "integrity": "sha512-eluGqUjuSZKqe3dqqBvMkh3HJ9aPxXOT0i3ydUHoV9XWA7oeUfWk6gIqMm7WLTHagOGYp3v4KTOYdzu4QS6OMA==", + "dependencies": { + "@sentry-internal/browser-utils": "8.5.0", + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.5.0.tgz", + "integrity": "sha512-BOwoUjRHQ0OUsUwHiBhXtkvJXe+9LlB9cb8KmhcHdfqajp4L10aN+4OC8UTSbCX832Ph/K6nu5gelK4wAI9NVw==", + "dependencies": { + "@sentry-internal/replay": "8.5.0", + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/angular": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry/angular/-/angular-8.5.0.tgz", + "integrity": "sha512-0a22ON8KwYVfyEfFAxQiX1/8MgT2DZlfQf2RyFSxI+7B6viCAlnTS2Bs+xVxo2vuG1SVq2M1LrPUrRU+be7JMQ==", + "dependencies": { + "@sentry/browser": "8.5.0", + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0", + "tslib": "^2.4.1" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "@angular/common": ">= 14.x <= 18.x", + "@angular/core": ">= 14.x <= 18.x", + "@angular/router": ">= 14.x <= 18.x", + "rxjs": "^6.5.5 || ^7.x" + } + }, + "node_modules/@sentry/browser": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.5.0.tgz", + "integrity": "sha512-rxthVdwkkGqArQLM+/O8y0J4oe/J5MLE7WzzRkzSJWLdt6cJMrrb43sKGQf2IQSg6kf1se+qKmpRly5uEOf8OA==", + "dependencies": { + "@sentry-internal/browser-utils": "8.5.0", + "@sentry-internal/feedback": "8.5.0", + "@sentry-internal/replay": "8.5.0", + "@sentry-internal/replay-canvas": "8.5.0", + "@sentry/core": "8.5.0", + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/core": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.5.0.tgz", + "integrity": "sha512-SO3ddBzGdha+Oflp+IKwBxj+7ds1q69OAT3VsypTd+WUFQdI9DIhR92Bjf+QQZCIzUNOi79VWOh3aOi3f6hMnw==", + "dependencies": { + "@sentry/types": "8.5.0", + "@sentry/utils": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/types": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.5.0.tgz", + "integrity": "sha512-eDgkSmKI4+XL0QZm4H3j/n1RgnrbnjXZmjj+LsfccRZQwbPu9bWlc8q7Y7Ty1gOsoUpX+TecNLp2a8CRID4KHA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.5.0.tgz", + "integrity": "sha512-fdrCzo8SAYiw9JBhkJPqYqJkDXZ/wICzN7+zcXIuzKNhE1hdoFjeKcPnpUI3bKZCG6e3hT1PTYQXhVw7GIZV9w==", + "dependencies": { + "@sentry/types": "8.5.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sigstore/bundle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", + "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", + "devOptional": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", + "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", + "devOptional": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.3.2.tgz", + "integrity": "sha512-c6B0ehIWxMI8wiS/bj6rHMPqeFvngFV7cDU/MY+B16P9Z3Mp9k8L93eYZ7BYzSickzuqAQqAq0V956b3Ju6mLw==", + "devOptional": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", + "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", + "devOptional": true, + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "make-fetch-happen": "^13.0.1", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", + "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", + "devOptional": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.2", + "tuf-js": "^2.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", + "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", + "devOptional": true, + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "dev": true + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "devOptional": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", + "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", + "devOptional": true, + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.1.tgz", + "integrity": "sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.4.tgz", + "integrity": "sha512-px7OMFO/ncXxixDe1zR13V1iycqWae0MxTaw62RpFlksUi5QuNWgQJFkTQjIOvrmutJbI7Fp2Y2N1F6D2R4G6w==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha512-qYi3YV9inU/REEfxwVcGZzbS3KG/Xs90lv0Pr+lDtuVjBPGd1A+eciXzVSaRvLify132BfcvhvEjeVahrUl0Ug==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/raf": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", + "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", + "optional": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/@types/selenium-webdriver": { + "version": "3.0.26", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.26.tgz", + "integrity": "sha512-dyIGFKXfUFiwkMfNGn1+F6b80ZjR3uSYv1j6xVJSDlft5waZ2cwkHW4e7zNzvq7hiEackcgvBpmnXZrI1GltPg==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vitejs/plugin-basic-ssl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", + "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", + "dev": true, + "engines": { + "node": ">=14.6.0" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "devOptional": true + }, + "node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", + "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "devOptional": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "devOptional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/angular-in-memory-web-api": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/angular-in-memory-web-api/-/angular-in-memory-web-api-0.17.0.tgz", + "integrity": "sha512-q1VPfyg8B0dBKjjURitxFnUBqEiR4JyATxgHuAVTLfgcMJwJIBqfEYrejCPRE2GslzqMjf2PdLklxoYs/HDd7Q==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0", + "@angular/core": "^17.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "devOptional": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argparse/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/aria-query": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", + "integrity": "sha512-majUxHgLehQTeSA+hClx+DY09OVUqG3GtezWkF1krgLGNdlDu9l9V8DaqNMWbq4Eddc8wsyDA0hpDUtnYxQEXw==", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7", + "commander": "^2.11.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.18", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.18.tgz", + "integrity": "sha512-1DKbDfsr6KUElM6wg+0zRNkB/Q7WcKYAaK+pzXn+Xqmszm/5Xa9coeNdtP88Vi+dPzZnMjhge8GIV49ZQkDa+g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001591", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", + "dev": true + }, + "node_modules/axobject-query": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "dependencies": { + "ast-types-flow": "0.0.7" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "optional": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/blocking-proxy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz", + "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "blocking-proxy": "built/lib/bin.js" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/browserstack": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.6.1.tgz", + "integrity": "sha512-GxtFjpIaKdbAyzHfFDKixKO8IBT7wR3NjbzrGc78nNs/Ciys9wU3/nBtsqsWv5nDSrdI5tz0peKuzCPuNXNUiw==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + } + }, + "node_modules/browserstack/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/browserstack/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/browserstack/node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.3.tgz", + "integrity": "sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg==", + "devOptional": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "devOptional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "devOptional": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "devOptional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001623", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001623.tgz", + "integrity": "sha512-X/XhAVKlpIxWPpgRTnlgZssJrF0m6YtRA0QDWgsBNT12uZM6LPRydR7ip405Y3t1LamD8cP2TZFEDZFBf5ApcA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/canvg/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "optional": true + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "devOptional": true + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "devOptional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "devOptional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/codelyzer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-6.0.2.tgz", + "integrity": "sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==", + "dev": true, + "dependencies": { + "@angular/compiler": "9.0.0", + "@angular/core": "9.0.0", + "app-root-path": "^3.0.0", + "aria-query": "^3.0.0", + "axobject-query": "2.0.2", + "css-selector-tokenizer": "^0.7.1", + "cssauron": "^1.4.0", + "damerau-levenshtein": "^1.0.4", + "rxjs": "^6.5.3", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.2", + "tslib": "^1.10.0", + "zone.js": "~0.10.3" + }, + "peerDependencies": { + "@angular/compiler": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "@angular/core": ">=2.3.1 <13.0.0 || ^12.0.0-next || ^12.1.0-next || ^12.2.0-next", + "tslint": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/compiler": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.0.0.tgz", + "integrity": "sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==", + "dev": true, + "peerDependencies": { + "tslib": "^1.10.0" + } + }, + "node_modules/codelyzer/node_modules/@angular/core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.0.tgz", + "integrity": "sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==", + "dev": true, + "peerDependencies": { + "rxjs": "^6.5.3", + "tslib": "^1.10.0", + "zone.js": "~0.10.2" + } + }, + "node_modules/codelyzer/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/codelyzer/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/codelyzer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/codelyzer/node_modules/zone.js": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/core-js": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/critters": { + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.22.tgz", + "integrity": "sha512-NU7DEcQZM2Dy8XTKFHxtdnIM/drE312j2T4PCVaSUcS0oBeyT/NImpRw/Ap0zOr/1SE7SgPK9tGPg1WK/sVakw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "postcss-media-query-parser": "^0.2.3" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/critters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "devOptional": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/css-loader": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-selector-tokenizer": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha512-Ht70DcFBh+/ekjVrYS2PlDMdSQEl3OFNmjK6lcn49HptBgilXf/Zwg4uFh9Xn0pX3Q8YOkSjIFOfK2osvdqpBw==", + "dev": true, + "dependencies": { + "through": "X.X.X" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge-ts": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", + "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", + "peer": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "devOptional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha512-Z4fzpbIRjOu7lO5jCETSWoqUDVe0IPOlfugBsF6suen2LKDlVb4QZpKEM9P+buNJ4KI1eN7I083w/pbKUpsrWQ==", + "dev": true, + "dependencies": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha512-HJRTIH2EeH44ka+LWig+EqT2ONSYpVlNfx6pyd592/VF1TbfljJ7elwie7oSwcViLGqOdWocSdu2txwBF9bjmQ==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/devexpress-diagram": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/devexpress-diagram/-/devexpress-diagram-2.2.5.tgz", + "integrity": "sha512-gxcBYNChijcfmsOnWOWPmTGxIPn+eGIf3635PUgpTBL/WPpDVZJsXdEV+eXe92OEX0MopcyxiCSJZN5o3zZ4hQ==", + "peer": true, + "dependencies": { + "@devexpress/utils": "1.3.16", + "es6-object-assign": "^1.1.0" + } + }, + "node_modules/devexpress-gantt": { + "version": "4.1.54", + "resolved": "https://registry.npmjs.org/devexpress-gantt/-/devexpress-gantt-4.1.54.tgz", + "integrity": "sha512-5o5Y/v+mc/ukYGwmRy9UJ2SegKB/XXsa981BsXXT437QGHcwLzT47+NBRhsmQ8yIkp7NvCzKz8nEsF4tYORGFg==", + "peer": true, + "dependencies": { + "@devexpress/utils": "^1.4.3", + "tslib": "2.3.1" + } + }, + "node_modules/devexpress-gantt/node_modules/@devexpress/utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@devexpress/utils/-/utils-1.4.3.tgz", + "integrity": "sha512-UmmIwVRGQ6u6itE/zJ1xNmMuugXo/t1fWBtjROb7mhq2nY4ecDBdnRIqogKWAasGbMbhCxW9+ijkgRaNBVCIzQ==", + "peer": true, + "dependencies": { + "tslib": "2.3.1" + } + }, + "node_modules/devexpress-gantt/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "peer": true + }, + "node_modules/devextreme": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/devextreme/-/devextreme-23.2.6.tgz", + "integrity": "sha512-JZkqvjLdv66feFWH0+23XRLSEKdp/DnW+AXJVTLeUc4ZvGcuZVLkOnusLF0yZ21BTG+xKxkZ4lTaSrw1BeYLDQ==", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.12.1", + "@devextreme/runtime": "3.0.12", + "devexpress-diagram": "2.2.5", + "devexpress-gantt": "4.1.54", + "devextreme-quill": "1.6.4", + "inferno": "^7.4.9", + "inferno-hydrate": "^7.4.9", + "jszip": "^3.10.1", + "rrule": "^2.7.1", + "showdown": "^2.1.0", + "turndown": "~7.1.0" + }, + "bin": { + "devextreme-bundler": "bin/bundler.js", + "devextreme-bundler-init": "bin/bundler-init.js" + } + }, + "node_modules/devextreme-angular": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/devextreme-angular/-/devextreme-angular-23.2.6.tgz", + "integrity": "sha512-v/Q30m7kj3yZ4TEl1QvEWcLJULNuhdwJ16S4LJn7u5kGNxOLSiEP6Tovi1MUNd1p5AZrZyzEwCFb1FWNzQB1Dg==", + "dependencies": { + "@angular-devkit/schematics": "^12.2.18", + "devextreme-schematics": "*", + "inferno-server": "7.4.11", + "tslib": "^2.2.0" + }, + "peerDependencies": { + "@angular/common": ">12.0.0", + "@angular/core": ">12.0.0", + "@angular/forms": ">12.0.0", + "devextreme": "~23.2.6" + } + }, + "node_modules/devextreme-angular/node_modules/@angular-devkit/core": { + "version": "12.2.18", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.18.tgz", + "integrity": "sha512-GDLHGe9HEY5SRS+NrKr14C8aHsRCiBFkBFSSbeohgLgcgSXzZHFoU84nDWrl3KZNP8oqcUSv5lHu6dLcf2fnww==", + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/devextreme-angular/node_modules/@angular-devkit/schematics": { + "version": "12.2.18", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.18.tgz", + "integrity": "sha512-bZ9NS5PgoVfetRC6WeQBHCY5FqPZ9y2TKHUo12sOB2YSL3tgWgh1oXyP8PtX34gasqsLjNULxEQsAQYEsiX/qQ==", + "dependencies": { + "@angular-devkit/core": "12.2.18", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/devextreme-angular/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/devextreme-angular/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/devextreme-angular/node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/devextreme-angular/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/devextreme-angular/node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/devextreme-angular/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/devextreme-quill": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/devextreme-quill/-/devextreme-quill-1.6.4.tgz", + "integrity": "sha512-qs8lt+nn/2vQX1PrImQmCj2B1c8ydD5Hrjn42wWeqa4sVFd/9e2UM+PL979EtKqX0k1M4ncMe25cSbgYz5nNdA==", + "peer": true, + "dependencies": { + "core-js": "^3.34.0", + "eventemitter3": "^4.0.7", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.merge": "^4.6.2", + "parchment": "^2.0.1", + "quill-delta": "^5.0.0" + } + }, + "node_modules/devextreme-schematics": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/devextreme-schematics/-/devextreme-schematics-1.6.9.tgz", + "integrity": "sha512-TGW0yK8ZPUt8KIDruZrbUYM6TyB98+zHs93P0GYC0aepGODDW5OAiBAUCa99Hf4VabA2aopa0W/0MWhFH3P0SA==", + "dependencies": { + "@angular-devkit/core": "^12.2.18", + "@angular-devkit/schematics": "^12.2.18", + "@schematics/angular": "^12.2.18" + } + }, + "node_modules/devextreme-schematics/node_modules/@angular-devkit/core": { + "version": "12.2.18", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.18.tgz", + "integrity": "sha512-GDLHGe9HEY5SRS+NrKr14C8aHsRCiBFkBFSSbeohgLgcgSXzZHFoU84nDWrl3KZNP8oqcUSv5lHu6dLcf2fnww==", + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/devextreme-schematics/node_modules/@angular-devkit/schematics": { + "version": "12.2.18", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.18.tgz", + "integrity": "sha512-bZ9NS5PgoVfetRC6WeQBHCY5FqPZ9y2TKHUo12sOB2YSL3tgWgh1oXyP8PtX34gasqsLjNULxEQsAQYEsiX/qQ==", + "dependencies": { + "@angular-devkit/core": "12.2.18", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/devextreme-schematics/node_modules/@schematics/angular": { + "version": "12.2.18", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.18.tgz", + "integrity": "sha512-niRS9Ly9y8uI0YmTSbo8KpdqCCiZ/ATMZWeS2id5M8JZvfXbngwiqJvojdSol0SWU+n1W4iA+lJBdt4gSKlD5w==", + "dependencies": { + "@angular-devkit/core": "12.2.18", + "@angular-devkit/schematics": "12.2.18", + "jsonc-parser": "3.0.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/devextreme-schematics/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/devextreme-schematics/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/devextreme-schematics/node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" + }, + "node_modules/devextreme-schematics/node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/devextreme-schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/devextreme-schematics/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/devextreme-schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domino": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz", + "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==", + "peer": true + }, + "node_modules/dompurify": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.4.tgz", + "integrity": "sha512-l5NNozANzaLPPe0XaAwvg3uZcHtDBnziX/HjsY1UcDj1MxTK8Dd0Kv096jyPK5HRzs/XM5IMj20dW8Fk+HnbUA==", + "optional": true + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "devOptional": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.783", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", + "integrity": "sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", + "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "devOptional": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "devOptional": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "devOptional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz", + "integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg==", + "dev": true + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "peer": true + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "dev": true, + "dependencies": { + "es6-promise": "^4.0.3" + } + }, + "node_modules/esbuild": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", + "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.1", + "@esbuild/android-arm": "0.20.1", + "@esbuild/android-arm64": "0.20.1", + "@esbuild/android-x64": "0.20.1", + "@esbuild/darwin-arm64": "0.20.1", + "@esbuild/darwin-x64": "0.20.1", + "@esbuild/freebsd-arm64": "0.20.1", + "@esbuild/freebsd-x64": "0.20.1", + "@esbuild/linux-arm": "0.20.1", + "@esbuild/linux-arm64": "0.20.1", + "@esbuild/linux-ia32": "0.20.1", + "@esbuild/linux-loong64": "0.20.1", + "@esbuild/linux-mips64el": "0.20.1", + "@esbuild/linux-ppc64": "0.20.1", + "@esbuild/linux-riscv64": "0.20.1", + "@esbuild/linux-s390x": "0.20.1", + "@esbuild/linux-x64": "0.20.1", + "@esbuild/netbsd-x64": "0.20.1", + "@esbuild/openbsd-x64": "0.20.1", + "@esbuild/sunos-x64": "0.20.1", + "@esbuild/win32-arm64": "0.20.1", + "@esbuild/win32-ia32": "0.20.1", + "@esbuild/win32-x64": "0.20.1" + } + }, + "node_modules/esbuild-wasm": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.20.1.tgz", + "integrity": "sha512-6v/WJubRsjxBbQdz6izgvx7LsVFvVaGmSdwrFHmEzoVgfXL89hkKPoQHsnVI2ngOkcBUQT9kmAM1hVL1k/Av4A==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exceljs": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz", + "integrity": "sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==", + "dependencies": { + "archiver": "^5.0.0", + "dayjs": "^1.8.34", + "fast-csv": "^4.3.1", + "jszip": "^3.10.1", + "readable-stream": "^3.6.0", + "saxes": "^5.0.1", + "tmp": "^0.2.0", + "unzipper": "^0.10.11", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "devOptional": true + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.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" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "devOptional": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "devOptional": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-csv": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-4.3.6.tgz", + "integrity": "sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==", + "dependencies": { + "@fast-csv/format": "4.3.5", + "@fast-csv/parse": "4.3.6" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "peer": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "devOptional": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "devOptional": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "devOptional": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "deprecated": "This package is no longer supported.", + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "devOptional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "devOptional": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "devOptional": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/har-validator/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "devOptional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "devOptional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "devOptional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "devOptional": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "devOptional": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "devOptional": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "optional": true, + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "devOptional": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "devOptional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "devOptional": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "devOptional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", + "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", + "devOptional": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inferno": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno/-/inferno-7.4.11.tgz", + "integrity": "sha512-N+cs33ESWI8fdToCd98yMRYl7jkLnCkJskxov3FKKlaKOvk3PRlAttbhmUaYdWXlRvt2WeXi+J4MbzNj3V6G0w==", + "hasInstallScript": true, + "dependencies": { + "inferno-shared": "7.4.11", + "inferno-vnode-flags": "7.4.11", + "opencollective-postinstall": "^2.0.3" + } + }, + "node_modules/inferno-create-element": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno-create-element/-/inferno-create-element-7.4.11.tgz", + "integrity": "sha512-kE6XIx2hPAd5qpDli2iGjNXgubvuyxdLvoiW71WnSzIIxA+Uxa/s8lY8m03VyHHVypFV3n329ZY5dFvKc7UQMg==", + "peer": true, + "dependencies": { + "inferno": "7.4.11" + } + }, + "node_modules/inferno-hydrate": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno-hydrate/-/inferno-hydrate-7.4.11.tgz", + "integrity": "sha512-hF9Ke4GHAkj8GQrMXBZPfsUqhq6WjkoDCAfXhPBuF1Wiceqyy8KerOOXEnuocHky77fuEXq0AzVnQcC064Bkfw==", + "peer": true, + "dependencies": { + "inferno": "7.4.11" + } + }, + "node_modules/inferno-server": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno-server/-/inferno-server-7.4.11.tgz", + "integrity": "sha512-SUnkCqZNWOIrjRVoVk/E1/70O1f1ImkCX9H2gDPbS0uc3GDxuzIeCgn0rpcc0XV9KzZJ2LTGxuBtEoQQOjUn2Q==", + "dependencies": { + "inferno": "7.4.11" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inferno-shared": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno-shared/-/inferno-shared-7.4.11.tgz", + "integrity": "sha512-pN725bDSTxkQmRS3e/3H02/xAqgHl+xgddCMjPm8M0etRdRcVCisi3NGPhzSbDDmiftrxhY31exs7+dwsngcDA==" + }, + "node_modules/inferno-vnode-flags": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/inferno-vnode-flags/-/inferno-vnode-flags-7.4.11.tgz", + "integrity": "sha512-L7lslEQCq3IfwgT/b9zhuMf8fv6KXCNXXHZevk/WYxnqJsOWGDcKpJn0zkzXfvmj0otbB149iLUQVBq3oe2sfA==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.2.tgz", + "integrity": "sha512-AMB1mvwR1pyBFY/nSevUX6y8nJWS63/SzUKD3JyQn97s4xgIdgQPT75IRouIiBAN4yLQBUShNYVW0+UG25daCw==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/inquirer": { + "version": "9.2.15", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", + "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", + "devOptional": true, + "dependencies": { + "@ljharb/through": "^2.3.12", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^3.2.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "devOptional": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "devOptional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "devOptional": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "devOptional": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "devOptional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha512-cnS56eR9SPAscL77ik76ATVqoPARTqPIVkMDVxRaWH06zT+6+CzIroYRJ0VVvm0Z1zfAvxvz9i/D3Ppjaqt5Nw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha512-qhsCR/Esx4U4hg/9I19OVUAJkGWtjRYHMRgUMZE2TDdj+Ag+kttZanLupfddNyglzz50cUlmWzUaI37GDfNx/g==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "devOptional": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", + "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", + "devOptional": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha512-KbdGQTf5jbZgltoHs31XGiChAPumMSY64OZMWLNYnEnMfG5uwGBhffePwuskexjT+/Jea/gU3qAU8344hNohSw==", + "dev": true, + "dependencies": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.8.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, + "node_modules/jasmine-core": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.2.tgz", + "integrity": "sha512-2oIUMGn00FdUiqz6epiiJr7xcFyNYj3rDcfmnzfkBnHyBQ3cBQUs4mmyGsOb7TTLb9kxk7dBcmEmqhDKkBoDyA==", + "dev": true + }, + "node_modules/jasmine-spec-reporter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-7.0.0.tgz", + "integrity": "sha512-OtC7JRasiTcjsaCBPtMO0Tl8glCejM4J4/dNuOJdA8lBjz4PmWjYQ6pzb0uzpBNAWJMDudYuj9OdXJWqM2QTJg==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jasmine/node_modules/jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha512-SNkOkS+/jMZvLhuSx1fjhcNWUC/KG6oVyFUGkSBEr9n1axSNduWU8GlI7suaHXr4yxjet6KjrUZxUTE5WzzWwQ==", + "dev": true + }, + "node_modules/jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha512-Rn0nZe4rfDhzA63Al3ZGh0E+JTmM6ESZYXJGKuqKGZObsAB9fwXPD03GjtIEvJBDOhN94T5MzbwZSqzFHSQPzg==", + "dev": true, + "engines": { + "node": ">= 6.9.x" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", + "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "devOptional": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", + "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "devOptional": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "dependencies": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.4.8" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/karma": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz", + "integrity": "sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.7.2", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", + "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-coverage": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", + "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "dependencies": { + "jasmine-core": "^4.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "karma": "^6.0.0" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", + "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", + "dev": true, + "peerDependencies": { + "jasmine-core": "^4.0.0 || ^5.0.0", + "karma": "^6.0.0", + "karma-jasmine": "^5.0.0" + } + }, + "node_modules/karma-jasmine/node_modules/jasmine-core": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", + "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", + "dev": true + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/karma/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/karma/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/less": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", + "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "peer": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + }, + "node_modules/lodash.groupby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", + "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==" + }, + "node_modules/lodash.isnil": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isnil/-/lodash.isnil-4.0.0.tgz", + "integrity": "sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isundefined": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz", + "integrity": "sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "peer": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", + "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "devOptional": true, + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz", + "integrity": "sha512-/1HDlyFRxWIZPI1ZpgqlZ8jMw/1Dp/dl3P0L1jtZ+zVcHqwPhGwaJwKL00WVgfnBy6PWCde9W65or7IIETImuA==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "devOptional": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", + "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "devOptional": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "devOptional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/ngx-clipboard": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-16.0.0.tgz", + "integrity": "sha512-rZ/Eo1PqiKMiyF8tdjhmUkoUu68f7OzBJ7YH1YFeh2RAaNrerTaW8XfFOzppSckjFQqA1fwGSYuTTJlDhDag5w==", + "dependencies": { + "ngx-window-token": ">=7.0.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0" + } + }, + "node_modules/ngx-device-detector": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngx-device-detector/-/ngx-device-detector-7.0.0.tgz", + "integrity": "sha512-6IQZLlB31wQecbFr/5YyBfoj9zXgLz/2UHHrslgBnWIzbgdnjfEYSiwqXiJlBC9wIxMvM/BLEIQlxnl3MseQ5g==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "^17.0.0", + "@angular/core": "^17.0.0" + } + }, + "node_modules/ngx-mask": { + "version": "17.0.8", + "resolved": "https://registry.npmjs.org/ngx-mask/-/ngx-mask-17.0.8.tgz", + "integrity": "sha512-zTol/ntrGyBsjkaSt04e/hPmE18TjzmK8+qxU0yyvFiXo5hF8Ut34sgY3NSHAukWAeZVUruS0gVbVOVjW8n8dA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": ">=14.0.0", + "@angular/core": ">=14.0.0", + "@angular/forms": ">=14.0.0" + } + }, + "node_modules/ngx-spinner": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/ngx-spinner/-/ngx-spinner-17.0.0.tgz", + "integrity": "sha512-VWDSvLlCnaWqu0W1L+ybQIRHTbd+GffkX1sWs++iMPXMGVJ2ZCuzW32FHnu+p0regMUHU8r1/rvUcFD0YooJxQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": ">=15.0.0", + "@angular/common": ">=15.0.0", + "@angular/core": ">=15.0.0" + } + }, + "node_modules/ngx-translate-multi-http-loader": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/ngx-translate-multi-http-loader/-/ngx-translate-multi-http-loader-17.0.0.tgz", + "integrity": "sha512-YCq2xEwGiGwuhWHXDoNHVR9TvKEhrVnGFt4WqJjYU220W8yXYKJsoX9f+BOj+sR8ryjOax4wvHy7eCZnIxuIyg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0", + "@ngx-translate/core": ">=15.0.0", + "deepmerge-ts": "^5.1.0", + "rxjs": "^7.8.1" + } + }, + "node_modules/ngx-webcam": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/ngx-webcam/-/ngx-webcam-0.4.1.tgz", + "integrity": "sha512-8WoC8GWHaN5tH+4zO0/gfUigVKg/jX7JShAewpumJIgJXFmlKhSPnPjewNNxv7OTQiOOb+5Mh6lhTo52VLlY9A==", + "dependencies": { + "tslib": "^2.3.0" + } + }, + "node_modules/ngx-window-token": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ngx-window-token/-/ngx-window-token-7.0.0.tgz", + "integrity": "sha512-5+XfRVSY7Dciu8xyCNMkOlH2UfwR9W2P1Pirz7caaZgOZDjFbL8aEO2stjfJJm2FFf1D6dlVHNzhLWGk9HGkqA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=13.0.0", + "@angular/core": ">=13.0.0" + } + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.1.0.tgz", + "integrity": "sha512-B4J5M1cABxPc5PwfjhbV5hoy2DP9p8lFXASnEN6hugXOa61416tnTZ29x9sSwAd0o99XNIcpvDDy1swAExsVKA==", + "devOptional": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "devOptional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "devOptional": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "devOptional": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "devOptional": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", + "integrity": "sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==", + "devOptional": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", + "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", + "devOptional": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "devOptional": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "devOptional": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-packlist": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "devOptional": true, + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", + "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", + "devOptional": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.2.1.tgz", + "integrity": "sha512-8l+7jxhim55S85fjiDGJ1rZXBWGtRLi1OSb4Z3BPLObPuIaeKRlPRiYMSHU4/81ck3t71Z+UwDDl47gcpmfQQA==", + "devOptional": true, + "dependencies": { + "@npmcli/redact": "^1.1.0", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "devOptional": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "devOptional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", + "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", + "devOptional": true, + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^7.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parchment": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-2.0.1.tgz", + "integrity": "sha512-VBKrlEoZCBD+iwoeag0QTtY1Cti+Ma4nLpVYcc/uus/wHhMsPOi5InH3RL1s4aekahPZpabcS2ToKyGf7RMH/g==", + "peer": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dependencies": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "devOptional": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "devOptional": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "devOptional": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "devOptional": true + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/piscina": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.4.0.tgz", + "integrity": "sha512-+AQduEJefrOApE4bV7KRmp3N2JnnyErlVqq4P/jmko4FPz9Z877BCccl/iB3FdrWSUkvbGV9Kan/KllJgat3Vg==", + "dev": true, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/postcss": { + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-loader": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "dev": true, + "dependencies": { + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "devOptional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "devOptional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/protractor": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-7.0.0.tgz", + "integrity": "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw==", + "deprecated": "We have news to share - Protractor is deprecated and will reach end-of-life by Summer 2023. To learn more and find out about other options please refer to this post on the Angular blog. Thank you for using and contributing to Protractor. https://goo.gle/state-of-e2e-in-angular", + "dev": true, + "dependencies": { + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "^3.0.0", + "blocking-proxy": "^1.0.0", + "browserstack": "^1.5.1", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "2.8.0", + "jasminewd2": "^2.1.0", + "q": "1.4.1", + "saucelabs": "^1.5.0", + "selenium-webdriver": "3.6.0", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "2.1.0", + "webdriver-manager": "^12.1.7", + "yargs": "^15.3.1" + }, + "bin": { + "protractor": "bin/protractor", + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=10.13.x" + } + }, + "node_modules/protractor/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/protractor/node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/protractor/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protractor/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/protractor/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/protractor/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/protractor/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg==", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "peer": true, + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-package-json": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.1.tgz", + "integrity": "sha512-8PcDiZ8DXUjLf687Ol4BR8Bpm2umR7vhoZOzNRt+uxD9GpBh/K+CAAALVIiYFknmvlmyg7hM7BSNUXPaCCqd0Q==", + "deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.", + "devOptional": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "devOptional": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "devOptional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "devOptional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "devOptional": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "dev": true + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "devOptional": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "devOptional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrule": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rrule/-/rrule-2.8.1.tgz", + "integrity": "sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==", + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "devOptional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true + }, + "node_modules/safevalues": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz", + "integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw==" + }, + "node_modules/sass": { + "version": "1.71.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz", + "integrity": "sha512-wovtnV2PxzteLlfNzbgm1tFXPLoZILYAMJtvoXXkD7/+1uP41eKkIt1ypWq5/q2uT94qHjXehEYfmjKOvjL9sg==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.1.1.tgz", + "integrity": "sha512-QX8AasDg75monlybel38BZ49JP5Z+uSKfKwF2rO7S74BywaRmGQMUBw9dtkS+ekyM/QnP+NOrRYq8ABMZ9G8jw==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/saucelabs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz", + "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/saucelabs/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/saucelabs/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/saucelabs/node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/sax": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.0.tgz", + "integrity": "sha512-G3nn4N8SRaR9NsCqEUHfTlfTM/Fgza1yfb8JP2CEmzYuHtHWza5Uf+g7nuUQq96prwu0GiGyPgDw752+j4fzQQ==", + "dev": true + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "dependencies": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/selenium-webdriver/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/selenium-webdriver/node_modules/tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha512-e8BOaTo007E3dMuQQTnPdalbKTABKNS7UxoBIDnwOqRa+QwMrCPjynB8zAlPF6xlqUfdLPPLIJ13hJNmhtq8Ng==", + "dev": true, + "dependencies": { + "semver": "^5.3.0" + } + }, + "node_modules/semver-dsl/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "devOptional": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "peer": true, + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sigstore": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", + "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", + "devOptional": true, + "dependencies": { + "@sigstore/bundle": "^2.3.2", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^2.3.2", + "@sigstore/tuf": "^2.3.4", + "@sigstore/verify": "^1.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dev": true, + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "devOptional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz", + "integrity": "sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==", + "devOptional": true, + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", + "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "dev": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "devOptional": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "devOptional": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "devOptional": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "devOptional": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "devOptional": true + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/ssri": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", + "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "devOptional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "devOptional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "devOptional": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "devOptional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/terser": { + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "optional": true, + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "engines": { + "node": "*" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tslint": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.3", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.13.0", + "tsutils": "^2.29.0" + }, + "bin": { + "tslint": "bin/tslint" + }, + "engines": { + "node": ">=4.8.0" + }, + "peerDependencies": { + "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + } + }, + "node_modules/tslint/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tslint/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "peerDependencies": { + "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tuf-js": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", + "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", + "devOptional": true, + "dependencies": { + "@tufjs/models": "2.0.1", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/turndown": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.3.tgz", + "integrity": "sha512-Z3/iJ6IWh8VBiACWQJaA5ulPQE5E1QwvBHj00uGzdQxdRnd8fh1DPqNOJqzQDu6DkOstORrtXzf/9adB+vMtEA==", + "peer": true, + "dependencies": { + "domino": "^2.1.6" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "devOptional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.37", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.37.tgz", + "integrity": "sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/undici": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.11.1.tgz", + "integrity": "sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==", + "dev": true, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "devOptional": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "devOptional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "optional": true, + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "devOptional": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "devOptional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vite": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz", + "integrity": "sha512-sgnEEFTZYMui/sTlH1/XEnVNHMujOahPLGMxn1+5sIT45Xjng1Ec1K78jRP15dSmVgg5WBin9yO81j3o9OxofA==", + "dev": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webdriver-js-extender": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", + "dev": true, + "dependencies": { + "@types/selenium-webdriver": "^3.0.0", + "selenium-webdriver": "^3.0.1" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager": { + "version": "12.1.9", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.9.tgz", + "integrity": "sha512-Yl113uKm8z4m/KMUVWHq1Sjtla2uxEBtx2Ue3AmIlnlPAKloDn/Lvmy6pqWCUersVISpdMeVpAaGbNnvMuT2LQ==", + "dev": true, + "dependencies": { + "adm-zip": "^0.5.2", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + }, + "bin": { + "webdriver-manager": "bin/webdriver-manager" + }, + "engines": { + "node": ">=6.9.x" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/webdriver-manager/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/webdriver-manager/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/webdriver-manager/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webdriver-manager/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/webpack": { + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.2.tgz", + "integrity": "sha512-Wu+EHmX326YPYUpQLKmKbTyZZJIB8/n6R09pTmB03kJmnMsVPTo9COzHZFr01txwaCAuZvfBJE4ZCHRcKs5JaQ==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "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-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "dev": true, + "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 + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", + "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "devOptional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "devOptional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "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 + } + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zone.js": { + "version": "0.14.6", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.6.tgz", + "integrity": "sha512-vyRNFqofdaHVdWAy7v3Bzmn84a1JHWSjpuTZROT/uYn8I3p2cmo7Ro9twFmYRQDPhiYOV7QLk0hhY4JJQVqS6Q==" + } + } +} diff --git a/ClientApp/staff-db-ui/package.json b/ClientApp/staff-db-ui/package.json new file mode 100644 index 0000000..93a8fd6 --- /dev/null +++ b/ClientApp/staff-db-ui/package.json @@ -0,0 +1,70 @@ +{ + "name": "staffdb", + "version": "14.23.33", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e", + "reinstall:packages": "rm -rf node_modules dist && npm cache clean --force && rm package-lock.json && npm install", + "win_reinstall:packages": "rd /s /q node_modules && npm cache clean --force && del package-lock.json && npm install", + "add_pwa": "ng add @angular/pwa@latest" + }, + "private": true, + "dependencies": { + "@angular/animations": "^17.3.10", + "@angular/cdk": "^16.2.14", + "@angular/common": "^17.3.10", + "@angular/compiler": "^17.3.10", + "@angular/core": "^17.3.10", + "@angular/forms": "^17.3.10", + "@angular/localize": "^17.3.10", + "@angular/material": "^16.2.14", + "@angular/material-moment-adapter": "^16.2.14", + "@angular/platform-browser": "^17.3.10", + "@angular/platform-browser-dynamic": "^17.3.10", + "@angular/pwa": "^17.3.8", + "@angular/router": "^17.3.10", + "@angular/service-worker": "^17.3.10", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@sentry/angular": "^8.4.0", + "angular-in-memory-web-api": "^0.17.0", + "devextreme-angular": "~23.2.6", + "exceljs": "^4.4.0", + "file-saver": "^2.0.5", + "jspdf": "^2.5.1", + "moment": "^2.30.1", + "ngx-clipboard": "^16.0.0", + "ngx-device-detector": "^7.0.0", + "ngx-mask": "^17.0.8", + "ngx-spinner": "^17.0.0", + "ngx-translate-multi-http-loader": "^17.0.0", + "ngx-webcam": "^0.4.1", + "rxjs": "^7.8.1", + "zone.js": "^0.14.6" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.3.8", + "@angular/cli": "^17.3.8", + "@angular/compiler-cli": "^17.3.10", + "@angular/language-service": "^17.3.10", + "@types/jasmine": "latest", + "@types/node": "latest", + "codelyzer": "latest", + "jasmine-core": "latest", + "jasmine-spec-reporter": "latest", + "karma": "latest", + "karma-chrome-launcher": "latest", + "karma-coverage": "latest", + "karma-jasmine": "latest", + "karma-jasmine-html-reporter": "latest", + "protractor": "latest", + "ts-node": "latest", + "tslint": "latest", + "typescript": "~5.4.5" + } +} diff --git a/ClientApp/staff-db-ui/src/app/app-routing.module.ts b/ClientApp/staff-db-ui/src/app/app-routing.module.ts new file mode 100644 index 0000000..762d9f2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/app-routing.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule, PreloadAllModules } from '@angular/router'; +import { APP_PAGES } from '@app_consts'; +import { ACCOUNT_PAGE, Globals, LOGIN_PAGE } from '@app_core/services/globals'; + +ACCOUNT_PAGE.loadChildren = () => import('@app_modules/app-account/app-account.module').then(m => m.AppAccountModule); + +const routes: Routes = [ + ...APP_PAGES, + { + path: '', + redirectTo: '/' + LOGIN_PAGE.path, + pathMatch: 'full' + } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes, { useHash: true, preloadingStrategy: PreloadAllModules })], + exports: [RouterModule] +}) +export class AppRoutingModule { public globals: Globals; } diff --git a/ClientApp/staff-db-ui/src/app/app.component.html b/ClientApp/staff-db-ui/src/app/app.component.html new file mode 100644 index 0000000..705ccc1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/app.component.html @@ -0,0 +1,2 @@ + + diff --git a/ClientApp/staff-db-ui/src/app/app.component.scss b/ClientApp/staff-db-ui/src/app/app.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/ClientApp/staff-db-ui/src/app/app.component.spec.ts b/ClientApp/staff-db-ui/src/app/app.component.spec.ts new file mode 100644 index 0000000..e0e2e4f --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed, async } from '@angular/core/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'staffdb'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('ang-material'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to Angular!'); + })); +}); diff --git a/ClientApp/staff-db-ui/src/app/app.component.ts b/ClientApp/staff-db-ui/src/app/app.component.ts new file mode 100644 index 0000000..700881a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/app.component.ts @@ -0,0 +1,58 @@ +import { Component, inject, OnInit } from '@angular/core'; +import { SwUpdate } from '@angular/service-worker'; +import * as AppCnst from '@app_consts'; +import * as Cnst from '@app_core/consts'; +import * as Utils from '@app_core/utils'; +import { TranslateService } from '@ngx-translate/core'; +import * as AppModule from './app.module'; +import { ENVIRONMENT_TOKEN } from '@app_core/injection-tokens'; +import { Globals } from '@app_core/services/globals'; +import { RepositoryService } from '@app_core/services/http/repository.service'; +import { ServerInfoService } from '@app_core/services/serverinfo.service'; +import { LocaleService } from '@app_core/services/localization/locale.service'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) + + +export class AppComponent implements OnInit { + private environment = inject(ENVIRONMENT_TOKEN); + + constructor( + public globals: Globals, + public repository: RepositoryService, + public translate: TranslateService, + private serverInfoService: ServerInfoService, + private localeService: LocaleService, + private updateService: SwUpdate + + ) { + this.initLangCulture(); + globals.appTitle = AppCnst.APP_TITLE; + Utils.setIndexTitle(globals.appTitle); + globals.appTitleWithVersion = `${AppCnst.APP_TITLE} V.${this.environment.appVersion} (${this.environment.appBuild})`; + globals.appPages = AppCnst.APP_PAGES; + globals.mainPage = AppCnst.APP_PAGES[0]; + this.serverInfoService.defaultServerInfoVisible = false; + } + + + private initLangCulture() { + this.translate.addLangs(AppCnst.SUPPORTED_LANGUAGES); + + const languageFromBrowser: string = navigator.language.split('-')[0]; + const startLanguage: string = Utils.isLanguageSupported(languageFromBrowser, AppCnst.SUPPORTED_LANGUAGES, Cnst.SUPPORTED_LANGUAGES) ? languageFromBrowser : AppCnst.cnst_DefaultLanguage; + const startCulture: string = Utils.isCultureSupported(navigator.language, AppModule.SUPPORTED_CULTURES, Cnst.SUPPORTED_CULTURES) ? navigator.language : AppCnst.cnst_DefaultCulture; + + this.localeService.initLocaleLanguage(startCulture, startLanguage); + } + + + ngOnInit(): void { + this.updateService.checkForUpdate().then((res) => { if (res) { this.updateService.activateUpdate(); window.location.reload(); } }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/app.module.ts b/ClientApp/staff-db-ui/src/app/app.module.ts new file mode 100644 index 0000000..dfd4540 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/app.module.ts @@ -0,0 +1,144 @@ +import { AppComponent } from './app.component'; +import { BrowserModule } from '@angular/platform-browser'; + +/* Routing */ +import { AppRoutingModule } from './app-routing.module'; + +/* Angular Material */ +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { AngularMaterialModule } from '@app_core/components/angular-material.module'; +import { APPICON4LIVE_TOKEN, APPICON4NAVBAR_TOKEN, APPICON4TEST_TOKEN, ENVIRONMENT_TOKEN, IENVIRONMENT, SUPPORTED_CULTURES_TOKEN, SUPPORTED_LANGUAGES_TOKEN } from '@app_core/injection-tokens'; +import { NgModule, CUSTOM_ELEMENTS_SCHEMA, Injectable } from '@angular/core'; + +/* FormsModule */ +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +/* Components */ +import { LayoutModule } from '@app_core/components/layout/layout.module'; +import { NgxSpinnerModule } from 'ngx-spinner'; + +/* data acess */ +import { HttpInterceptorService } from '@app_core/services/http/http-interceptor.service'; +import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; + +/* Globals */ +import { ErrorStateMatcher, ShowOnDirtyErrorStateMatcher } from '@angular/material/core'; +import { DxFormModule, DxButtonModule, DxTemplateHost, DxTemplateModule, DxChartModule, DxDataGridModule } from 'devextreme-angular'; +import { NgxMaskDirective, NgxMaskPipe, optionsConfig, provideNgxMask } from 'ngx-mask'; +import { Router } from '@angular/router'; +import { ServiceWorkerModule } from '@angular/service-worker'; +import { MessageBoxModule } from '@app_core/components/message-box/message-box.module'; +import { ClipboardModule } from 'ngx-clipboard'; + +/* Localisaton */ +import { TranslateModule, TranslateService } from '@ngx-translate/core'; +import { LocaleProvider } from '@app_core/services/localization/locale.provider'; +import { HenselTranslateService } from '@app_core/services/localization/hensel-translate.service'; +import { registerLocaleData } from '@angular/common'; +import { loadMessages } from 'devextreme/localization'; + +import localeDe from '@angular/common/locales/de'; +import localeUs from '@angular/common/locales/en'; +import localeFr from '@angular/common/locales/fr'; +import localeGb from '@angular/common/locales/en-GB'; + +export const SUPPORTED_CULTURES = ['de-DE', 'en-GB', 'en-US', 'fr-FR']; +registerLocaleData(localeDe, 'de-DE'); +registerLocaleData(localeUs, 'en-US'); +registerLocaleData(localeFr, 'fr-FR'); +registerLocaleData(localeGb, 'en-GB'); + +import * as deMessages from 'devextreme/localization/messages/de.json'; +loadMessages(deMessages); + +// import { HammerGestureConfig, HAMMER_GESTURE_CONFIG, HammerModule } from '@angular/platform-browser'; +// AoT requires an exported function for factories +// export class MyHammerConfig extends HammerGestureConfig { +// // tslint:disable-next-line:no-angle-bracket-type-assertion +// overrides = { +// swipe: { direction: Hammer.DIRECTION_ALL }, +// }; +// } + +/* Sentry */ +import { APP_INITIALIZER, ErrorHandler } from '@angular/core'; +import * as Sentry from '@sentry/angular'; +import { SUPPORTED_LANGUAGES } from '@app_consts'; +import { TranslateLoaderProvider } from '@app_core/services/localization/translation-loader.provider'; +import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@app_core/components/angular-material-index'; + +/* important to use mask functionality */ +const maskConfig: optionsConfig = { + validation: false, +}; + + +declare const environment: IENVIRONMENT; +declare const appVersion: string; +declare const appBuild: string; +environment['appVersion'] = appVersion; +environment['appBuild'] = appBuild; + +@Injectable() +export class SentryErrorHandler implements ErrorHandler { + handleError(error) { + Sentry.captureException(error.originalError || error); + } +} + +@NgModule({ + declarations: [ + AppComponent, + ], + imports: [ + HttpClientModule, + BrowserModule, + BrowserAnimationsModule, + AngularMaterialModule, + ReactiveFormsModule, + FormsModule, + DxFormModule, + DxTemplateModule, + DxDataGridModule, + DxChartModule, + DxButtonModule, + MessageBoxModule, + ClipboardModule, + NgxSpinnerModule, + NgxMaskDirective, + NgxMaskPipe, + TranslateModule.forRoot({loader: TranslateLoaderProvider}), + ServiceWorkerModule.register('ngsw-worker.js', { + enabled: true, //environment.production, + // Register the ServiceWorker as soon as the application is stable + // or after 30 seconds (whichever comes first). + registrationStrategy: 'registerWhenStable:30000' + }), + LayoutModule, + AppRoutingModule, // must be the last!!! + ], + providers: [ + DxTemplateHost, + LocaleProvider, + { provide: ENVIRONMENT_TOKEN, useValue: environment }, + { provide: SUPPORTED_LANGUAGES_TOKEN, useValue: SUPPORTED_LANGUAGES}, + { provide: SUPPORTED_CULTURES_TOKEN, useValue: SUPPORTED_CULTURES}, + { provide: APPICON4TEST_TOKEN, useValue: 'assets/icons/develop/dhr-icon-48x48.png'}, + { provide: APPICON4LIVE_TOKEN, useValue: 'assets/icons/production/dhr-icon-48x48.png'}, + { provide: APPICON4NAVBAR_TOKEN, useValue: 'assets/icons/main_48x48.png'}, + { provide: TranslateService, useClass: HenselTranslateService }, + { provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true }, + { provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { floatLabel: 'auto' } }, + { provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }, + /* Sentry */ + { provide: ErrorHandler, useClass: SentryErrorHandler/*, useValue: Sentry.createErrorHandler({showDialog: false, })*/ }, + { provide: Sentry.TraceService, deps: [Router] }, + { provide: APP_INITIALIZER, useFactory: () => () => {}, deps: [Sentry.TraceService], multi: true }, + provideNgxMask(maskConfig) + ], + bootstrap: [AppComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA], +}) + + +export class AppModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/app-account/app-account-routing.module.ts b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account-routing.module.ts new file mode 100644 index 0000000..466013e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AppAccountComponent } from './app-account.component'; +import { AuthGuard } from '@app_core/services/authguard'; + + +const routes: Routes = [ + { + path: '', + component: AppAccountComponent, + canActivate: [AuthGuard] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AppAccountRoutingModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.html b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.html new file mode 100644 index 0000000..0c07ff7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.html @@ -0,0 +1,22 @@ + +
+
+ + + +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.scss b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.scss new file mode 100644 index 0000000..f8698ef --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.scss @@ -0,0 +1,9 @@ +.input-webapp{ + float: left; +} + + +.btn{ + margin-left: 10px; + margin-top: 8px; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.ts b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.ts new file mode 100644 index 0000000..e8d66cf --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.component.ts @@ -0,0 +1,16 @@ +import { Component, inject } from '@angular/core'; +import { AccountComponent } from '@app_core/components/account/account.component'; +import { AppDataService } from '@app_services/app.data.service'; + +@Component({ + selector: 'app-account-ext', + templateUrl: 'app-account.component.html', + styleUrls: ['app-account.component.scss'] +}) + +export class AppAccountComponent extends AccountComponent { + public appDataService = inject(AppDataService); + + onClick() { + } +} diff --git a/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.module.ts b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.module.ts new file mode 100644 index 0000000..a72ec7c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/app-account/app-account.module.ts @@ -0,0 +1,29 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import { DxDataGridModule } from 'devextreme-angular'; +import { DxoSearchPanelModule } from 'devextreme-angular/ui/nested'; +import { AppAccountRoutingModule } from './app-account-routing.module'; +import { AppAccountComponent } from './app-account.component'; +import { AccountModule } from '@app_core/components/account/account.module'; +import { AngularMaterialModule } from '@app_core/components/angular-material.module'; +import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component'; + + +@NgModule({ + declarations: [AppAccountComponent], + imports: [ + CommonModule, + AppAccountRoutingModule, //must be earlier AccountModule + AccountModule, + AngularMaterialModule, + ReactiveFormsModule, + FormsModule, + DxDataGridModule, + DxoSearchPanelModule, + HenselSelectionComponent, + TranslateModule + ] +}) +export class AppAccountModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-data.service.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-data.service.ts new file mode 100644 index 0000000..d9fdaa8 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-data.service.ts @@ -0,0 +1,181 @@ +import { Injectable } from '@angular/core'; +import { cnst_LoadedEntitiesExpiresInMs, EN_AppEntities, EN_AppPages, EN_HttpQueriesCount4Page } from '@app_consts'; +import { CoreUser } from '@app_core/models/coreuser'; +import { RepositoryService } from '@app_core/services/http/repository.service'; +import { CorePageService } from '@app_core/services/page.service'; +import { Department, DepartmentFilter } from '@app_models/basedata/department'; +import { DocumentArtToDepartment } from '@app_models/documentart-to-department'; +import { Employee } from '@app_models/employee'; +import { User } from '@app_models/user'; +import { WindreamIndex } from '@app_models/windream-index'; +import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department'; +import { ClientIdFilter, WindreamSearch } from '@app_models/windream-search'; +import { WindreamSearchItem } from '@app_models/windream-search-item'; +import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department'; +import { WindreamSearchToDepartment, WindreamSearchToDepartmentFilter } from '@app_models/windream-search-to-department'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; + + +@Injectable({ providedIn: 'root' }) + +export class DepartmentDataService extends CorePageService { + protected appPage: EN_AppPages = EN_AppPages.Department; + protected loadImedeately: boolean = true; //load on pening the page + protected get appPageNoQueries() { return EN_HttpQueriesCount4Page.Department; } + + // --- running data + departmentFilter: DepartmentFilter = new DepartmentFilter('DepartmentFullFilter'); + departmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Department, 'Abteilungsliste', EN_AppEntities.Department); + + departmentDetails: AppBaseEntityWrapper; + windreamSearchToDepartmentDetails: AppBaseEntityWrapper; + // tslint:disable-next-line: max-line-length + windreamSearchToDepartmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WindreamSearchToDepartment, 'Windream Suche Kacheln', EN_AppEntities.WindreamSearchToDepartment); + windreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('DepartmentFilter'); + // tslint:disable-next-line: max-line-length + windreamSearchItemToWindreamSearchToDepartmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WindreamSearchItemToWindreamSearchToDepartment, 'Windream Suchbausteine', EN_AppEntities.WindreamSearchItemToWindreamSearchToDepartment); + windreamSearchItemToWindreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('WindreamSearchToDepartmentFilter'); + windreamSearchItemToWindreamSearchToDepartmentDetails: AppBaseEntityWrapper; + + windreamSearchItemList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WindreamSearchItem, 'windream suche kacheln attribute', EN_AppEntities.WindreamSearchItem); + windreamIndexToWindreamSearchToDepartmentDetails: AppBaseEntityWrapper; + // tslint:disable-next-line: max-line-length + windreamIndexToWindreamSearchToDepartmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WindreamIndexToWindreamSearchToDepartment, 'Ausgabespalten für Windream Suche', EN_AppEntities.WindreamIndexToWindreamSearchToDepartment); + windreamIndexToWindreamSearchToDepartmentFilter: WindreamSearchToDepartmentFilter = new WindreamSearchToDepartmentFilter('WindreamSearchToDepartmentFilter'); + + windreamSearchList: AppBaseEntityListWrapper = + new AppBaseEntityListWrapper(WindreamSearch, 'Windream Suche Kacheln', EN_AppEntities.WindreamSearch); + + clientIdFilter: ClientIdFilter = new ClientIdFilter('ClientIdFilter'); + + windreamIndexList: AppBaseEntityListWrapper = + new AppBaseEntityListWrapper(WindreamIndex, 'Windream Index', EN_AppEntities.WindreamIndex); + + documentArtToDepartmentListFilter: DepartmentFilter = new DepartmentFilter('DepartmentFilter'); + + documentArtToDepartmentList: AppBaseEntityListWrapper = + new AppBaseEntityListWrapper(DocumentArtToDepartment, 'Dokumentartenliste für Department', EN_AppEntities.DocumentArtToDepartment); + + employeeList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Employee, 'mitarbeiter', EN_AppEntities.Employee + '/all'); + + selectedDocumentarts: number[] = []; + clpbrdWindreamOutColHint1: string; + clpbrdWindreamOutColHints: string; + clpbrdWindreamOutColList: WindreamIndexToWindreamSearchToDepartment[] = []; + + clpbrdWindreamSearchItemHint1: string; + clpbrdWindreamSearchItemHints: string; + clpbrdWindreamSearchItemList: WindreamSearchItemToWindreamSearchToDepartment[] = []; + + constructor( + private repositoryService: RepositoryService, + ) { + super(); + + this.departmentList.focusedCallBack = this.focusCallBack.bind(this); + this.departmentList.filter = this.departmentFilter; + this.departmentDetails = this.departmentList.createFocusedShadowEntity(AppBaseEntityWrapper.EN_ViewMode); + this.departmentDetails.loadedDataExpiresInMs = cnst_LoadedEntitiesExpiresInMs; + this.baseEntityWrapperWaitLoading = this.departmentDetails; + this.activateRouting4EntityList(this.departmentList); //we are using routing + + this.windreamSearchToDepartmentList.filter = this.windreamSearchToDepartmentFilter; + this.windreamSearchToDepartmentDetails = this.windreamSearchToDepartmentList.createFocusedShadowEntity(); + this.windreamSearchToDepartmentDetails.dontLoadEntity = true; + this.windreamSearchToDepartmentDetails.beforeNewCallBack = this.prepareSearchToDepartment.bind(this); + + this.windreamIndexToWindreamSearchToDepartmentList.filter = this.windreamIndexToWindreamSearchToDepartmentFilter; + this.windreamIndexToWindreamSearchToDepartmentDetails = this.windreamIndexToWindreamSearchToDepartmentList.createFocusedShadowEntity(); + this.windreamIndexToWindreamSearchToDepartmentDetails.dontLoadEntity = true; + + this.windreamSearchItemToWindreamSearchToDepartmentList.filter = this.windreamSearchItemToWindreamSearchToDepartmentFilter; + this.windreamSearchItemToWindreamSearchToDepartmentDetails = this.windreamSearchItemToWindreamSearchToDepartmentList.createFocusedShadowEntity(); + this.windreamSearchItemToWindreamSearchToDepartmentDetails.dontLoadEntity = true; + + this.windreamSearchList.filter = this.clientIdFilter; + this.windreamIndexList.filter = this.clientIdFilter; + this.windreamSearchItemList.filter = this.clientIdFilter; + this.documentArtToDepartmentList.filter = this.documentArtToDepartmentListFilter; + + + this.departmentDetails.detailItems.register(this.windreamSearchToDepartmentList, null, 'departmentId'); + this.departmentDetails.detailItems.register(this.documentArtToDepartmentList, null, 'departmentId', (docarts: DocumentArtToDepartment[]) => { + this.selectedDocumentarts = docarts.map(docart => docart.documentArtId); + }); + this.windreamSearchToDepartmentDetails.detailItems.register(this.windreamIndexToWindreamSearchToDepartmentList, null, 'windreamSearchToDepartmentId'); + this.windreamSearchToDepartmentDetails.detailItems.register(this.windreamSearchItemToWindreamSearchToDepartmentList, null, 'windreamSearchToDepartmentId'); + + this.loadBaseData(); + this.init(); + } + + + loadData() { + super.loadData(); + this.departmentList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage)); + } + + public loadBaseData() { + super.loadBaseData(this.appPage, 1); + this.employeeList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage)); + } + + public focusCallBack(focusedItem: Department) { + this.clientIdFilter.clientId = focusedItem?.clientId; + } + + public clearData() { + super.clearData(); + this.departmentFilter.filterReset(); + this.departmentList.clear(); + } + + protected onLoggedInOut(user: CoreUser) { + this.userChanged(new User(user)); + super.onLoggedInOut(user); + } + + private userChanged(user: User) { + if (this.authService.isLoggedIn()) { + this.departmentDetails.canNew = user.isMaster; + this.departmentDetails.canEdit = this.departmentDetails.canNew; + this.departmentDetails.canDelete = this.departmentDetails.canNew; + } + } + + moveUpDown(direction: number, + list: + AppBaseEntityListWrapper + | AppBaseEntityListWrapper + | AppBaseEntityListWrapper + ) { + const curItemIndex: number = list.focusedItemIndex; + if (!(direction < 0 && curItemIndex === 0 || direction > 0 && curItemIndex === list.items.length)) { + const targetItem = list.items[curItemIndex + direction]; + const targetSeq: number = targetItem.seq; + const currentItem = list.focusedItem; + targetItem.seq = currentItem.seq; + currentItem.seq = targetSeq; + targetItem.entityChanged = true; + currentItem.entityChanged = true; + + targetItem.save(this.repositoryService, null, null, null); + currentItem.save(this.repositoryService, null, null, null); + this.sortBySeq(list.items); + } + } + + public sortBySeq(list: WindreamSearchToDepartment[] | WindreamSearchItemToWindreamSearchToDepartment[] | WindreamIndexToWindreamSearchToDepartment[]) { + list.sort((fp1, fp2) => (fp1.seq - fp2.seq)); + } + + + prepareSearchToDepartment(item: WindreamSearchToDepartment) { + const maxSeq = this.windreamSearchToDepartmentList.items.reduce((max: number, _index: WindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0); + item.seq = maxSeq + 1; + item.isActive = true; + } + + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.html new file mode 100644 index 0000000..ba9d181 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.html @@ -0,0 +1,100 @@ +
+ + + + + + + + + + + + + + + + + + + + Virtual + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.scss new file mode 100644 index 0000000..e0c9031 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.scss @@ -0,0 +1,52 @@ +.departmentDetailsContent{ +// z-index: 10; + // position: relative; //otherwise z-index is not working + padding: 0 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-column-gap: 8px; + grid-template-columns: repeat(2, minmax(1px, 1fr)); // column relationship + grid-template-rows: repeat(5, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: + "input-departmentName input-cost-centre" + "input-departmentType input-headofDepartmentId" + "input-executiveDirectorId input-managingDirectorId" + "input-departmentNameFolder input-adGroupDepartmentName" + "input-clientId input-isVirtual" + ; +} + + +.input-departmentName{ + grid-area: input-departmentName; +} +.input-cost-centre{ + grid-area: input-cost-centre; +} +.input-departmentType{ + grid-area: input-departmentType; +} +.input-headofDepartmentId{ + grid-area: input-headofDepartmentId; +} +.input-executiveDirectorId{ + grid-area: input-executiveDirectorId; +} +.input-managingDirectorId{ + grid-area: input-managingDirectorId; +} +.input-departmentNameFolder{ + grid-area: input-departmentNameFolder; +} +.input-adGroupDepartmentName{ + grid-area: input-adGroupDepartmentName; +} +.input-clientId{ + grid-area: input-clientId; +} +.input-isVirtual{ + grid-area: input-isVirtual; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.spec.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.spec.ts new file mode 100644 index 0000000..d663dca --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentContentComponent } from './department-content.component'; + +describe('DepartmentContentComponent', () => { + let component: DepartmentContentComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DepartmentContentComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentContentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.ts new file mode 100644 index 0000000..a39c835 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-content/department-content.component.ts @@ -0,0 +1,53 @@ +import { Component, Input, OnInit, ViewChild, AfterViewInit } from '@angular/core'; +import { Department } from '@app_models/basedata/department'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { CostCentre } from '@app_models/basedata/cost-centre'; +import { Employee } from '@app_models/employee'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; +import { NgForm } from '@angular/forms'; + +@Component({ + selector: 'app-department-content', + templateUrl: './department-content.component.html', + styleUrls: ['./department-content.component.scss'] +}) +export class DepartmentContentComponent implements OnInit, AfterViewInit { + @ViewChild('detailForm') detailForm: NgForm; + @Input() departmentDetails: AppBaseEntityWrapper; + + + public get department(): Department { + return this.departmentDetails.entity; + } + + + public get employeeList(): Employee[] { + return this.departmentService.employeeList.items; + } + + + + public get costCentreList(): CostCentre[] { + return this.appDataService.costCentreList.items; + } + + + constructor( + private appDataService: AppDataService, + private departmentService: DepartmentDataService) { } + + ngOnInit() { + } + + ngAfterViewInit(): void { + this.departmentDetails.detailForm = this.detailForm; + } + + depNameWasChanged() { + if (!this.department.departmentName) return; + if (!this.department.departmentNameFolder) this.department.departmentNameFolder = this.department.departmentName; + if (!this.department.adGroupDepartmentName) this.department.adGroupDepartmentName = this.department.departmentName; + } +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.html new file mode 100644 index 0000000..e7ecd6d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.html @@ -0,0 +1,59 @@ +
+ + + + +
+
+ + + + + +
+
+ + + + + + + + + + + +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.scss new file mode 100644 index 0000000..3820531 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.scss @@ -0,0 +1,46 @@ +.DepartmentDetails { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: auto repeat(1, minmax(1px, 250px)); // row relationships + grid-template-columns: minmax(1px, 0.7fr) minmax(1px, 0.7fr) minmax(1px, 0.5fr) minmax(1px, 0.5fr) minmax(1px, 1fr); // column relationship + grid-row-gap: 6px; + grid-column-gap: 10px; + grid-template-areas: + 'toolbar toolbar toolbar toolbar toolbar' + 'detail documentArtList windreamSearchList windreamSearchItemList windreamIndexList'; + z-index: 10; + position: relative; //otherwise z-index is not working +} +.WindreamSearchItemList{ + grid-area: windreamSearchItemList; +} + +.WindreamIndexList{ + grid-area: windreamIndexList; +} +.WindreamSearchList{ + grid-area: windreamSearchList; +} +.DetailsContent { + grid-area: detail; +} +.DocumentArtList { + grid-area: documentArtList; +} + +.abstand { + margin-right: 1px !important; +} + +.toolbar { + grid-area: toolbar; +} + +.card { + padding: 12px; + margin: 2px 2px 2px 2px; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.ts new file mode 100644 index 0000000..d8f5228 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-detail.component.ts @@ -0,0 +1,109 @@ +import { Component, OnInit, Input, ChangeDetectorRef, DoCheck, ChangeDetectionStrategy, Output, EventEmitter, ViewChild, ElementRef, AfterViewInit, HostListener } from '@angular/core'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { DepartmentDataService } from '../department-data.service'; +import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department'; +import { Department } from '@app_models/basedata/department'; +import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department'; +import { WindreamSearchItem } from '@app_models/windream-search-item'; +import { NgForm } from '@angular/forms'; +import { reduce } from 'rxjs/operators'; +import { AuthorizeService } from '@app_core/services/authorize.service'; +import { PageLoadingService } from '@app_core/services/pageloading.service'; +import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts'; +import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component'; + +@Component({ + selector: 'app-department-detail', + templateUrl: './department-detail.component.html', + styleUrls: ['./department-detail.component.scss'], +}) +export class DepartmentDetailComponent implements AfterViewInit { + + @ViewChild('detailForm') detailForm: NgForm; + + @Input() public departmentDetails: AppBaseEntityWrapper; + + public get windreamSearchToDepartmentDetails(): AppBaseEntityWrapper { + return this.departmentDataService.windreamSearchToDepartmentDetails; + } + + constructor( + public departmentDataService: DepartmentDataService, + public authorizeService: AuthorizeService, + private pageLoadingService: PageLoadingService, + ) { + } + public get windreamSearchList(): AppBaseEntityListWrapper { + return this.departmentDataService.windreamSearchToDepartmentList; + } + public get windreamSearchDetails(): AppBaseEntityWrapper { + return this.departmentDataService.windreamSearchToDepartmentDetails; + } + + + public get windreamSearchItemToWindreamSearchToDepartmentList(): AppBaseEntityListWrapper { + return this.departmentDataService.windreamSearchItemToWindreamSearchToDepartmentList; + } + public get windreamSearchItemToWindreamSearchToDepartmentDetails(): AppBaseEntityWrapper { + return this.departmentDataService.windreamSearchItemToWindreamSearchToDepartmentDetails; + } + public get windreamSearchItemList(): AppBaseEntityListWrapper { + return this.departmentDataService.windreamSearchItemList; + } + + + public get windreamIndexList(): AppBaseEntityListWrapper { + return this.departmentDataService.windreamIndexToWindreamSearchToDepartmentList; + } + public get windreamIndexDetails(): AppBaseEntityWrapper { + return this.departmentDataService.windreamIndexToWindreamSearchToDepartmentDetails; + } + + + public get focusedItem(): Department { + return this.departmentDetails.entity; + } + + ngAfterViewInit(): void { + this.departmentDetails.beforeNewCallBack = this.newDepartmentInit.bind(this); + this.departmentDetails.beforeSaveCallBack = this.beforeSaveDepartment.bind(this); + } + + newDepartmentInit(department: Department) { + this.departmentDataService.selectedDocumentarts = []; + department.departmentTypeId = 1; + department.clientId = 24110; + } + + async beforeSaveDepartment(department: Department): Promise { + const maxId: number = this.departmentDataService.departmentList.items.reduce((max, currentItem) => (currentItem.entityId > max ? currentItem.entityId : max), 0); + if (department.isNew()) department.departmentId = -(maxId + 1); + this.departmentDataService.documentArtToDepartmentList.match2KeysArray(department, 'departmentId', this.departmentDataService.selectedDocumentarts, 'documentArtId'); + return EN_EntityBeforeSaveCallBackResults.Ok_Continue; + } + + + public save = () => { //because of calling as callback of cancel + this.pageLoadingService.startSpinner(); + this.departmentDetails.save((department: Department) => this.afterSave(department), null, () => this.pageLoadingService.hideSpinner()); + } + + afterSave(department: Department) { + // this.departmentDetails.loadDetails(this.catalogDataService.departmentCategoryList); + + } + + public cancel = () => { + // this.setCurrentMaster4Subdepartment = null; + this.departmentDetails.cancelWithSave(this.save); + } + + + @HostListener('window:keydown', ['$event']) + keyboardInput(event: any) { + return LoginPopupComponent.LOGIN_IS_SHOWN || this.departmentDetails.shortcutsHandler(event, this.save, this.cancel); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.html new file mode 100644 index 0000000..cd7a5fd --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.html @@ -0,0 +1,21 @@ +
+ + + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.scss new file mode 100644 index 0000000..05fa790 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.scss @@ -0,0 +1,19 @@ +.department-documentart { + width: 100%; + height: 100%; + display: grid; + grid-template-columns: minmax(0, 1fr); // column relationship + grid-template-rows: 0 minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label" "attributes"; +} + + +.documentart { + grid-area: attributes; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.ts new file mode 100644 index 0000000..b8879e1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-documentart/department-documentart.component.ts @@ -0,0 +1,28 @@ + + +import { Component, OnInit, Input } from '@angular/core'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { Department } from '@app_models/basedata/department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; + +@Component({ + selector: 'app-department-documentart', + templateUrl: './department-documentart.component.html', + styleUrls: ['./department-documentart.component.scss'] +}) + +export class DepartmentDocumentartsComponent implements OnInit { + + @Input() public departmentDetails: AppBaseEntityWrapper; + + constructor( + public appDataService: AppDataService, + public departmentDataService: DepartmentDataService, + ) { + } + + ngOnInit() { + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.html new file mode 100644 index 0000000..2234b0c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.html @@ -0,0 +1,35 @@ +
+ +

{{description}} - {{keyItemName}}

+ + +
+ + +
+ + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.scss new file mode 100644 index 0000000..7eef6e2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.scss @@ -0,0 +1,24 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto; // row relationships + grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'input-windreamSearch .' + 'buttons buttons' +} + +.input-windreamSearch { + grid-area: input-windreamSearch; +} + +.input-seq { + grid-area: input-seq; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.ts new file mode 100644 index 0000000..b2c00ef --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component.ts @@ -0,0 +1,57 @@ +import { Component, ViewChild } from '@angular/core'; +import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component'; +import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component'; +import { WindreamIndex } from '@app_models/windream-index'; +import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; + +@Component({ + selector: 'app-department-windream-index-popupedit', + templateUrl: './department-windream-index-popupedit.component.html', + styleUrls: ['./department-windream-index-popupedit.component.scss'] +}) +export class DepartmentWindreamIndexPopupeditComponent extends PopupBaseComponent { + + public windreamIndexIds: number[] = []; + @ViewChild('input_windreamIndex') input_windreamIndex: HenselSelectionComponent; + + constructor( + public departmentDataService: DepartmentDataService, + ) { + super(); + this.departmentDataService.windreamIndexList.load(); + } + + + public get windreamIndexList(): WindreamIndex[] { + return this.departmentDataService.windreamIndexList.items; + } + + public get focusedItem(): WindreamIndexToWindreamSearchToDepartment { + return (this._focusedItem); + } + + getNotUsedwindreamIndexes = (dep: WindreamIndex) => { + return !this.list.items.find((item) => item['windreamIndexId'] === dep.entityId); + } + + save = () => { + let maxSeq = this.list.items.reduce((max: number, _index: WindreamIndexToWindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0); + // for each selected WindreamIndexIds + this.windreamIndexIds.forEach(windreamIndexId => { + // create new WindreamIndexMap Item + const newWindreamIndex = new WindreamIndexToWindreamSearchToDepartment(); + // calculate highest seq + newWindreamIndex.seq = ++maxSeq; + newWindreamIndex.windreamIndexId = windreamIndexId; + newWindreamIndex.windreamSearchToDepartmentId = this.focusedItem.windreamSearchToDepartmentId; + newWindreamIndex.entityChanged = true; + this.list.items.push(newWindreamIndex); + }); + this.list.save(() => { + this.baseEntityWrapper.resetEditMode(); + this.close(true); + }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.html new file mode 100644 index 0000000..c71a7da --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.html @@ -0,0 +1,115 @@ +
+ +
+
+
+ + + + + + + +
+
+
+ + + + --> + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.scss new file mode 100644 index 0000000..192008c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.scss @@ -0,0 +1,23 @@ +.department-windreamsearch-windreamindex{ + width: 100%; + height: 100%; + display: grid; + grid-template-columns: auto minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label label" "toolbar grid"; +} + +.grid { + grid-area: grid; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; + // padding-bottom: 6px; +} + +.toolbar { + grid-area: toolbar; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.spec.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.spec.ts new file mode 100644 index 0000000..1e3e321 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentWindreamIndexComponent } from './department-windream-index.component'; + +describe('DepartmentWindreamIndexComponent', () => { + let component: DepartmentWindreamIndexComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DepartmentWindreamIndexComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentWindreamIndexComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.ts new file mode 100644 index 0000000..6d0d1bb --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-index/department-windream-index.component.ts @@ -0,0 +1,101 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Department } from '@app_models/basedata/department'; +import { WindreamIndexToWindreamSearchToDepartment } from '@app_models/windream-index-to-windream-search-to-department'; +import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { DepartmentWindreamIndexPopupeditComponent } from './department-windream-index-popupedit/department-windream-index-popupedit.component'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { MatDialogService } from '@app_core/services/mat-dialog.service'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Globals } from '@app_core/services/globals'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-department-windream-index', + templateUrl: './department-windream-index.component.html', + styleUrls: ['./department-windream-index.component.scss'] +}) +export class DepartmentWindreamIndexComponent implements OnInit { + @Input() windreamIndexList: AppBaseEntityListWrapper; + @Input() windreamIndexDetails: AppBaseEntityWrapper; + @Input() windreamSearchToDepartmentDetails: AppBaseEntityWrapper; + @Input() departmentDetails: AppBaseEntityWrapper; + + + public get windreamSearchName(): string { + return this.windreamSearchToDepartmentDetails.entity.windreamSearchName; + } + + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + constructor( + private dialog: MatDialogService, + public departmentDataService: DepartmentDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + initColumns() { + let col: ColumnConfig; + col = this.columnConfigList.add('Seq.', 'seq', 2); + col.sortIndex = 0; + col.sortOrder = EN_SortOrder.asc; + col = this.columnConfigList.add('Ausgabespalte', 'objectTypeAttributeSzName', 15); + col = this.columnConfigList.add('Indexname', 'attributeSzColumnName', 15); + this.columnConfigList.recalcWidth(); + } + + addItem() { + this.windreamIndexList.focusedEntityShadowed.new(); + this.windreamIndexList.focusedEntityShadowed.entity.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId; + this.openPopupDialog(this.windreamIndexList.focusedEntityShadowed); + } + + public openPopupDialog(editEntity: AppBaseEntityWrapper) { + this.windreamSearchToDepartmentDetails.keyDownListenerStopped = true; + this.dialog.openDialog(DepartmentWindreamIndexPopupeditComponent, { + baseEntityWrapper: editEntity, + keyItemName: this.windreamSearchToDepartmentDetails.entity.windreamSearchName, + readOnly: !this.departmentDetails.inEditMode, + description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '), + list: this.windreamIndexList, + }, true, () => this.windreamSearchToDepartmentDetails.keyDownListenerStopped = false); + } + + + private outColKeyItemDescription() { + return `Ausgabespalten für "${this.windreamSearchToDepartmentDetails.entity.windreamSearchName}" Abteilung "${this.departmentDetails.entity.departmentName}"`; + + } + + public copyWindreamOutCols() { + this.departmentDataService.clpbrdWindreamOutColList = this.windreamIndexList.items.slice(); + this.departmentDataService.clpbrdWindreamOutColHint1 = this.outColKeyItemDescription(); + this.departmentDataService.clpbrdWindreamOutColHints = ''; + this.departmentDataService.clpbrdWindreamOutColList.forEach(col => + this.departmentDataService.clpbrdWindreamOutColHints += '\n' + col.objectTypeAttributeSzName); + } + + + public pasteWindreamOutCols() { + this.windreamIndexDetails.confirmMessageBoxYesNo('Übernahme von ' + this.departmentDataService.clpbrdWindreamOutColHint1, this.outColKeyItemDescription() + ' werden mit ' + this.departmentDataService.clpbrdWindreamOutColHint1 + ' überschrieben. Sind Sie sicher?', + () => { + this.windreamIndexList.deleteAll(); + this.windreamIndexList.items.push(...this.departmentDataService.clpbrdWindreamOutColList); + this.windreamIndexList.items.forEach(el => { + el.entityId = 0; + el.entityChanged = true; + el.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId; + }); + this.windreamIndexList.save(); + } + ); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.html new file mode 100644 index 0000000..ccfc9ea --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.html @@ -0,0 +1,34 @@ +
+ +

{{description}} - {{keyItemName}}

+ + +
+ + +
+ + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.scss new file mode 100644 index 0000000..7eef6e2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.scss @@ -0,0 +1,24 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto; // row relationships + grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'input-windreamSearch .' + 'buttons buttons' +} + +.input-windreamSearch { + grid-area: input-windreamSearch; +} + +.input-seq { + grid-area: input-seq; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.ts new file mode 100644 index 0000000..a715795 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component.ts @@ -0,0 +1,57 @@ +import { Component } from '@angular/core'; +import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component'; +import { WindreamSearchItem } from '@app_models/windream-search-item'; +import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; + +@Component({ + selector: 'app-department-windream-search-item-popupedit', + templateUrl: './department-windream-search-item-popupedit.component.html', + styleUrls: ['./department-windream-search-item-popupedit.component.scss'] +}) +export class DepartmentWindreamSearchItemPopupeditComponent extends PopupBaseComponent { + + public windreamSearchItemIds: number[] = []; + + constructor( + public departmentDataService: DepartmentDataService, + ) { + super(); + this.departmentDataService.windreamSearchItemList.load(); + this.getNotUsedwindreamSearchItems = this.getNotUsedwindreamSearchItems.bind(this); + } + + + public get windreamSearchItemList(): WindreamSearchItem[] { + return this.departmentDataService.windreamSearchItemList.items; + } + + public get focusedItem(): WindreamSearchItemToWindreamSearchToDepartment { + return (this._focusedItem); + } + + getNotUsedwindreamSearchItems(dep: WindreamSearchItem) { + return !this.list.items.find((item) => item['windreamSearchItemId'] === dep.entityId); + } + + + save = () => { + let maxSeq = this.list.items.reduce((max: number, _index: WindreamSearchItemToWindreamSearchToDepartment) => max > _index.seq ? max : _index.seq, 0); + // for each selected WindreamIndexIds + this.windreamSearchItemIds.forEach(windreamSearchItemId => { + // create new WindreamIndexMap Item + const newWindreamItem = new WindreamSearchItemToWindreamSearchToDepartment(); + // calculate highest seq + newWindreamItem.seq = ++maxSeq; + newWindreamItem.windreamSearchItemId = windreamSearchItemId; + newWindreamItem.windreamSearchToDepartmentId = this.focusedItem.windreamSearchToDepartmentId; + newWindreamItem.entityChanged = true; + this.list.items.push(newWindreamItem); + }); + this.list.save(() => { + this.baseEntityWrapper.resetEditMode(); + this.close(true); + }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.html new file mode 100644 index 0000000..17128fb --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.html @@ -0,0 +1,117 @@ +
+ +
+
+
+ + + + + + + +
+
+
+ + + + --> + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.scss new file mode 100644 index 0000000..192008c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.scss @@ -0,0 +1,23 @@ +.department-windreamsearch-windreamindex{ + width: 100%; + height: 100%; + display: grid; + grid-template-columns: auto minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label label" "toolbar grid"; +} + +.grid { + grid-area: grid; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; + // padding-bottom: 6px; +} + +.toolbar { + grid-area: toolbar; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.spec.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.spec.ts new file mode 100644 index 0000000..030ac44 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { DepartmentWindreamSearchItemComponent } from './department-windream-search-item.component'; + + +describe('DepartmentWindreamIndexComponent', () => { + let component: DepartmentWindreamSearchItemComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [DepartmentWindreamSearchItemComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentWindreamSearchItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.ts new file mode 100644 index 0000000..ed9faf3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search-item/department-windream-search-item.component.ts @@ -0,0 +1,94 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Department } from '@app_models/basedata/department'; +import { WindreamSearchItemToWindreamSearchToDepartment } from '@app_models/windream-search-item-to-windream-search-to-department'; +import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { DepartmentWindreamSearchItemPopupeditComponent } from './department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { MatDialogService } from '@app_core/services/mat-dialog.service'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Globals } from '@app_core/services/globals'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-department-windream-search-item', + templateUrl: './department-windream-search-item.component.html', + styleUrls: ['./department-windream-search-item.component.scss'] +}) +export class DepartmentWindreamSearchItemComponent implements OnInit { + @Input() windreamSearchItemList: AppBaseEntityListWrapper; + @Input() windreamSearchItemDetails: AppBaseEntityWrapper; + @Input() windreamSearchToDepartmentDetails: AppBaseEntityWrapper; + @Input() departmentDetails: AppBaseEntityWrapper; + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + constructor( + private dialog: MatDialogService, + public departmentDataService: DepartmentDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + initColumns() { + let col: ColumnConfig; + col = this.columnConfigList.add('Seq.', 'seq', 2); + col.sortIndex = 0; + col.sortOrder = EN_SortOrder.asc; + col = this.columnConfigList.add('Suchbaustein', 'windreamSearchItemName', 10); + this.columnConfigList.recalcWidth(); + } + + addItem() { + this.windreamSearchItemList.focusedEntityShadowed.new(); + this.windreamSearchItemList.focusedEntityShadowed.entity.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId; + this.openPopupDialog(this.windreamSearchItemList.focusedEntityShadowed); + } + + public openPopupDialog(editEntity: AppBaseEntityWrapper) { + this.windreamSearchToDepartmentDetails.keyDownListenerStopped = true; + this.dialog.openDialog(DepartmentWindreamSearchItemPopupeditComponent, { + baseEntityWrapper: editEntity, + keyItemName: this.windreamSearchToDepartmentDetails.entity._name, + readOnly: !this.departmentDetails.inEditMode, + description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '), + list: this.windreamSearchItemList, + }, true, () => this.windreamSearchToDepartmentDetails.keyDownListenerStopped = false); + } + + + private outColKeyItemDescription() { + return `Suchfelder für "${this.windreamSearchToDepartmentDetails.entity.windreamSearchName}" Abteilung "${this.departmentDetails.entity.departmentName}"`; + } + + + public copyWindreamOutCols() { + this.departmentDataService.clpbrdWindreamSearchItemList = this.windreamSearchItemList.items.slice(); + this.departmentDataService.clpbrdWindreamSearchItemHint1 = this.outColKeyItemDescription(); + this.departmentDataService.clpbrdWindreamSearchItemHints = ''; + this.departmentDataService.clpbrdWindreamSearchItemList.forEach(col => + this.departmentDataService.clpbrdWindreamSearchItemHints += '\n' + col.windreamSearchItemName); + } + + + public pasteWindreamOutCols() { + this.windreamSearchItemDetails.confirmMessageBoxYesNo('Übernahme von ' + this.departmentDataService.clpbrdWindreamSearchItemHint1, this.outColKeyItemDescription() + ' werden mit ' + this.departmentDataService.clpbrdWindreamSearchItemHint1 + ' überschrieben. Sind Sie sicher?', + () => { + this.windreamSearchItemList.deleteAll(); + this.windreamSearchItemList.items.push(...this.departmentDataService.clpbrdWindreamSearchItemList); + this.windreamSearchItemList.items.forEach(el => { + el.entityId = 0; + el.entityChanged = true; + el.windreamSearchToDepartmentId = this.windreamSearchToDepartmentDetails.entityId; + }); + this.windreamSearchItemList.save(); + } + ); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.html new file mode 100644 index 0000000..4e8e8b3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.html @@ -0,0 +1,37 @@ +
+ +

{{description}} - {{keyItemName}}

+ + + +
+ + +
+ + + + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.scss new file mode 100644 index 0000000..877b92d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.scss @@ -0,0 +1,20 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto; // row relationships + grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'input-windreamSearch .' + 'buttons buttons' +} + +.input-windreamSearch { + grid-area: input-windreamSearch; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.spec.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.spec.ts new file mode 100644 index 0000000..574baa9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentWindreamSearchPopupeditComponent } from './department-windream-search-popupedit.component'; + +describe('DepartmentWindreamSearchPopupeditComponent', () => { + let component: DepartmentWindreamSearchPopupeditComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DepartmentWindreamSearchPopupeditComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentWindreamSearchPopupeditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.ts new file mode 100644 index 0000000..99976c2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component.ts @@ -0,0 +1,34 @@ +import { Component } from '@angular/core'; +import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component'; +import { WindreamSearch } from '@app_models/windream-search'; +import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; + +@Component({ + selector: 'app-department-windream-search-popupedit', + templateUrl: './department-windream-search-popupedit.component.html', + styleUrls: ['./department-windream-search-popupedit.component.scss'] +}) +export class DepartmentWindreamSearchPopupeditComponent extends PopupBaseComponent { + + constructor( + public departmentDataService: DepartmentDataService, + ) { + super(); + this.departmentDataService.windreamSearchList.load(); + } + + + public get windreamSearchList(): WindreamSearch[] { + return this.departmentDataService.windreamSearchList.items; + } + + public get focusedItem(): WindreamSearchToDepartment { + return (this._focusedItem); + } + + getNotUsedWindreamSearches = (dep: WindreamSearch) => { + return !this.list.items.find((item) => item['windreamSearchId'] === dep.entityId); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.html new file mode 100644 index 0000000..dae5a17 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.html @@ -0,0 +1,113 @@ +
+ +
+
+
+ + + + + + + +
+
+
+ + + + --> + + + + + + + + + + + + + + + +
+ +
+
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.scss new file mode 100644 index 0000000..15a776e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.scss @@ -0,0 +1,23 @@ +.department-windreamsearch { + width: 100%; + height: 100%; + display: grid; + grid-template-columns: auto minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label label" "toolbar grid"; +} + +.grid { + grid-area: grid; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; + // padding-bottom: 6px; +} + +.toolbar { + grid-area: toolbar; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.spec.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.spec.ts new file mode 100644 index 0000000..8ae40b5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DepartmentWindreamSearchComponent } from './department-windream-search.component'; + +describe('DepartmentWindreamSearchComponent', () => { + let component: DepartmentWindreamSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DepartmentWindreamSearchComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DepartmentWindreamSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.ts new file mode 100644 index 0000000..669dfb2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/department-windream-search.component.ts @@ -0,0 +1,121 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { EN_AppEntities } from '@app_consts'; +import { Department } from '@app_models/basedata/department'; +import { WindreamSearchToDepartment } from '@app_models/windream-search-to-department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { DepartmentWindreamSearchPopupeditComponent } from './department-windream-search-popupedit/department-windream-search-popupedit.component'; +import { SelectDepartmentPopupComponent } from './select-department-popup/select-department-popup.component'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { MatDialogService } from '@app_core/services/mat-dialog.service'; +import { RepositoryService } from '@app_core/services/http/repository.service'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Globals } from '@app_core/services/globals'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-department-windream-search', + templateUrl: './department-windream-search.component.html', + styleUrls: ['./department-windream-search.component.scss'] +}) +export class DepartmentWindreamSearchComponent implements OnInit { + + @Input() windreamSearchList: AppBaseEntityListWrapper; + @Input() departmentDetails: AppBaseEntityWrapper; + + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + + constructor( + private dialog: MatDialogService, + public departmentDataService: DepartmentDataService, + public repoService: RepositoryService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + + initColumns() { + let col: ColumnConfig; + col = this.columnConfigList.addNumber('Seq.', 'seq', 2); + col.sortIndex = 0; + col.sortOrder = EN_SortOrder.asc; + col = this.columnConfigList.add('Suche Kachel', 'windreamSearchName', 10); + col = this.columnConfigList.addBoolean('Active', 'isActive', 2); + col.cellTemplate = 'checkbox_template'; + this.columnConfigList.recalcWidth(); + } + + addItem() { + this.windreamSearchList.focusedEntityShadowed.new(); + this.windreamSearchList.focusedEntityShadowed.entity.departmentId = this.departmentDetails.entityId; + this.openPopupDialog(this.windreamSearchList.focusedEntityShadowed); + } + + public openPopupDialog(editEntity: AppBaseEntityWrapper) { + this.departmentDetails.keyDownListenerStopped = true; + this.dialog.openDialog(DepartmentWindreamSearchPopupeditComponent, { + baseEntityWrapper: editEntity, + keyItemName: this.departmentDetails.entity.departmentName, + readOnly: !this.departmentDetails.inEditMode, + description: editEntity.entity.entitytitle + (editEntity.entity.entityId === 0 ? ' zuweisen' : ' bearbeiten '), + list: this.windreamSearchList, + }, true, () => this.departmentDetails.keyDownListenerStopped = false); + } + + + public get nameOfDepartment(): string { + return this.departmentDetails.entity.departmentName; + } + + + public changeKeyWS(wsTD: WindreamSearchToDepartment) { + if (this.departmentDetails.inEditMode) { + wsTD.isActive = !wsTD.isActive; + wsTD.entityChanged = true; + wsTD.save(this.repoService, null); + } + } + + + public copyAllTiles() { + this.openSelectDepartmentsPopup(`Wählen Sie Abteilungen, bei welchen alle Suchkacheln von Suchkacheln aus "${this.departmentDetails.entity.departmentName}" ersetzt werden sollen` + , 'content_copy' + , (depIds: number[]) => { + this.repoService.putDataById(EN_AppEntities.DepartmentCopyWindreamTiles, this.departmentDetails.entityId, depIds).subscribe( + () => this.departmentDetails.informationMessageBox('Kopieren von Suchkacheln', `Die Suchkacheln aus "${this.departmentDetails.entity.departmentName}" haben Suchkacheln aus den ausgewählten Abteilungen erfolgreich ersetzt`) + ); + } + ); + } + + + public copyCurrentTile() { + this.openSelectDepartmentsPopup(`Wählen Sie Abteilungen, für welche die Suchkachel "${this.windreamSearchList.focusedItem.windreamSearchName}" aus "${this.departmentDetails.entity.departmentName}" hinzugefügt werden soll` + , 'content_copy' + , (depIds: number[]) => { + this.repoService.putDataById(EN_AppEntities.WindreamSearchToDepartmentCopyWindreamTile, this.windreamSearchList.focusedItemId, depIds).subscribe( + () => this.departmentDetails.informationMessageBox('Kopieren von Suchkacheln', `Die Suchkachel "${this.windreamSearchList.focusedItem.windreamSearchName}" aus "${this.departmentDetails.entity.departmentName}" wurde zu den ausgewählten Abteilungen erfolgreich hinzugefügt`) + ); + } + ); + } + + + public openSelectDepartmentsPopup(text: string, iconanme: string, callBack: (depIds: number[]) => void) { + this.departmentDetails.keyDownListenerStopped = true; + this.dialog.openDialog(SelectDepartmentPopupComponent + , { text: text, iconanme: iconanme } + , true + , (result) => { + if (result && callBack) callBack(result); + this.departmentDetails.keyDownListenerStopped = false; + }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.html new file mode 100644 index 0000000..c15b83e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.html @@ -0,0 +1,40 @@ +
+

+ {{iconanme}} + Windreameinstellungen übernehmen +

+
+ {{text}} +
+ + +
+ + +
+ + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.scss new file mode 100644 index 0000000..a28252a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.scss @@ -0,0 +1,21 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto auto; // row relationships + grid-template-columns: repeat(2, minmax(0, 1fr)); // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'text text' + 'input-departments input-departments' + 'buttons buttons' +} + +.input-departments { + grid-area: input-departments; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.ts new file mode 100644 index 0000000..729485e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-detail/department-windream-search/select-department-popup/select-department-popup.component.ts @@ -0,0 +1,25 @@ +import { Component, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA } from '@app_core/components/angular-material-index'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; + +@Component({ + selector: 'app-select-department-popup', + templateUrl: './select-department-popup.component.html', + styleUrls: [ './select-department-popup.component.scss'] +}) + +export class SelectDepartmentPopupComponent { + + public selectedDepartments: number[] = []; + public text: string; + public iconanme: string; + + constructor( + public departmentDataService: DepartmentDataService, + @Inject(MAT_DIALOG_DATA) data: any + ) { + this.text = data.text; + this.iconanme = data.iconanme; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.html new file mode 100644 index 0000000..db76289 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.html @@ -0,0 +1,24 @@ + + + + + + + + +
+ + + + +
+ +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.scss new file mode 100644 index 0000000..85d3855 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.scss @@ -0,0 +1,49 @@ +.filterCardContainer { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-column-gap: 15px; + grid-template-rows: repeat(1, auto); // row relationships + grid-template-columns: repeat(5, minmax(0, 1fr)) auto; // column relationship + grid-template-areas: + "filterDepartment . . . . filterButtons" +} + +// @media screen and (max-width:1024px) { +// .woassays { +// font-size: 1vw; +// } +// } + +.filterDepartment { + grid-area: filterDepartment; +} + +.filterButtons { + grid-area: filterButtons; + margin-left: auto; +} + +// .filterBtn { +// font-size: 1vw; //scales buttons caption depended from the current view port resolution +// } + +.card { + padding: 10px; + margin: 2px 2px 0px 2px; +} + +.filterBtn { + margin-left: 2px; + margin-right: 2px; + margin-right: 1px; + margin-top: 6px; + width: 90px; +} + +// .filterButtons .filterBtn { +// width: unset; +// } diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.ts new file mode 100644 index 0000000..c9538fa --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-filter/department-filter.component.ts @@ -0,0 +1,61 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core'; +import { Department, DepartmentFilter } from '@app_models/basedata/department'; +import { DepartmentDataService } from '@app_modules/department/department-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import * as Cnst from '@app_core/consts'; +import { AuthorizeService } from '@app_core/services/authorize.service'; +import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component'; + +@Component({ + selector: 'app-department-filter', + templateUrl: './department-filter.component.html', + styleUrls: ['./department-filter.component.scss'], +}) + +export class DepartmentFilterComponent implements OnInit, AfterViewInit { + + constructor( + public departmentDataService: DepartmentDataService, + public appDataService: AppDataService, + public authService: AuthorizeService, + ) { } + @Input() public filterObject: DepartmentFilter; + @Input() departmentDetails: AppBaseEntityWrapper; + @Output() public filterFetch = new EventEmitter(); + + public dropDownAllCaption = Cnst.EN_DropDownConst4Filter.AllCaption; + public dropDownAllValueString = Cnst.EN_DropDownConst4Filter.AllValueString; + public dropDownAllValueInt = Cnst.EN_DropDownConst4Filter.AllValueInt; + public allCaption = Cnst.EN_DropDownConst4Filter.AllCaption; + public allValue: number = Cnst.EN_DropDownConst4Filter.AllValueInt; + public noneCaption = Cnst.EN_DropDownConst4Filter.NoneCaption; + public noneValue = Cnst.EN_DropDownConst4Filter.NoneValueInt; + + ngOnInit() { } + ngAfterViewInit() { } + onFilterClick() { + if (this.departmentDetails.inViewMode) this.filterFetch.emit(); + } + onClearClick() { + this.filterObject.filterReset(); + } + + + @HostListener('window:keydown', ['$event']) + keyboardInput(event: any) { + if (!LoginPopupComponent.LOGIN_IS_SHOWN && !this.departmentDetails.keyDownListenerStopped) { + if (event.ctrlKey) { + switch (event.which) { + case keycode.F: //Ctrl + 'f' + event.stopPropagation(); + this.onFilterClick(); + return false; //processed + } + } + } + return true; //default processing + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.html new file mode 100644 index 0000000..a641df6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.html @@ -0,0 +1,86 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
+
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.scss new file mode 100644 index 0000000..4393ad5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.scss @@ -0,0 +1,39 @@ +.DepartmentList { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: auto minmax(0, 1fr); // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-row-gap: 7px; + grid-template-areas: + 'filter' + 'grid'; +} + + +.FilterComponent { + grid-area: filter; // grid area: auto height 1fr width + margin: 0 0 0 0; +} + + +.card { + grid-area: grid; + width: 100%; + padding: 0px; + margin: 0; + border-radius: 0px; + box-shadow: none; +} + +.gridDepartment { + position: absolute; // position absolut ist hier zwingend! Die position ist absolut innerhalb mehrerer parent divs und darf sich NICHT über diese hinausstrecken. + height: 100%; + width: 100%; + padding-left: 1px; + padding-right: 1px; + padding-bottom: 1px; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.ts new file mode 100644 index 0000000..9294269 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department-list/department-list.component.ts @@ -0,0 +1,59 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { Department } from '@app_models/basedata/department'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { DepartmentDataService } from '../department-data.service'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Globals } from '@app_core/services/globals'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-department-list', + templateUrl: './department-list.component.html', + styleUrls: ['./department-list.component.scss'] +}) +export class DepartmentListComponent implements OnInit { + @Input() public dataSource: AppBaseEntityListWrapper; + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + + + constructor( + public departmentDataService: DepartmentDataService, + public appDataService: AppDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + + initColumns() { + let col: ColumnConfig; + col = this.columnConfigList.addNumber('Id', 'departmentId', 5); + col = this.columnConfigList.add('Name', 'departmentName', 13); + col.sortIndex = 0; + col.sortOrder = EN_SortOrder.asc; + col.allowHeaderFiltering = true; + col = this.columnConfigList.addNumber('Typ Id', 'departmentTypeId', 5); + col = this.columnConfigList.addNumber('CostCentre Id', 'costCentreId', 5); + col = this.columnConfigList.add('CostCentre', 'costCentre', 10); + col = this.columnConfigList.add('Abteilungsleiter', 'headofDepartment', 18); + col = this.columnConfigList.add('CEO', 'executiveDirector', 18); + col = this.columnConfigList.add('COO', 'managingDirector', 18); + col = this.columnConfigList.add('Folder', 'departmentNameFolder', 13); + col = this.columnConfigList.add('AD-Group Name', 'adGroupDepartmentName', 13); + col = this.columnConfigList.addNumber('Client Id', 'clientId', 5); + col = this.columnConfigList.addBoolean('Virtual', 'isVirtual', 2); + this.columnConfigList.recalcWidth(); + } + + + public loadData() { + this.departmentDataService.loadData(); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department.component.html b/ClientApp/staff-db-ui/src/app/modules/department/department.component.html new file mode 100644 index 0000000..0e19c08 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department.component.html @@ -0,0 +1,7 @@ +
+ + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department.component.scss b/ClientApp/staff-db-ui/src/app/modules/department/department.component.scss new file mode 100644 index 0000000..90683e3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department.component.scss @@ -0,0 +1,22 @@ +.DepartmentComponent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: minmax(0, 1fr) auto; // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-template-areas: 'list''details'; + grid-column-gap: 5px; + grid-row-gap: 5px; +} + +.DepartmentListComponent { + grid-area: list; +} + +.DepartmentDetailsComponent { + grid-area: details; + z-index: 10; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department.component.ts b/ClientApp/staff-db-ui/src/app/modules/department/department.component.ts new file mode 100644 index 0000000..f0d3953 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; +import { DepartmentDataService } from './department-data.service'; + +@Component({ + selector: 'app-department', + templateUrl: './department.component.html', + styleUrls: ['./department.component.scss'] +}) +export class DepartmentComponent implements OnInit { + + constructor( + public departmentDataService: DepartmentDataService + ) { } + + ngOnInit() { + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department.module.ts b/ClientApp/staff-db-ui/src/app/modules/department/department.module.ts new file mode 100644 index 0000000..9bb8f89 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department.module.ts @@ -0,0 +1,57 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { AngularMaterialModule } from '@app_core/components/angular-material.module'; +import { DxButtonModule, DxDataGridModule, DxFileUploaderModule, DxPieChartModule, DxTemplateModule, DxTooltipModule } from 'devextreme-angular'; +import { DepartmentContentComponent } from './department-detail/department-content/department-content.component'; +import { DepartmentDetailComponent } from './department-detail/department-detail.component'; +import { DepartmentDocumentartsComponent as DepartmentDocumentArtComponent } from './department-detail/department-documentart/department-documentart.component'; +import { DepartmentWindreamIndexPopupeditComponent } from './department-detail/department-windream-index/department-windream-index-popupedit/department-windream-index-popupedit.component'; +import { DepartmentWindreamIndexComponent } from './department-detail/department-windream-index/department-windream-index.component'; +import { DepartmentWindreamSearchItemPopupeditComponent } from './department-detail/department-windream-search-item/department-windream-search-item-popupedit.component/department-windream-search-item-popupedit.component'; +import { DepartmentWindreamSearchItemComponent } from './department-detail/department-windream-search-item/department-windream-search-item.component'; +import { DepartmentWindreamSearchPopupeditComponent } from './department-detail/department-windream-search/department-windream-search-popupedit/department-windream-search-popupedit.component'; +import { DepartmentWindreamSearchComponent } from './department-detail/department-windream-search/department-windream-search.component'; +import { SelectDepartmentPopupComponent } from './department-detail/department-windream-search/select-department-popup/select-department-popup.component'; +import { DepartmentFilterComponent } from './department-list/department-filter/department-filter.component'; +import { DepartmentListComponent } from './department-list/department-list.component'; +import { DepartmentComponent } from './department.component'; +import { DepartmentRoutingModule } from './department.routing.module'; +import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component'; +import { HenselInputComponent } from '@app_core/components/hensel-input/hensel-input.component'; + + +@NgModule({ + declarations: [ + DepartmentComponent, + DepartmentListComponent, + DepartmentDetailComponent, + DepartmentFilterComponent, + DepartmentContentComponent, + DepartmentWindreamSearchComponent, + DepartmentWindreamSearchPopupeditComponent, + DepartmentWindreamSearchItemComponent, + DepartmentWindreamSearchItemPopupeditComponent, + DepartmentWindreamIndexComponent, + DepartmentDocumentArtComponent, + DepartmentWindreamIndexPopupeditComponent, + SelectDepartmentPopupComponent + ], + imports: [ + CommonModule, + DepartmentRoutingModule, + AngularMaterialModule, + DxDataGridModule, + FormsModule, + HenselSelectionComponent, + HenselInputComponent, + DxFileUploaderModule, + DxButtonModule, + DxTooltipModule, + DxTemplateModule, + DxPieChartModule, + ], + providers: [], + exports: [] +}) +export class DepartmentModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/department/department.routing.module.ts b/ClientApp/staff-db-ui/src/app/modules/department/department.routing.module.ts new file mode 100644 index 0000000..7e2514a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/department/department.routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { DepartmentComponent } from './department.component'; +import { AuthGuard } from '@app_core/services/authguard'; + +const routes: Routes = [ + { + path: '**', + component: DepartmentComponent, + canActivate: [AuthGuard] + }, +]; + + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class DepartmentRoutingModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio b/ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio new file mode 100644 index 0000000..057d656 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/Page1.drawio @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-data.service.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-data.service.ts new file mode 100644 index 0000000..f573dc5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-data.service.ts @@ -0,0 +1,167 @@ +import { Injectable } from '@angular/core'; +import { cnst_LoadedEntitiesExpiresInMs, EN_AppEntities, EN_AppPages, EN_HttpQueriesCount4Page } from '@app_consts'; +import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts'; +import { CoreUser } from '@app_core/models/coreuser'; +import { RepositoryService } from '@app_core/services/http/repository.service'; +import { UINotifierService } from '@app_core/services/notification/uinotifier.service'; +import { CorePageService } from '@app_core/services/page.service'; +import { Employee, EmployeeFilter, EmployeeFullFilter } from '@app_models/employee'; +import { EmployeeToAttribute } from '@app_models/employee-to-attribute'; +import { EmployeeToDepartment } from '@app_models/employee-to-department'; +import { EmployeeToWebApp } from '@app_models/employee-to-webapp'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; + +import { User } from '@app_models/user'; +import { EmployeeToWebAppFilter, WebAppToDepartment } from '@app_models/webapp-to-department'; +import { WebAppToWebAppAdditionalRole } from '@app_models/webapp-to-webappadditionalrole'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { AppBaseEntityCallBack } from 'src/app/shared/app.types'; + + +@Injectable({ providedIn: 'root' }) + +export class EmployeeDataService extends CorePageService { + protected appPage: EN_AppPages = EN_AppPages.Employee; + protected get appPageNoQueries() { return EN_HttpQueriesCount4Page.Employee; } + + // --- running data + employeeDetails: AppBaseEntityWrapper; + employeeList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Employee, 'Mitarbeiterliste', EN_AppEntities.Employee); + employeeFilter: EmployeeFullFilter = new EmployeeFullFilter('EmployeeFullFilter'); + employee2AllFilter: EmployeeFilter = new EmployeeFilter('EmployeeFilter'); + + employee2DepartmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(EmployeeToDepartment, 'Abteilungen von Mitarbeiter', EN_AppEntities.EmployeeToDepartment); + + employee2WebAppList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(EmployeeToWebApp, 'Applikationen von Mitarbeiter', EN_AppEntities.EmployeeToWebapp); + + employee2AttributeList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(EmployeeToAttribute, 'Merkmale von Mitarbeiter', EN_AppEntities.EmployeeToAttribute); + + constructor( + private appDataService: AppDataService, + private repositoryService: RepositoryService, + protected uiNotificationsService: UINotifierService + ) { + super(); + + this.employeeList.alwaysFocused = true; + this.employeeList.focusedCallBack = this.focusCallBack.bind(this); + this.employeeList.filter = this.employeeFilter; + + this.employeeDetails = this.employeeList.createFocusedShadowEntity(AppBaseEntityWrapper.EN_ViewMode); + this.employeeDetails.loadedDataExpiresInMs = cnst_LoadedEntitiesExpiresInMs; + + this.activateRouting4EntityList(this.employeeList); //we are using routing + this.baseEntityWrapperWaitLoading = this.employeeDetails; + + this.prepareDetailsList(this.employee2DepartmentList); + this.prepareDetailsList(this.employee2WebAppList); + + this.employeeDetails.detailItems.register(this.employee2DepartmentList, null, 'employeeId', /*() => this.employee2DepartmentList.focuseFirstItem()*/); + this.employeeDetails.detailItems.register(this.employee2WebAppList, null, 'employeeId'); + this.employeeDetails.detailItems.register(this.employee2AttributeList, null, 'employeeId'); + this.employee2WebAppList.batchInsert = false; + this.employee2WebAppList.beforeSaveCallBack = this.beforeSaveEmployee2WebAppList.bind(this); + this.employee2WebAppList.afterInsertCallBack = this.afterInsertEmployee2WebAppList.bind(this); + this.employee2AttributeList.filter = this.employee2AllFilter; + + this.loadBaseData(); + this.init(); + } + + async beforeSaveEmployee2WebAppList(entities: EmployeeToWebApp[]): Promise { + entities.forEach((entity: EmployeeToWebApp) => { + if (entity.entityChanged && !entity.isNew()) this.afterInsertEmployee2WebAppList(entity, null, false); + }); + this.employee2WebAppList.deletedItems.forEach((entity: EmployeeToWebApp) => { + entity.arExtendedDepartmentIdList = []; + entity.arAdditionalRoleIdList = []; + this.afterInsertEmployee2WebAppList(entity, null, false); + }); + return EN_EntityBeforeSaveCallBackResults.Ok_Continue; + } + + + afterInsertEmployee2WebAppList(entity: EmployeeToWebApp, callback?: AppBaseEntityCallBack, reloadEntity = true) { + if (entity) { + const filter = new EmployeeToWebAppFilter('EmployeeToWebAppFilter'); + filter.employeeToWebAppId = entity.employeeToWebAppId; + //to create wrapper not in the constructor we need to pass appLogsService, repositoryService, uiNotificationsService explicetely! + const departmentList = new AppBaseEntityListWrapper(WebAppToDepartment, 'Abteilungen für Mitarbeiterapplikation', EN_AppEntities.WebAppToDepartment, filter, this.appLogsService, this.repositoryService, this.uiNotificationsService); + const addRoleList = + new AppBaseEntityListWrapper(WebAppToWebAppAdditionalRole, 'Zusatzrole für Mitarbeiterapplikation', EN_AppEntities.WebAppToWebAppAdditionalRole, filter, this.appLogsService, this.repositoryService, this.uiNotificationsService); + + this._saveEmployee2WebAppSublists(entity + , departmentList + , 'arExtendedDepartmentIdList' + , 'departmentId' + , (result1) => { + this._saveEmployee2WebAppSublists(entity + , addRoleList + , 'arAdditionalRoleIdList' + , 'webAppAdditionalRoleId' + , (result2) => { if (reloadEntity && (result1 || result2)) entity.load(this.repositoryService, callback); else if (callback) callback(); } + ); + } + ); + } + } + + + private _saveEmployee2WebAppSublists(entity: EmployeeToWebApp, list: AppBaseEntityListWrapper, idListName: string, idName: string, callback?: (entity: boolean) => void) { + let result: boolean = false; + list.load(() => { + if (result = list.match2array(entity, 'employeeToWebAppId', idListName, idName)) { + list.save(() => { if (callback) callback(true); }, (err) => { if (callback) callback(true); }); + } else if (callback) callback(false); + }); + } + + + prepareDetailsList(list: AppBaseEntityListWrapper) { + list.createFocusedShadowEntity(); + list.filter = this.employee2AllFilter; + list.focusedEntityShadowed.dontLoadEntity = true; + list.focusedEntityShadowed.dontUpdateEntityDirectly = true; + list.focusedEntityShadowed.dontInsertEntityDirectly = true; + } + + + loadData() { + super.loadData(); + this.employeeList.load(null, null, () => this.pageLoadingService.updatePageLoadedCounters(this.appPage)); + } + + public loadBaseData() { + super.loadBaseData(EN_AppPages.Login, EN_HttpQueriesCount4Page.Login); + this.appDataService.loadData(() => this.pageLoadingService.updatePageLoadedCounters(EN_AppPages.Login)); + } + + + public focusCallBack(focusedItem: Employee) { + } + + + public clearData() { + super.clearData(); + this.employeeFilter.filterReset(); + this.employeeList.clear(); + } + + + protected onLoggedInOut(user: CoreUser) { + this.userChanged(new User(user)); + super.onLoggedInOut(user); + } + + private userChanged(user: User) { + if (this.authService.isLoggedIn()) { + this.employeeDetails.canNew = user.isMaster; + this.employeeDetails.canEdit = this.employeeDetails.canNew; + this.employeeDetails.canDelete = this.employeeDetails.canNew; + } + // this.globalsService.appPages[EN_AppPages.UserConfig].hidden = !user?.isMaster; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.html new file mode 100644 index 0000000..6578e33 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.html @@ -0,0 +1,20 @@ +
+ + + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.scss new file mode 100644 index 0000000..cb3da64 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.scss @@ -0,0 +1,20 @@ +.employee-attribute { + width: 100%; + height: 100%; + display: grid; + grid-template-columns: minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label""attributes"; +} + + +.attributes { + grid-area: attributes; + height: 100%; + width: calc(100% - 28px); + margin-left: 28px; +} + +.label { + grid-area: label; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.ts new file mode 100644 index 0000000..2dcf40c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-attribute/employee-attribute.component.ts @@ -0,0 +1,24 @@ + + +import { Component, OnInit, Input } from '@angular/core'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { Employee } from '@app_models/employee'; +import { AppDataService } from '@app_services/app.data.service'; + +@Component({ + selector: 'app-employee-attribute', + templateUrl: './employee-attribute.component.html', + styleUrls: ['./employee-attribute.component.scss'] +}) +export class EmployeeAttributeComponent implements OnInit { + + @Input() public employeeDetails: AppBaseEntityWrapper; + + constructor( + public appDataService: AppDataService, + ) { + } + ngOnInit() { + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.html new file mode 100644 index 0000000..859981b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.html @@ -0,0 +1,147 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aktiv + + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.scss new file mode 100644 index 0000000..71dc6c9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.scss @@ -0,0 +1,97 @@ + +.employeeDetailsContent { + // z-index: 10; + // position: relative; //otherwise z-index is not working + padding: 0 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-column-gap: 8px; + grid-template-columns: repeat(2, minmax(1px, 1fr)); // column relationship + grid-template-rows: repeat(7, 42px); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: + "input-employeeno input-title" + "input-salutation input-position" + "input-firstname input-rang" + "input-lastname input-mobilephoneno" + "input-shortname input-phoneno" + "input-loginname input-mandant" + "input-email input-isActive " + ; +} + +.input-isActive { + + margin-top: 12px; +grid-area: input-isActive; +} +.input-mandant { + grid-area: input-mandant; +} + +.input-employeeno { + grid-area: input-employeeno; +} + +.input-firstname { + grid-area: input-firstname; +} + +.input-lastname { + grid-area: input-lastname; +} + +.input-shortname { + grid-area: input-shortname; +} + +.input-loginname { + grid-area: input-loginname; +} + +.input-email { + grid-area: input-email; +} + +.input-salutation { + grid-area: input-salutation; +} + +.input-title { + grid-area: input-title; +} + +.input-position { + grid-area: input-position; +} + +.input-rang { + grid-area: input-rang; +} + +.input-email { + grid-area: input-email; +} + +.input-mobilephoneno { + grid-area: input-mobilephoneno; +} + +.input-phoneno { + grid-area: input-phoneno; +} + +.check-box { + margin-top: 13px; +} + +.card { + padding: 12px; + margin: 2px 2px 2px 2px; +} + +.abstand { + margin-right: 1px !important; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.ts new file mode 100644 index 0000000..2888af6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-content/employee-content.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit, Input, ViewChild, AfterViewInit } from '@angular/core'; +import { NgForm } from '@angular/forms'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { Employee } from '@app_models/employee'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AuthorizeService } from '@app_core/services/authorize.service'; +import { Globals } from '@app_core/services/globals'; + +@Component({ + selector: 'app-details-content', + templateUrl: './employee-content.component.html', + styleUrls: ['./employee-content.component.scss'], +}) +export class EmployeeContentComponent implements OnInit, AfterViewInit { + @Input() public employeeDetails: AppBaseEntityWrapper; + @ViewChild('detailForm') detailForm: NgForm; + + constructor( + public appDataService: AppDataService, + public employeeDataService: EmployeeDataService, + public authorizeService: AuthorizeService, + public globals: Globals + ) { } + + ngAfterViewInit(): void { + this.employeeDetails.detailForm = this.detailForm; + } + + ngOnInit() { } + + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.html new file mode 100644 index 0000000..415206d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.html @@ -0,0 +1,94 @@ +
+ +
+
+
+ + + +
+
+
+ + + + --> + + + + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.scss new file mode 100644 index 0000000..2492105 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.scss @@ -0,0 +1,23 @@ +.employee-department { + width: 100%; + height: 100%; + display: grid; + grid-template-columns: auto minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + grid-template-areas: "label label" "toolbar grid"; +} + +.grid { + grid-area: grid; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; + // padding-bottom: 6px; +} + +.toolbar { + grid-area: toolbar; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.ts new file mode 100644 index 0000000..98aa67c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.component.ts @@ -0,0 +1,103 @@ + + +import { Component, Input, OnInit } from '@angular/core'; +import { EN_EmployeeRang, EN_EmployeeStatus } from '@app_consts'; +import { Employee } from '@app_models/employee'; +import { EmployeeToDepartment } from '@app_models/employee-to-department'; +import { EmployeeToWebApp } from '@app_models/employee-to-webapp'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { EmployeeToDepartmentPopupeditComponent } from './employee-department.popupedit/employee-department.popupedit.component'; +import { MatDialogService } from '@app_core/services/mat-dialog.service'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Globals } from '@app_core/services/globals'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-employee-department', + templateUrl: './employee-department.component.html', + styleUrls: ['./employee-department.component.scss'] +}) + +export class EmployeeDepartmentComponent implements OnInit { + + @Input() employeeDepartmentList: AppBaseEntityListWrapper; + @Input() public employeeDetails: AppBaseEntityWrapper; + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + + constructor( + private dialog: MatDialogService, + public appDataService: AppDataService, + public employeeDataService: EmployeeDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + get emplDepDetails(): AppBaseEntityWrapper { + return this.employeeDepartmentList.focusedEntityShadowed; + } + + ngOnInit() { + this.initColumns(); + } + + initColumns() { + let col: ColumnConfig; + + if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0); + + col = this.columnConfigList.add('Name', 'departmentId', 25); + + col = this.columnConfigList.add('Status', 'employeeStatusId', 20); + col.sortIndex = 1; + col.sortOrder = EN_SortOrder.asc; + col = this.columnConfigList.add('Rang', 'rangId', 10); + + this.columnConfigList.recalcWidth(); + } + + addItem() { + this.emplDepDetails.new(); + this.emplDepDetails.entity.employeeId = this.employeeDetails.entityId; + const employeeStatusId = this.employeeDepartmentList.items.find(e2d => e2d.employeeStatusId === EN_EmployeeStatus.MainFunction) ? EN_EmployeeStatus.AdditionalFunction : EN_EmployeeStatus.MainFunction; + this.emplDepDetails.entity.employeeStatusId = employeeStatusId; + this.emplDepDetails.entity.rangId = EN_EmployeeRang.Mitarbeiter; + this.openPopupDialog(this.emplDepDetails); + } + + dblClick(event: any) { + if (!this.employeeDetails.entityIsLoading) this.employeeDepartmentList.focusedEntityShadowed.delayedEdit(event.data['entityId'], this.editItem); + } + + editItem = () => { + this.emplDepDetails.edit(); + this.openPopupDialog(this.emplDepDetails); + } + + public openPopupDialog(editEntity: AppBaseEntityWrapper) { + this.employeeDetails.keyDownListenerStopped = true; + this.dialog.openDialog(EmployeeToDepartmentPopupeditComponent, { + baseEntityWrapper: editEntity, + keyItemName: this.employeeDetails.entity.firstName + ' ' + this.employeeDetails.entity.lastName, + readOnly: !this.employeeDetails.inNotViewMode, + description: (editEntity.entity.entityId === 0 ? 'Neue Abteilung zuweisen' : 'Daten zur Abteilung "' + editEntity.entity.departmentName + '" bearbeiten '), + list: this.employeeDepartmentList, + }, true, () => this.employeeDetails.keyDownListenerStopped = false); + } + + + public deleteDepartment() { + let usedDepartmentIdsStr: string = ''; + this.employeeDataService.employee2WebAppList.items.forEach((e2w: EmployeeToWebApp) => usedDepartmentIdsStr += ',' + e2w.departmentId + ',' + e2w.arExtendedDepartmentIdList); + const usedDepartmentIdsList: string[] = usedDepartmentIdsStr.split(','); + if (usedDepartmentIdsList.indexOf('' + this.emplDepDetails.entity.departmentId) > -1) { + this.emplDepDetails.warningMessageBox(`Löschen von Abteilung <${this.emplDepDetails.entity.departmentName}>`, + 'Die Abteilung kann nicht gelöscht werden, weil sie zu einer Webapplikation zugewiesen ist'); + } else this.emplDepDetails.delete(); + } +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.html new file mode 100644 index 0000000..5f9cf47 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.html @@ -0,0 +1,68 @@ +
+ +

{{description}} - {{keyItemName}}

+ + + +
+ + +
+ + + + + + + + + + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.scss new file mode 100644 index 0000000..92caaa3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.scss @@ -0,0 +1,28 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto; // row relationships + grid-template-columns: repeat(3, minmax(0, 1fr)); // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'input-department input-emplstatus input-rang' + 'buttons buttons buttons' +} + +.input-department { + grid-area: input-department; +} + +.input-emplstatus { + grid-area: input-emplstatus; +} + +.input-rang { + grid-area: input-rang; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.ts new file mode 100644 index 0000000..6ec1f89 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; +import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component'; +import { Department } from '@app_models/basedata/department'; +import { EmployeeToDepartment } from '@app_models/employee-to-department'; +import { AppDataService } from '@app_services/app.data.service'; + +@Component({ + selector: 'app-employee-department-popupedit', + templateUrl: 'employee-department.popupedit.component.html', + styleUrls: ['employee-department.popupedit.component.scss'] +}) + +export class EmployeeToDepartmentPopupeditComponent extends PopupBaseComponent { + + constructor( + public appDataService: AppDataService, + ) { + super(); + } + + + public get focusedItem(): EmployeeToDepartment { + return (this._focusedItem); + } + + getNotUsedDepartments = (dep: Department) => { + return !this.list.items.find((item) => item['departmentId'] === dep.entityId); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.html new file mode 100644 index 0000000..3358f3b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.html @@ -0,0 +1,47 @@ +
+ + + + + +
+
+ + + + + +
+
+ + + + + + +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.scss new file mode 100644 index 0000000..0c1cf7e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.scss @@ -0,0 +1,48 @@ +.EmployeeDetails { + padding: 0; + margin: 0; + overflow: hidden; + display: grid; + width: 100%; + height: 100%; + grid-template-rows: 42px minmax(1px, 168px) minmax(1px, 120px); + grid-template-columns: auto minmax(1px, 1fr) minmax(1px, 1.8fr); + grid-row-gap: 6px; + grid-column-gap: 13px; + grid-template-areas: + 'toolbar department-grid webapps-grid' + 'detail department-grid webapps-grid ' + 'detail attribute-grid webapps-grid'; + z-index: 10; + position: relative; //otherwise z-index is not working +} + + +.DetailsContent { + grid-area: detail; +} + +.DepartmentList { + grid-area: department-grid; +} + +.WebAppList { + grid-area: webapps-grid; +} + +.AttributeList { + grid-area: attribute-grid; +} + +.abstand { + margin-right: 1px !important; +} + +.toolbar { + grid-area: toolbar; +} + +.card { + padding: 12px; + margin: 2px 2px 2px 2px; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.ts new file mode 100644 index 0000000..7954b38 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-detail.component.ts @@ -0,0 +1,71 @@ +import { AfterViewInit, Component, HostListener, Input } from '@angular/core'; +import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component'; +import { EN_EntityBeforeSaveCallBackResults } from '@app_core/consts'; +import { AuthorizeService } from '@app_core/services/authorize.service'; +import { PageLoadingService } from '@app_core/services/pageloading.service'; +import { Employee } from '@app_models/employee'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; + +@Component({ + selector: 'app-employee-detail', + templateUrl: './employee-detail.component.html', + styleUrls: ['./employee-detail.component.scss'], +}) +export class EmployeeDetailComponent implements AfterViewInit { + @Input() public employeeDetails: AppBaseEntityWrapper; + + constructor( + public employeeDataService: EmployeeDataService, + public authorizeService: AuthorizeService, + private pageLoadingService: PageLoadingService, + ) { + } + + public get focusedItem(): Employee { + return this.employeeDetails.entity; + } + + ngAfterViewInit(): void { + this.employeeDetails.beforeNewCallBack = this.newEmployeeInit.bind(this); + this.employeeDetails.beforeSaveCallBack = this.beforeSaveEmployee.bind(this); + } + + newEmployeeInit(employee: Employee) { + /* employee.createdOn = new Date(); + employee.createdBy = this.authorizeService.user.userCode; + employee.changedOn = employee.createdOn; + employee.changedBy = employee.createdBy;*/ + } + + async beforeSaveEmployee(employee: Employee): Promise { + this.employeeDataService.employee2AttributeList.match2array(employee, 'employeeId', 'arAttributeIdList', 'employeeAttributeId'); + return EN_EntityBeforeSaveCallBackResults.Ok_Continue; + } + + + public save = () => { //because of calling as callback of cancel + this.pageLoadingService.startSpinner(); + this.employeeDetails.save((employee: Employee) => this.afterSave(employee), null, () => this.pageLoadingService.hideSpinner()); + } + + afterSave(employee: Employee) { + // this.employeeDetails.loadDetails(this.catalogDataService.employeeCategoryList); + + } + + public cancel = () => { + // this.setCurrentMaster4Subemployee = null; + this.employeeDetails.cancelWithSave(this.save); + } + + public add(){ + this.employeeDetails.new(); + this.employeeDetails.entity.isActive = true; + } + @HostListener('window:keydown', ['$event']) + keyboardInput(event: any) { + return LoginPopupComponent.LOGIN_IS_SHOWN || this.employeeDetails.shortcutsHandler(event, this.save, this.cancel); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.html new file mode 100644 index 0000000..6d2c961 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.html @@ -0,0 +1,96 @@ +
+ +
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.scss new file mode 100644 index 0000000..1d9bd55 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.scss @@ -0,0 +1,24 @@ +.employee-webapp { + width: 100%; + height: 100%; + display: grid; + grid-template-columns: auto minmax(0, 1fr); // column relationship + grid-template-rows: auto minmax(1px, 1fr); // auto auto auto auto auto auto auto auto auto; // row relationships + // grid-template-areas: "label""toolbar""grid"; + grid-template-areas: "label label" "toolbar grid"; + } + +.grid { + grid-area: grid; + height: 100%; + width: 100%; +} + +.label { + grid-area: label; + // padding-bottom: 6px; +} + +.toolbar { + grid-area: toolbar; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.ts new file mode 100644 index 0000000..8693e5c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.component.ts @@ -0,0 +1,124 @@ + + +import * as keycode from '@angular/cdk/keycodes'; +import { Component, HostListener, Input, OnInit } from '@angular/core'; +import { EN_EmployeeStatus } from '@app_consts'; +import { ColumnConfig, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { Globals } from '@app_core/services/globals'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { MatDialogService } from '@app_core/services/mat-dialog.service'; +import { Employee } from '@app_models/employee'; +import { EmployeeToDepartment } from '@app_models/employee-to-department'; +import { EmployeeToWebApp } from '@app_models/employee-to-webapp'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { EmployeeToWebAppPopupeditComponent } from './employee-webapp.popupedit/employee-webapp.popupedit.component'; + + +@Component({ + selector: 'app-employee-webapp', + templateUrl: './employee-webapp.component.html', + styleUrls: ['./employee-webapp.component.scss'] +}) + +export class EmployeeWebappComponent implements OnInit { + + public get employeeWebappList(): AppBaseEntityListWrapper { + return this.employeeDataService.employee2WebAppList; + } + + @Input() public employeeDetails: AppBaseEntityWrapper; + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + + constructor( + private dialog: MatDialogService, + public employeeDataService: EmployeeDataService, + public appDataService: AppDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + + initColumns() { + let col: ColumnConfig; + + if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0); + col = this.columnConfigList.add('Webapp', 'webAppName', 15); + // col = this.columnConfigList.addId('Webapp', 'webAppId', 15); + // col.calculateSortValue = 'webAppName'; + col.sortIndex = 1; + col.sortOrder = EN_SortOrder.asc; + + col = this.columnConfigList.add('Abteilung', 'departmentName', 20); + // col = this.columnConfigList.add('Abteilung', 'departmentId', 20); + // col.calculateSortValue = 'departmentName'; + col = this.columnConfigList.add('Role', 'webAppRoleName', 15); + // col = this.columnConfigList.add('Role', 'webAppRoleId', 15); + // col.calculateSortValue = 'webAppRoleName'; + col = this.columnConfigList.add('Zusatzabteilungen', 'extendedDepartmentNameList', 30); + col = this.columnConfigList.add('Zusatzrolen', 'additionalRoleNameList', 30); + this.columnConfigList.recalcWidth(); + } + + addItem() { + this.employeeWebappList.focusedEntityShadowed.new(); + this.employeeWebappList.focusedEntityShadowed.entity.employeeId = this.employeeDetails.entityId; + if (this.employeeDataService.employee2DepartmentList.items.length > 0) { + let mainDepId: number = 0; + const addDepIds: number[] = []; + let addDepNames = ''; + this.employeeDataService.employee2DepartmentList.items.forEach((e2d: EmployeeToDepartment) => { + if (e2d.employeeStatusId === EN_EmployeeStatus.MainFunction) { + if (mainDepId === 0) mainDepId = e2d.departmentId; + } else { + addDepIds.push(e2d.departmentId); + const depname = this.appDataService.departmentList?.items.find(dep => dep.entityId === e2d.departmentId)?.departmentName; + addDepNames += depname ? depname + ', ' : ''; + } + }); + if (mainDepId > 0) this.employeeWebappList.focusedEntityShadowed.entity.departmentId = mainDepId; + this.employeeWebappList.focusedEntityShadowed.entity.arExtendedDepartmentIdList = addDepIds; + this.employeeWebappList.focusedEntityShadowed.entity.extendedDepartmentNameList = addDepNames.slice(0, -2); + } + this.openPopupDialog(this.employeeWebappList.focusedEntityShadowed); + } + + dblClick(event: any) { + if (!this.employeeDetails.entityIsLoading) this.employeeWebappList.focusedEntityShadowed.delayedEdit(event.data['entityId'], this.editItem); + } + + editItem = () => { + this.employeeWebappList.focusedEntityShadowed.edit(); + this.openPopupDialog(this.employeeWebappList.focusedEntityShadowed); + } + + public openPopupDialog(editEntity: AppBaseEntityWrapper) { + this.employeeDetails.keyDownListenerStopped = true; + this.dialog.openDialog(EmployeeToWebAppPopupeditComponent, { + baseEntityWrapper: editEntity, + keyItemName: this.employeeDetails.entity.firstName + ' ' + this.employeeDetails.entity.lastName, + readOnly: !this.employeeDetails.inNotViewMode || !this.employeeDetails.entity.isActive, + description: (editEntity.entity.entityId === 0 ? 'Neue Webbapp zuweisen' : 'Daten zur Webbapp "' + editEntity.entity.webAppName + '" bearbeiten '), + list: this.employeeWebappList, + }, true, () => this.employeeDetails.keyDownListenerStopped = false); + } + + @HostListener('keydown', ['$event']) + onKeyDown(event: any) { + switch (event. which) { + case keycode.ENTER: + return false; + } + return true; + } + + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.html new file mode 100644 index 0000000..ea5e162 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.html @@ -0,0 +1,113 @@ +
+ +

{{description}} - {{keyItemName}}

+ + + +
+ + +
+ + + + + + + + + + + + + + + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.scss new file mode 100644 index 0000000..05aa8a2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.scss @@ -0,0 +1,38 @@ +@import 'popup-base.component'; + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: repeat(3, 42px) auto; // row relationships + grid-template-columns: repeat(2, minmax(1px, 300px)) auto; // column relationship + grid-column-gap: 15px; + grid-row-gap: 15px; + grid-template-areas: + 'input-webapp input-adddepartment input-addrole' + 'input-department input-adddepartment input-addrole' + 'input-role input-adddepartment input-addrole' + 'buttons buttons buttons' +} + +.input-department { + grid-area: input-department; +} + +.input-adddepartment { + grid-area: input-adddepartment; +} + +.input-addrole { + grid-area: input-addrole; +} + +.input-webapp { + grid-area: input-webapp; +} + +.input-role { + grid-area: input-role; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.ts new file mode 100644 index 0000000..a4ca5cf --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component.ts @@ -0,0 +1,70 @@ +import { Component } from '@angular/core'; +import { EN_AppEntities } from '@app_consts'; +import { PopupBaseComponent } from '@app_core/components/popup-base/popup-base.component'; +import { Department } from '@app_models/basedata/department'; +import { WebApp } from '@app_models/basedata/webapp'; +import { WebAppToWebAppRole } from '@app_models/basedata/webapp-to-webapprole'; +import { WebAppAdditionalRole } from '@app_models/basedata/webappadditionalrole '; +import { EmployeeToWebApp } from '@app_models/employee-to-webapp'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; + +@Component({ + selector: 'app-employee-webapp-popupedit', + templateUrl: 'employee-webapp.popupedit.component.html', + styleUrls: ['employee-webapp.popupedit.component.scss'] +}) + +export class EmployeeToWebAppPopupeditComponent extends PopupBaseComponent { + public webAppRoleList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WebAppToWebAppRole, 'Applikation Rolenliste', EN_AppEntities.WebAppToWebAppRole); + public additionalRoleList: AppBaseEntityListWrapper = + new AppBaseEntityListWrapper(WebAppAdditionalRole, 'Applikation Rolenliste', EN_AppEntities.WebAppAdditionalRole); + + public departmentIdList: number[] = this.employeeService.employee2DepartmentList.items.map(e2d => e2d.departmentId); + + constructor( + public appDataService: AppDataService, + public employeeService: EmployeeDataService, + ) { + super(); + this.webAppRoleList.filter = this.appDataService.webAppFilter; + this.additionalRoleList.filter = this.appDataService.webAppFilter; + this.loadRoles(); + } + + + loadRoles() { + if (this.focusedItem.webAppId) { + this.appDataService.webAppFilter.webAppId = this.focusedItem.webAppId; + this.webAppRoleList.load(); + if (this.focusedItem.isNew() || this.focusedItem.additionalRoleIdList !== null) this.additionalRoleList.load(); + } else { + this.webAppRoleList.clear(); + this.additionalRoleList.clear(); + } + } + + + public get focusedItem(): EmployeeToWebApp { + return (this._focusedItem); + } + + + getWebapps = (wa: WebApp) => { + return this.focusedItem.entityId !== 0 || !this.list.items.find((item) => item['webAppId'] === wa.entityId) && wa.isActive; + } + + + public filterDepartments = (department: Department) => { + return this.departmentIdList.indexOf(department.departmentId) > -1; + } + + public save = () => { + this.focusedItem.webAppName = this.appDataService.webAppList?.getItemById(this.focusedItem.webAppId)?.webAppName; + this.focusedItem.departmentName = this.appDataService.departmentList?.getItemById(this.focusedItem.departmentId)?.departmentName; + this.focusedItem.webAppRoleName = this.appDataService.roleList?.getItemById(this.focusedItem.webAppRoleId)?.webAppRoleName; + + this.baseEntityWrapper.save(() => this.close(true)); + } +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.html new file mode 100644 index 0000000..6bc825d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.html @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Aktiv + + +
+ + + +
+ +
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.scss new file mode 100644 index 0000000..1ce85f1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.scss @@ -0,0 +1,77 @@ +.filterCardContainer { + padding: 0; + margin: 0; + overflow: hidden; + display: grid; + width: 100%; + height: 100%; + grid-column-gap: 15px; + grid-template-rows: repeat(1, auto); + grid-template-columns: repeat(8, minmax(0, 1fr)) auto auto; + grid-template-areas: + "filterName filterShortName filterLogin filterDepartment filterWebApp filterAttribute filterEmployeeId filterMandant filterIsActive filterButtons " +} + +// @media screen and (max-width:1024px) { +// .woassays { +// font-size: 1vw; +// } +// } + +.filterIsActive{ + + margin: auto; + grid-area: filterIsActive; +} +.filterMandant { + grid-area: filterMandant; +} +.filterName { + grid-area: filterName; +} + +.filterShortName { + grid-area: filterShortName; +} + +.filterLogin { + grid-area: filterLogin; +} + +.filterWebApp { + grid-area: filterWebApp; +} + +// .filterEmail { +// grid-area: filterEmail; +// } + +.filterDepartment { + grid-area: filterDepartment; +} + +.filterEmployeeId { + grid-area: filterEmployeeId; +} + +.filterAttribute { + grid-area: filterAttribute; +} + +.filterButtons { + grid-area: filterButtons; + margin-left: auto; +} + +// .filterBtn { +// font-size: 1vw; //scales buttons caption depended from the current view port resolution +// } + +.card { + padding: 10px; + margin: 2px 2px 0px 2px; +} + +.filterButtons .filterBtn { + width: unset; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.ts new file mode 100644 index 0000000..8614e7b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-filter/employee-filter.component.ts @@ -0,0 +1,85 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnInit, Output } from '@angular/core'; +import { Employee, EmployeeFullFilter } from '@app_models/employee'; +import { EmployeeDataService } from '@app_modules/employee/employee-data.service'; +import { AppBaseEntityWrapper } from '@app_services/app.baseentity.wrapper'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import * as Cnst from '@app_core/consts'; +import { ClipboardService } from 'ngx-clipboard'; +import { AuthorizeService } from '@app_core/services/authorize.service'; +import { UINotifierService } from '@app_core/services/notification/uinotifier.service'; +import { LoginPopupComponent } from '@app_core/components/login/login-popup/login-popup.component'; +import { LocaleService } from '@app_core/services/localization/locale.service'; + +@Component({ + selector: 'app-employee-filter', + templateUrl: './employee-filter.component.html', + styleUrls: ['./employee-filter.component.scss'], +}) +export class EmployeeFilterComponent implements OnInit, AfterViewInit { + + constructor( + public employeeDataService: EmployeeDataService, + public appDataService: AppDataService, + public authService: AuthorizeService, + public localeService: LocaleService, + private clipboardService: ClipboardService, + private notifierService: UINotifierService, + ) { } + @Input() public filterObject: EmployeeFullFilter; + @Input() employeeDetails: AppBaseEntityWrapper; + @Input() employeeList: AppBaseEntityListWrapper; + @Output() public filterFetch = new EventEmitter(); + + public dropDownAllCaption = Cnst.EN_DropDownConst4Filter.AllCaption; + public dropDownAllValueString = Cnst.EN_DropDownConst4Filter.AllValueString; + public dropDownAllValueInt = Cnst.EN_DropDownConst4Filter.AllValueInt; + public allCaption = Cnst.EN_DropDownConst4Filter.AllCaption; + public allValue: number = Cnst.EN_DropDownConst4Filter.AllValueInt; + public noneCaption = Cnst.EN_DropDownConst4Filter.NoneCaption; + public noneValue = Cnst.EN_DropDownConst4Filter.NoneValueInt; + + ngOnInit() { + } + ngAfterViewInit() { } + + onFilterClick() { + if (this.employeeDetails.inViewMode) this.filterFetch.emit(); + } + + onClearClick() { + this.filterObject.filterReset(); + this.filterObject.isActive = true; + this.onFilterClick(); + } + + + + + onEmailClick() { + const listEmployeeIds = this.employeeList.items.filter((empl: Employee) => !!empl.email).map((empl: Employee) => empl.entityId); + const listEmails = this.employeeList.items.sort((empl1, empl2) => empl1.lastName.localeCompare(empl2.lastName)).map((empl: Employee) => empl.email).filter(email => !!email); + if (listEmails.length === 0) return; + this.clipboardService.copy(listEmails.join('; ')); + const endung = (listEmails.length > 1 ? 'n' : ''); + this.notifierService.showMessage(`${listEmails.length} Emailadresse${endung} wurde${endung} in die Zwischenablage gespeichert`); + } + + + @HostListener('window:keydown', ['$event']) + keyboardInput(event: any) { + if (!LoginPopupComponent.LOGIN_IS_SHOWN && !this.employeeDetails.keyDownListenerStopped) { + if (event.ctrlKey) { + switch (event.which) { + case keycode.F: //Ctrl + 'f' + event.stopPropagation(); + this.onFilterClick(); + return false; //processed + } + } + } + return true; //default processing + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.html new file mode 100644 index 0000000..7046859 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.html @@ -0,0 +1,86 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{cell.value | number:'1.0-0':culture}} +
+
+ {{cell.value | number:'1.1-1':culture}} +
+
+ {{cell.value | number:'1.2-2':culture}} +
+
+ {{cell.value | number:'1.3-3':culture}} +
+
+
+
+
+
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.scss new file mode 100644 index 0000000..8ec9070 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.scss @@ -0,0 +1,38 @@ +.EmployeeList { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: auto minmax(0, 1fr); // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-row-gap: 7px; + grid-template-areas: + 'filter' + 'grid'; +} + +.FilterComponent { + grid-area: filter; // grid area: auto height 1fr width + margin: 0 0 0 0; +} + + +.card { + grid-area: grid; + width: 100%; + padding: 0px; + margin: 0; + border-radius: 0px; + box-shadow: none; +} + +.gridEmployee { + position: absolute; // position absolut ist hier zwingend! Die position ist absolut innerhalb mehrerer parent divs und darf sich NICHT über diese hinausstrecken. + height: 100%; + width: 100%; + padding-left: 1px; + padding-right: 1px; + padding-bottom: 1px; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.ts new file mode 100644 index 0000000..3464163 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee-list/employee-list.component.ts @@ -0,0 +1,80 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { ColumnConfigList } from '@app_core/components/grid-config/columnconfiglist'; +import { Globals } from '@app_core/services/globals'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { Employee } from '@app_models/employee'; +import { AppBaseEntityListWrapper } from '@app_services/app.baseentitylist.wrapper'; +import { AppDataService } from '@app_services/app.data.service'; +import { EmployeeDataService } from '../employee-data.service'; +import { ColumnConfig, EN_Alignment, EN_SortOrder } from '@app_core/components/grid-config/columnconfig'; + +@Component({ + selector: 'app-employee-list', + templateUrl: './employee-list.component.html', + styleUrls: ['./employee-list.component.scss'] +}) +export class EmployeeListComponent implements OnInit { + @Input() public dataSource: AppBaseEntityListWrapper; + // @ViewChild('gridCatalog') dxGrid: DxDataGridComponent; + + public columnConfigList: ColumnConfigList = new ColumnConfigList(); + + + constructor( + public employeeDataService: EmployeeDataService, + public appDataService: AppDataService, + public localeService: LocaleService, + public globals: Globals, + ) { + } + + ngOnInit() { + this.initColumns(); + } + + + initColumns() { + let col: ColumnConfig; + + // col = this.columnConfigList.addNumber('id', 'EmployeeId', 7); + + if (this.appDataService.showIds) col = this.columnConfigList.addNumber('Id', 'entityId', 7, 0); + if (this.appDataService.showIds) col = this.columnConfigList.add('Nr', 'employeeNo', 7); + + col = this.columnConfigList.add('Nachname', 'lastName', 25); + col.sortIndex = 1; + col.sortOrder = EN_SortOrder.asc; + + col = this.columnConfigList.add('Vorname', 'firstName', 15); + col.sortIndex = 2; + col.sortOrder = EN_SortOrder.asc; + + // col = this.columnConfigList.add('Anrede', 'salutation', 10); + col = this.columnConfigList.add('Kürzel', 'shortName', 7); + col = this.columnConfigList.add('Position', 'position', 25); + + col = this.columnConfigList.add('Login', 'loginName', 15); + col = this.columnConfigList.add('Email', 'email', 30); + col = this.columnConfigList.add('Rang', 'rangId', 10); + + col = this.columnConfigList.add('Handynummer', 'mobilePhoneNo', 20); + col = this.columnConfigList.add('Festnetznummer', 'phoneNo', 20); + + + // if (this.appDataService.showIds) col = + col = this.columnConfigList.add('Department', 'departmentNamesList', 30); + col = this.columnConfigList.add('Webapps', 'webappNamesList', 25); + col = this.columnConfigList.add('Merkmale', 'attributeNamesList', 20); + // this.columnConfigList.addNumber('Firma-Id', 'clientId', 7); + col = this.columnConfigList.add('Mandant', 'mandantCode', 15); + col = this.columnConfigList.addBoolean('Aktiv', 'isActive', -50); + col.alignment = EN_Alignment.left; + + this.columnConfigList.recalcWidth(); + } + + + public loadData() { + this.employeeDataService.loadData(); + } +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.html b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.html new file mode 100644 index 0000000..d04d7c0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.html @@ -0,0 +1,4 @@ +
+ + +
diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.scss b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.scss new file mode 100644 index 0000000..c990dc3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.scss @@ -0,0 +1,22 @@ +.EmployeeComponent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: minmax(0, 1fr) auto; // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-template-areas: 'list''details'; + grid-column-gap: 5px; + grid-row-gap: 5px; +} + +.EmployeeListComponent { + grid-area: list; +} + +.EmployeeDetailsComponent { + grid-area: details; + z-index: 10; +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.ts new file mode 100644 index 0000000..26c0382 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee.component.ts @@ -0,0 +1,18 @@ +import { Component, OnInit } from '@angular/core'; +import { EmployeeDataService } from './employee-data.service'; + +@Component({ + selector: 'app-employee', + templateUrl: './employee.component.html', + styleUrls: ['./employee.component.scss'] +}) +export class EmployeeComponent implements OnInit { + + constructor( + public employeeDataService: EmployeeDataService + ) { } + + ngOnInit() { + } + +} diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee.module.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee.module.ts new file mode 100644 index 0000000..c139822 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee.module.ts @@ -0,0 +1,59 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { FormsModule } from '@angular/forms'; +import { AngularMaterialModule } from '@app_core/components/angular-material.module'; +import { DxButtonModule, DxDataGridModule, DxFileUploaderModule, DxPieChartModule, DxTemplateModule, DxTooltipModule } from 'devextreme-angular'; +import { EmployeeAttributeComponent } from './employee-detail/employee-attribute/employee-attribute.component'; +import { EmployeeContentComponent } from './employee-detail/employee-content/employee-content.component'; +import { EmployeeDepartmentComponent } from './employee-detail/employee-department/employee-department.component'; +import { EmployeeToDepartmentPopupeditComponent } from './employee-detail/employee-department/employee-department.popupedit/employee-department.popupedit.component'; +import { EmployeeDetailComponent } from './employee-detail/employee-detail.component'; +import { EmployeeWebappComponent } from './employee-detail/employee-webapp/employee-webapp.component'; +import { EmployeeToWebAppPopupeditComponent } from './employee-detail/employee-webapp/employee-webapp.popupedit/employee-webapp.popupedit.component'; +import { EmployeeFilterComponent } from './employee-list/employee-filter/employee-filter.component'; +import { EmployeeListComponent } from './employee-list/employee-list.component'; +import { EmployeeComponent } from './employee.component'; +import { EmployeeRoutingModule } from './employee.routing.module'; +import { HenselSelectionComponent } from '@app_core/components/hensel-selection/hensel-selection.component'; +import { HenselInputComponent } from '@app_core/components/hensel-input/hensel-input.component'; +import { NgxMaskDirective, NgxMaskPipe } from 'ngx-mask'; +import { HenselMaskDecimalDirective } from '@app_core/directives/hensel-decimal.directive'; +import { HenselValidator } from '@app_core/validators/hensel-validator.directive'; + + +@NgModule({ + declarations: [ + EmployeeComponent, + EmployeeListComponent, + EmployeeContentComponent, + EmployeeAttributeComponent, + EmployeeDetailComponent, + EmployeeFilterComponent, + EmployeeWebappComponent, + EmployeeDepartmentComponent, + EmployeeToDepartmentPopupeditComponent, + EmployeeToWebAppPopupeditComponent + ], + imports: [ + CommonModule, + EmployeeRoutingModule, + AngularMaterialModule, + DxDataGridModule, + FormsModule, + HenselSelectionComponent, + HenselInputComponent, + HenselMaskDecimalDirective, + HenselValidator, + DxFileUploaderModule, + DxButtonModule, + DxTooltipModule, + DxTemplateModule, + DxPieChartModule, + NgxMaskDirective, + NgxMaskPipe, + ], + providers: [], + exports: [] +}) +export class EmployeeModule { } diff --git a/ClientApp/staff-db-ui/src/app/modules/employee/employee.routing.module.ts b/ClientApp/staff-db-ui/src/app/modules/employee/employee.routing.module.ts new file mode 100644 index 0000000..c97529c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/modules/employee/employee.routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { EmployeeComponent } from './employee.component'; +import { AuthGuard } from '@app_core/services/authguard'; + +const routes: Routes = [ + { + path: '**', + component: EmployeeComponent, + canActivate: [AuthGuard] + }, +]; + + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class EmployeeRoutingModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/app.consts.ts b/ClientApp/staff-db-ui/src/app/shared/app.consts.ts new file mode 100644 index 0000000..4f59b41 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/app.consts.ts @@ -0,0 +1,97 @@ +import { IENVIRONMENT } from '@app_core/injection-tokens'; +import { ACCOUNT_PAGE, IAppPage, LOGIN_PAGE } from '@app_core/services/globals'; + +export const SUPPORTED_LANGUAGES = ['de', 'en']; + +declare const environment: IENVIRONMENT; +export const APP_TITLE: string = environment['APP_TITLE'] ?? 'StaffDB'; +export const cnst_DefaultCulture = environment.culture ?? 'de-DE'; +export const cnst_DefaultLanguage = environment.language ?? 'de'; + +// page description, wich is used for routing as well for preparing routings menus and intern for page loading +export const APP_PAGES: IAppPage[] = [ + { + caption: 'Mitarbeiter', + path: 'employee', + loadChildren: () => import('@app_modules/employee/employee.module').then(m => m.EmployeeModule), + icon: '', + messageCaption: 'Employee', + }, + { + caption: 'Abteilungen', + path: 'departments', + loadChildren: () => import('@app_modules/department/department.module').then(m => m.DepartmentModule), + icon: '', + messageCaption: 'Department', + }, + ACCOUNT_PAGE, + LOGIN_PAGE, +]; + +// named constants to access the arry APP_PAGES + +export const enum EN_AppPages { + Employee = 0, + Department = 1, + Settings = 2, + Login = 3, +} + +// named constants with numbers of http requests of data loading for every page for maintain of spinner + +export const enum EN_HttpQueriesCount4Page { + Employee = 1, + Department = 1, + Login = 10, //no of quires in load stammdata +} + +export function getPageIndex(page: string): number { + return APP_PAGES.findIndex((pg) => pg.path === page); +} + + +export enum EN_AppEntities { + //-- base data entities + Employee = 'employee', + CostCentre = 'costcentre', + Vendor = 'vendor', + EmployeeStatus = 'employeestatus', + Rang = 'rang', + DocumentArt = 'documentart', + Project = 'project', + Department = 'department', + WindreamSearch = 'windreamsearch', + WindreamIndex = 'windreamindex', + WindreamIndexToWindreamSearchToDepartment = 'windreamindextowindreamsearchtodepartment', + WindreamSearchToDepartment = 'windreamsearchtodepartment', + WindreamSearchItemToWindreamSearchToDepartment = 'windreamsearchitemtowindreamsearchtodepartment', + WindreamSearchItem = 'windreamsearchitem', + DocumentArtToDepartment = 'documentarttodepartment', + EmployeeToDepartment = 'employeetodepartment', + EmployeeToWebapp = 'employeetowebapp', + WebApp = 'webapp', + WebAppRole = 'webapprole', + WebAppToDepartment = 'webapptodepartment', + WebAppToWebAppRole = 'webapptowebapprole', + EmployeeAttribute = 'employeeattribute', + EmployeeToAttribute = 'employeetoattribute', + WebAppAdditionalRole = 'webappadditionalrole', + WebAppToWebAppAdditionalRole = 'webapptowebappadditionalrole', + WindreamSearchToDepartmentCopyWindreamTile = 'windreamSearchToDepartment/CopyWindreamTile', + DepartmentCopyWindreamTiles = 'department/copyWindreamTiles', + Subsidiary = 'Subsidiary' +} + + +export enum EN_EmployeeStatus { + MainFunction = 1, + AdditionalFunction = 2, +} + + +export enum EN_EmployeeRang { + Mitarbeiter = 4, +} + + +export const cnst_LoadedEntitiesExpiresInMs = 30000; //30s diff --git a/ClientApp/staff-db-ui/src/app/shared/app.types.ts b/ClientApp/staff-db-ui/src/app/shared/app.types.ts new file mode 100644 index 0000000..ca858dd --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/app.types.ts @@ -0,0 +1,4 @@ +import { BaseEntityCallBack, ErrorCallBack } from '@app_core/models/generics/baseentity'; + +export declare type AppBaseEntityCallBack = BaseEntityCallBack; +export declare type AppErrorCallBack = ErrorCallBack; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/at.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/at.svg new file mode 100644 index 0000000..99f7814 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/at.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/au.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/au.svg new file mode 100644 index 0000000..9ba68fb --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/au.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/de.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/de.svg new file mode 100644 index 0000000..834f82f --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/de.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/fr.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/fr.svg new file mode 100644 index 0000000..a4bded5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/fr.svg @@ -0,0 +1,2 @@ + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/gb.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/gb.svg new file mode 100644 index 0000000..56487b0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/gb.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/ko.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/ko.svg new file mode 100644 index 0000000..dbec9be --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/ko.svg @@ -0,0 +1,13 @@ + + +Flag of South Korea + + + + + + + + + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/my.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/my.svg new file mode 100644 index 0000000..79cebc2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/my.svg @@ -0,0 +1,11 @@ + + +Flag of Malaysia + + + + + + + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/us.svg b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/us.svg new file mode 100644 index 0000000..c31e895 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/flags/us.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_bright.ico b/ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_bright.ico new file mode 100644 index 0000000000000000000000000000000000000000..bc6c2d1fe45ce1642f6a2f9539bb66fa32fd687f GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_white.ico b/ClientApp/staff-db-ui/src/app/shared/core/assets/icons/hr-logo_white.ico new file mode 100644 index 0000000000000000000000000000000000000000..ff4f496b9c58968d7fe1f5c3d54bd47ec20366d2 GIT binary patch literal 3098 zcmbuB%}Z2K7>Cbw1})5H5txwVfGuhxAyg3I7%kjL2CZsiPz(`7tAeO-R{aGcMJ|f6 zZ)p)lWW*R$^r6dwG#bJ_KnkU_p~icA-r*j)oVmw)FI{=&J?DLY@9&(sb3atd;V-*Z z$)`%MQmR=gwGpz=0g{)a(5O^92_f#`y6y%z0e4{vetQ1F_y;_JO>zC=>R4hkz7N3F z>zR?#1!#)v8CQqrQTT1Hr{~lvjPr5*lIUdZz&gK}KZomZ&5trZiKYeWl6XgH@$Gamgv0D(+Yzi z-&?p1FJT7ce3W1uPQhWA3|n94sLOt1-4mjNUf2q9U0Dz6$K@O%a2W4}&o(hNxi|Zw z&N=+nC-RX1_Vd>yX(`ZVgPCT0N&W5A9~3 zIrn|6&l>SVGidh7oV@&Yq4$X2_b9B-%;E7$?>j6~pCO+%`(#dSG^|JGsCR|+1#@Wg zT5pT^90~U5G5S5W9?8=;thG9lTdBtqk=2uX8{s3@bb)HF&|_-*e7$uW)aBi98hEQ$_uXU@qj?AN z{uqMq=nm+$Y!O`_%-cM5Ui{!Z^E|Qo{A7GnnVU2qE)<8B0P8ScX+7>Di4tr4e&MjrTBogl|yu3?w%qx}@GwdOYRbGe!(OsC|Ni6rCuqq;-5dVG^p>191uD z`^$BH4tBF{eH>p;<-Cd-@XC(o&G7^*sWwP?1?6~Zh4Q*rtAS!h<%*d?uGCO$gY~6U av31TVI%U", + "core.dropdown-option.none": "< Keine >", + + "core.caption.login": "Login", + "core.caption.hidepassword": "Hide password", + "core.caption.registration": "Anmeldung", + "core.caption.logout": "Logout", + "core.caption.config": "Einstellungen", + "core.caption.version": "Version", + "core.caption.username": "Benutzername", + "core.caption.password": "Passwort", + "core.caption.account": "Konto", + "core.caption.all": "Alle", + "core.caption.none": "Keine", + "core.caption.serverinfo-pollinginterval": "Abstang für Erneuerung von Serverver Info (Sek., 0-nie)", + + "core.msg.saving": "Speichern {{value}}...", + "core.msg.saved": "Gespeichert {{value}}", + "core.msg.loading": "Laden {{value}}...", + "core.msg.loaded": "Geladen {{value}}: {{count}}", + "core.msg.loggedon": "Benutzeranmeldung für {{value}} war erfolgreich", + "core.msg.renewJWT": "Versuche zu verlängern von JWT", + "core.msg.waitingconnecton": "Warte auf Verbindung...", + "core.msg.checkuser": "Benutzer wird überprüft...", + "core.msg.greeting": "Hallo", + "core.msg.update": "Bitte aktualisieren!", + "core.hint.update": "Klicke um die Version zu aktualisieren", + + "core.error.loading": "Fehler beim Laden von {{value}}", + "core.error.saving": "Fehler beim Speichern von {{value}}", + "core.error.deleting": "Fehler beim Löschen von {{value}}", + "core.error.nouserrole": "Keine Benutzerrole ist zugewiesen!", + "core.error.logon": "Anmeldung ist fehlgeschlagen!", + "core.error.logonnotpossible": "{{value}}Anmeldung ist nicht möglich!", + "core.error.disclaimernotconfirmed": "Haftungsausschluss muss bestätigt werden!", + + "core.msgbox.header.cancel": "{{value}}", + "core.msgbox.body.cancel": "Sollen Änderungen gespeichert werden?", + "core.msgbox.header.delete": "{{value}}", + "core.msgbox.body.delete": "Soll {{value}} gelöscht werden?", + "core.msgbox.header.connect": "Verbindungsaufbau", + "core.msgbox.body.connect": "Keine Verbindung zum Server kann aufgebaut werden. Bitte wenden sie sich an IT-Entwicklung", + + "core.grid.nodata": "Keine Daten vorhanden", + "core.hdatepicker.dateoutofrange": "Das Datum ist ausser zulässigem Bereich", + + "core.hensel-selection.nohits": "Keine Treffer gefunden", + "core.hensel-selection.selectedfirst": "Selektierte zuerst", + "core.hensel-selection.processlist": "Liste bearbeiten", + "core.hensel-selection.inputminsybols": "Für Auswahl mind. {{value}} Zeichen eingeben", + + "core.hwebcam.delete": "Foto löschen", + "core.hwebcam.takepicture": "Foto aufnehmen", + + "core.footer.status": "Status", + "core.footer.noconnection": "Keine Verbindung ist vorhanden !!!", + "core.footer.lastloading": "Letzte Datenabruf", + "core.footer.loginexpires": "Anmeldung läuft ab in", + "core.footer.days": "Tag(e)", + "core.footer.hours": "Std.", + "core.footer.mins": "Min.", + "core.footer.secs": "Sek.", + + "core.account.caption.price": "Preis", + "core.account.caption.weight" : "Gewicht", + + "core.caption.date": "Datum", + "core.caption.user": "Benutzer", + "core.caption.role": "Rolle", + "core.caption.myaccount": "Mein Konto", + "core.caption.disclaimer": "Haftungsausschluss", + + "core.caption.addsettings" : "Admineinstellungen", + "core.caption.showstatusbar" : "Statuszeile anzeigen", + "core.caption.showids" : "Ids anzeigen", + "core.caption.language" : "Sprache", + "core.caption.regionformat" : "Regionales Format", + "core.caption.name": "Name", + "core.caption.userloginname": "Benutzername", + + "core.caption.country-ge": "Deutschland", + "core.caption.country-at": "Österrecih", + "core.caption.country-gb": "Grossbritanien", + "core.caption.country-us": "United States", + "core.caption.country-au": "Australien", + "core.caption.country-fr": "Frankreich", + "core.caption.country-kr": "Korea", + "core.caption.country-my": "Malaysia", + + "core.caption.lang-ge": "Deutsch", + "core.caption.lang-at": "Deutsch", + "core.caption.lang-gb": "Englisch", + "core.caption.lang-us": "Englisch", + "core.caption.lang-au": "Englisch", + "core.caption.lang-fr": "Französisch", + "core.caption.lang-kr": "Koreanisch", + "core.caption.lang-my": "Malaiisch" +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/en.json b/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/en.json new file mode 100644 index 0000000..d47f49c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/en.json @@ -0,0 +1,110 @@ +{ + "core.btn.ok": "Ok", + "core.btn.yes": "Yes", + "core.btn.no": "No", + "core.btn.cancel": "Cancel", + "core.btn.apply": "Apply", + "core.btn.reset": "Reset", + "core.hint.reset": "Reset", + "core.hint.undo": "Discard changes", + "core.btn.undo": "Discard", + "core.btn.search": "Search", + + "core.dropdown-option.all": "< All >", + "core.dropdown-option.none": "< None >", + + "core.caption.login": "Login", + "core.caption.hidepassword": "Hide password", + "core.caption.registration": "Log in", + "core.caption.logout": "Logout", + "core.caption.config": "Configuration", + "core.caption.version": "Version", + "core.caption.username": "Username", + "core.caption.password": "Password", + "core.caption.account": "Account", + "core.caption.all": "All", + "core.caption.none": "None", + "core.caption.serverinfo-pollinginterval": "Interval to refresh of Serverver Info (sec., 0-never)", + + "core.msg.saving": "Saving {{value}}...", + "core.msg.saved": "Saved {{value}}", + "core.msg.loading": "Loading {{value}}...", + "core.msg.loaded": "Loaded {{value}}: {{count}}", + "core.msg.loggedon": "Logon for {{value}} succeeded", + "core.msg.renewJWT": "Try to renew JWT", + "core.msg.waitingconnecton": "Waiting connection...", + "core.msg.checkuser": "Check user...", + "core.msg.greeting": "Hello", + "core.msg.update": "Please update!", + "core.hint.update": "Click to update the version", + + "core.error.loading": "Error during loading of {{value}}", + "core.error.saving": "Error during saving of {{value}}", + "core.error.deleting": "Error during deleting of {{value}}", + "core.error.nouserrole": "User is assigned no role!", + "core.error.logon": "Logon failed!", + "core.error.logonnotpossible": "{{value}}Logon is not possible!", + "core.error.disclaimernotconfirmed": "Disclaimer must be confirmed!", + + "core.msgbox.header.cancel": "{{value}}", + "core.msgbox.body.cancel": "Save changes?", + "core.msgbox.header.delete": "{{value}}", + "core.msgbox.body.delete": "Delete {{value}}?", + "core.msgbox.header.connect": "Establish connection", + "core.msgbox.body.connect": "The server connot be connected. Please contact IT-Development", + + "core.grid.nodata": "No data", + "core.hdatepicker.dateoutofrange": "The date is out of range", + + "core.hensel-selection.nohits": "No hits", + "core.hensel-selection.selectedfirst": "Selected first", + "core.hensel-selection.processlist": "Edit list", + "core.hensel-selection.inputminsybols": "For selection input at least {{value}} symbols", + + "core.hwebcam.delete": "Delete picture", + "core.hwebcam.takepicture": "Take picture", + + "core.footer.status": "Status", + "core.footer.noconnection": "No connectoin to the server !!!", + "core.footer.lastloading": "Last Dataloading", + "core.footer.loginexpires": "Login expires in", + "core.footer.days": "Day(s)", + "core.footer.hours": "Hr(s)", + "core.footer.mins": "Min(s)", + "core.footer.secs": "Sec(s)", + + "core.account.caption.price": "Price", + "core.account.caption.weight" : "Weight", + + "core.caption.date": "Date", + "core.caption.user": "User", + "core.caption.role": "Role", + "core.caption.myaccount": "My Account", + "core.caption.disclaimer": "Disclaimer", + + "core.caption.addsettings" : "Admin Settings", + "core.caption.showstatusbar" : "Show Statusbar", + "core.caption.showids" : "Show Ids", + "core.caption.language" : "Language", + "core.caption.regionformat" : "Regional Format", + "core.caption.name": "Name", + "core.caption.userloginname": "Loginname", + + "core.caption.country-ge": "Germany", + "core.caption.country-at": "Austria", + "core.caption.country-gb": "United Kingdom", + "core.caption.country-us": "United States", + "core.caption.country-au": "Australia", + "core.caption.country-fr": "France", + "core.caption.country-kr": "Korea", + "core.caption.country-my": "Malaysia", + + "core.caption.lang-ge": "German", + "core.caption.lang-at": "German", + "core.caption.lang-gb": "English", + "core.caption.lang-us": "English", + "core.caption.lang-au": "English", + "core.caption.lang-fr": "French", + "core.caption.lang-kr": "Korean", + "core.caption.lang-my": "Malay" +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/fr.json b/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/fr.json new file mode 100644 index 0000000..a3ab918 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/assets/translate-core/fr.json @@ -0,0 +1,107 @@ +{ + "core.btn.ok": "Ok", + "core.btn.yes": "Yes", + "core.btn.no": "No", + "core.btn.cancel": "Cancel", + "core.btn.apply": "Accept", + "core.btn.reset": "Reset", + "core.hint.reset": "Reset", + "core.btn.search": "Search", + + "core.dropdown-option.all": "< All >", + "core.dropdown-option.none": "< None >", + + "core.caption.login": "Login", + "core.caption.registration": "Log in", + "core.caption.logout": "Logout", + "core.caption.config": "Configuration", + "core.caption.version": "Version", + "core.caption.username": "Username", + "core.caption.password": "Password", + "core.caption.account": "Account", + "core.caption.all": "All", + "core.caption.none": "None", + "core.caption.serverinfo-pollinginterval": "Interval to refresh of Serverver Info (sec., 0-never)", + + "core.msg.saving": "Saving {{value}}...", + "core.msg.saved": "Saved {{value}}", + "core.msg.loading": "Loading {{value}}...", + "core.msg.loaded": "Loaded {{value}}: {{count}}", + "core.msg.loggedon": "Logon for {{value}} succeeded", + "core.msg.renewJWT": "Try to renew JWT", + "core.msg.waitingconnecton": "Waiting connection...", + "core.msg.checkuser": "Check user...", + "core.msg.greeting": "Hello", + "core.msg.update": "Please update!", + "core.hint.update": "Click to update the version", + + "core.error.loading": "Error during loading of {{value}}", + "core.error.saving": "Error during saving of {{value}}", + "core.error.deleting": "Error during deleting of {{value}}", + "core.error.nouserrole": "User is assigned no role!", + "core.error.logon": "Logon failed!", + "core.error.logonnotpossible": "{{value}}Logon is not possible!", + "core.error.disclaimernotconfirmed": "Disclaimer must be confirmed!", + + "core.msgbox.header.cancel": "Cancelling of processing of {{value}}", + "core.msgbox.body.cancel": "{{value}} was changed. Should changes be saved?", + "core-confirmmsgheader_delete": "Deleting of {{value}}", + "core.msgbox.body.delete": "Should {{value}} be deleted?", + "core-confirmmsgheader_connect": "Establish connection", + "core.msgbox.body.connect": "The server connot be connected. Please contact IT-Development", + + "core.grid.nodata": "No data", + "core.hdatepicker.dateoutofrange": "The date is out of range", + + "core.hensel-selection.nohits": "No hits", + "core.hensel-selection.selectedfirst": "Selected first", + "core.hensel-selection.processlist": "Edit list", + "core.hensel-selection.inputminsybols": "For selection input at least {{value}} symbols", + + "core.hwebcam.takepicture": "Take picture", + "core.hwebcam.delete": "Delete picture", + + "core.footer.status": "Status", + "core.footer.noconnection": "No connectoin to the server !!!", + "core.footer.lastloading": "Last Dataloading", + "core.footer.loginexpires": "Login expires in", + "core.footer.days": "Day(s)", + "core.footer.hours": "Hr(s)", + "core.footer.mins": "Min(s)", + "core.footer.secs": "Sec(s)", + + "core.account.caption.price": "Price", + "core.account.caption.weight" : "Weight", + + "core.caption.date": "Date", + "core.caption.user": "User", + "core.caption.role": "Role", + "core.caption.myaccount": "My Account", + "core.caption.disclaimer": "Disclaimer", + + "core.caption.addsettings" : "Admin Settings", + "core.caption.showstatusbar" : "Show Statusbar", + "core.caption.showids" : "Show Ids", + "core.caption.language" : "Language", + "core.caption.regionformat" : "Regional Format", + "core.caption.name": "Name", + "core.caption.userloginname": "Loginname", + + "core.caption.country-ge": "Germany", + "core.caption.country-at": "Austria", + "core.caption.country-gb": "United Kingdom", + "core.caption.country-us": "United States", + "core.caption.country-au": "Australia", + "core.caption.country-fr": "France", + "core.caption.country-kr": "Korea", + "core.caption.country-my": "Malaysia", + + "core.caption.lang-ge": "German", + "core.caption.lang-at": "German", + "core.caption.lang-gb": "English", + "core.caption.lang-us": "English", + "core.caption.lang-au": "English", + "core.caption.lang-fr": "French", + "core.caption.lang-kr": "Korean", + "core.caption.lang-my": "Malay" +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/account/account-routing.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account-routing.module.ts new file mode 100644 index 0000000..24c9026 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { AuthGuard } from '../../services/authguard'; +import { AccountComponent } from './account.component'; + + +const routes: Routes = [ + { + path: '', + component: AccountComponent, + canActivate: [AuthGuard] + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AccountRoutingModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.html new file mode 100644 index 0000000..5b93632 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.html @@ -0,0 +1,86 @@ +
+ + + + + {{'core.caption.myaccount' | translate}} + + + + + + + + + + + + + + + +
+ + +
{{'core.caption.date' | translate}}:
+
{{today | date:'shortDate'}}
+
{{'core.account.caption.weight' | translate}}:
+
{{0.74 | number:'1.3-3'}} kg
+
{{'core.account.caption.price' | translate}}:
+
{{44357.00 | currency:currencySymbol:"symbol":"1.2-2"}}
+
+ +
+
+ + + + {{'core.caption.addsettings' | translate}} + + +
+
+ {{'core.caption.showstatusbar' | translate}} +
+
+ {{'core.caption.showids' | translate}} +
+
+ +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.scss new file mode 100644 index 0000000..eb15301 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.scss @@ -0,0 +1,149 @@ +.ConfigContainer { + width: 100%; + height: 100%; + display: grid; + grid-template-rows: auto auto minmax(0, 1fr); + grid-template-columns: minmax(0, 1fr); + grid-template-areas: + "profile" + "other-settings" + "admin-settings" + ; + overflow: hidden; + grid-gap: 0.9em; +} + +.profile { + grid-area: profile; +} + +.admin-settings { + grid-area: admin-settings; + height: fit-content; +} + +.other-settings { + grid-area: other-settings; +} + +.admin-content{ + display: grid; + grid-template-columns: 250px 1fr; + grid-template-areas: "admin-std admin-custom"; + grid-gap: 0.5em; + column-gap: 2em; + overflow: hidden; +} + +.admin-custom { + grid-area: admin-custom; +} + +.setting-card { + margin-left: 1px; + margin-right: 2px !important; + margin-top: 1px; + margin-bottom: 1px; +} + +.abstand { + margin-bottom: 10px; +} + +.logout { + margin-left: auto; + font-size: large; + padding-right: 15px !important; + padding-left: 15px !important;} + +.logout-icon { + vertical-align: middle; + margin-right: 10px; +} + +.profile-content { + width: 100%; + height: calc(100% - 38px); + display: grid; + grid-template-rows: auto auto auto; + grid-template-columns: 250px auto 1fr; + grid-template-areas: + "user-name culture_section profile-custom" + "user-loginname culture_section profile-custom" + "language culture_section profile-custom"; + overflow: hidden; + grid-gap: 0.5em; + column-gap: 2em; +} + +.profile-custom { + grid-area: profile-custom; +} + +.user-name { + grid-area: user-name; +} + +.user-loginname { + grid-area: user-loginname; +} + +.culture_section { + grid-area: culture_section; + width: 100%; + height: 100%; + display: grid; + grid-template-rows: repeat(4, auto); + grid-template-columns: 1fr 1fr; + grid-template-areas: + "culture culture" + "sample-date-capt sample-date" + "sample-weight-capt sample-weight" + "sample-price-capt sample-price"; + overflow: hidden; + grid-gap: 0.5em; + column-gap: 1em; +} + + +.culture { + grid-area: culture; + width: 250px; +} + +.user-name { + grid-area: user-name; +} + +.sample-date-capt { + grid-area: sample-date-capt; +} + +.sample-date { + grid-area: sample-date; +} + +.sample-weight-capt { + grid-area: sample-weight-capt; +} + +.sample-weight { + grid-area: sample-weight; +} + +.sample-price-capt { + grid-area: sample-price-capt; +} + +.sample-price { + grid-area: sample-price; +} + + +.language { + grid-area: language; +} + +::ng-deep .ConfigContainer .mat-card-header-text { + margin-left: 0px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.ts new file mode 100644 index 0000000..6854aec --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.component.ts @@ -0,0 +1,80 @@ +import { Component, inject, Inject, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { SUPPORTED_CULTURES_TOKEN, SUPPORTED_LANGUAGES_TOKEN } from '../..//injection-tokens'; +import * as Cnst from '../../consts'; +import { Globals } from '../../services/globals'; +import { CoreUser } from '../../models/coreuser'; +import { AuthorizeService } from '../../services/authorize.service'; +import { RepositoryService } from '../../services/http/repository.service'; +import { LocaleService } from '../../services/localization/locale.service'; +import { ServerInfoService } from '../../services/serverinfo.service'; +import * as Utils from '../../utils'; + +@Component({ + selector: 'app-account', + templateUrl: './account.component.html', + styleUrls: ['./account.component.scss'] +}) +export class AccountComponent implements OnInit { + public noneCaption: string = Cnst.EN_DropDownConst4Filter.NoneCaption; + public noneValue: number = Cnst.EN_DropDownConst4Filter.NoneValueInt; + public webAppIdList: number[] = []; + public usedCultures: Cnst.SupportedCulture[]; + public usedLanguages: Cnst.SupportedLanguage[]; + public today: Date; + public currencySymbol: string; + public get user(): CoreUser { + return this.authService.user; + } + + public globals: Globals = inject(Globals); + protected router: Router = inject(Router); + + public authService: AuthorizeService = inject(AuthorizeService); + public serverInfoService: ServerInfoService = inject(ServerInfoService); + public localeService: LocaleService = inject(LocaleService); + protected repositoryService: RepositoryService = inject(RepositoryService); + protected APP_SUPPORTED_CULTURES: string[] = inject(SUPPORTED_CULTURES_TOKEN); + protected APP_SUPPORTED_LANGUAGES: string[] = inject(SUPPORTED_LANGUAGES_TOKEN); + + + constructor( + ) { + } + + + ngOnInit() { + this.usedLanguages = Cnst.SUPPORTED_LANGUAGES.filter((lang: Cnst.SupportedLanguage) => Utils.isLanguageSupported(lang.langCode, this.APP_SUPPORTED_LANGUAGES)); + this.usedCultures = Cnst.SUPPORTED_CULTURES.filter((cltr: Cnst.SupportedCulture) => Utils.isCultureSupported(cltr.culture, this.APP_SUPPORTED_CULTURES)); + this.today = Utils.today(); + this.currencySymbol = Utils.getCurrencySymbol(this.localeService.currentCulture); + } + + logout() { + this.authService.logout(true); + } + + setLocale(culture: string) { + this.localeService.currentCulture = culture; + this.currencySymbol = Utils.getCurrencySymbol(this.localeService.currentCulture); + this.saveCultureLanguage(); + } + + setLangauge(lang: string) { + this.localeService.currentLanguage = lang; + this.saveCultureLanguage(); + } + + + saveCultureLanguage() { + this.user.culture = this.localeService.currentCulture; + this.user.language = this.localeService.currentLanguage; + this.user.save(this.repositoryService, null, null, null, 'culture'); + } + + + goHome() { + this.router.navigate(['/' + this.globals.mainPage.path]); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.module.ts new file mode 100644 index 0000000..e9f9ec2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/account/account.module.ts @@ -0,0 +1,31 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { AccountRoutingModule } from './account-routing.module'; +import { AccountComponent } from './account.component'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; +import { DxDataGridModule } from 'devextreme-angular'; +import { DxoSearchPanelModule } from 'devextreme-angular/ui/nested'; +import { TranslateModule } from '@ngx-translate/core'; +import { AngularMaterialModule } from '../angular-material.module'; +import { HenselSelectionComponent } from '../hensel-selection/hensel-selection.component'; +import { HenselInputComponent } from '../hensel-input/hensel-input.component'; + + +@NgModule({ + declarations: [AccountComponent], + imports: [ + CommonModule, + AccountRoutingModule, + AngularMaterialModule, + ReactiveFormsModule, + FormsModule, + DxDataGridModule, + DxoSearchPanelModule, + HenselSelectionComponent, + HenselInputComponent, + TranslateModule + ], + exports: [AccountComponent] +}) +export class AccountModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material-index.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material-index.ts new file mode 100644 index 0000000..c3e96ac --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material-index.ts @@ -0,0 +1,53 @@ +export { + MatLegacyOptionSelectionChange as MatOptionSelectionChange, + _countGroupLabelsBeforeLegacyOption as _countGroupLabelsBeforeOption, + _getLegacyOptionScrollPosition as _getOptionScrollPosition +} from '@angular/material/legacy-core'; +export { + MatLegacyAutocomplete as MatAutocomplete, + MatLegacyAutocompleteTrigger as MatAutocompleteTrigger, + MatLegacyAutocompleteModule as MatAutocompleteModule +} from '@angular/material/legacy-autocomplete'; +export { MatNativeDateModule } from '@angular/material/core'; +export { MatToolbarModule } from '@angular/material/toolbar'; +export { MatButtonToggleModule } from '@angular/material/button-toggle'; +export { + MatLegacySnackBarModule as MatSnackBarModule, + MatLegacySnackBar as MatSnackBar, + MatLegacySnackBarConfig as MatSnackBarConfig, + MatLegacySnackBarHorizontalPosition as MatSnackBarHorizontalPosition, + MatLegacySnackBarRef as MatSnackBarRef, + MatLegacySnackBarVerticalPosition as MatSnackBarVerticalPosition, + LegacyTextOnlySnackBar as TextOnlySnackBar +} from '@angular/material/legacy-snack-bar'; +export { MatLegacyTabsModule as MatTabsModule } from '@angular/material/legacy-tabs'; +export { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu'; +export { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; +export { + MatLegacyDialogModule as MatDialogModule, + MatLegacyDialogRef as MatDialogRef, + MatLegacyDialog as MatDialog, + MatLegacyDialogConfig as MatDialogConfig, + MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA + } from '@angular/material/legacy-dialog'; +export { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; +export { MatLegacyCardModule as MatCardModule } from '@angular/material/legacy-card'; +export { MatLegacyPaginatorModule as MatPaginatorModule } from '@angular/material/legacy-paginator'; +export { MatLegacyTableModule as MatTableModule } from '@angular/material/legacy-table'; +export { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; +export { MatDatepickerModule } from '@angular/material/datepicker'; +export { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; +export { MatLegacyInputModule as MatInputModule } from '@angular/material/legacy-input'; +export { + MatLegacyFormFieldModule as MatFormFieldModule, + MatLegacyFormField as MatFormField, + MAT_LEGACY_FORM_FIELD_DEFAULT_OPTIONS as MAT_FORM_FIELD_DEFAULT_OPTIONS +} from '@angular/material/legacy-form-field'; +export { MatGridListModule } from '@angular/material/grid-list'; +export { MatLegacyListModule as MatListModule } from '@angular/material/legacy-list'; +export { MatBadgeModule } from '@angular/material/badge'; +export { MatSidenavModule } from '@angular/material/sidenav'; +export { MatIconModule } from '@angular/material/icon'; +export { MatLegacyRadioModule as MatRadioModule } from '@angular/material/legacy-radio'; +export { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; +export { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material.module.ts new file mode 100644 index 0000000..14dd105 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/angular-material.module.ts @@ -0,0 +1,100 @@ +import { NgModule } from '@angular/core'; +/*import { + MatAutocompleteModule, MatBadgeModule, MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatChipsModule, MatDatepickerModule, + MatDialogModule, MatFormFieldModule, MatGridListModule, MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatPaginatorModule, + MatProgressSpinnerModule, MatRadioModule, MatSelectModule, MatSidenavModule, MatSnackBarModule, MatTableModule, MatTabsModule, MatToolbarModule, MatTooltipModule +} from './angular-material-index'; +*/ +import { CommonModule } from '@angular/common'; +import { MatNativeDateModule } from '@angular/material/core'; +import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/legacy-snack-bar'; +import { MatLegacyTabsModule as MatTabsModule } from '@angular/material/legacy-tabs'; +import { MatLegacyMenuModule as MatMenuModule } from '@angular/material/legacy-menu'; +import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; +import { MatToolbarModule } from '@angular/material/toolbar'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; +import { MatLegacyAutocompleteModule as MatAutocompleteModule } from '@angular/material/legacy-autocomplete'; +import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog'; +import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox'; +import { MatLegacyCardModule as MatCardModule } from '@angular/material/legacy-card'; +import { MatLegacyPaginatorModule as MatPaginatorModule } from '@angular/material/legacy-paginator'; +import { MatLegacyTableModule as MatTableModule } from '@angular/material/legacy-table'; +import { MatLegacyTooltipModule as MatTooltipModule } from '@angular/material/legacy-tooltip'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; +import { MatLegacyInputModule as MatInputModule } from '@angular/material/legacy-input'; +import { MatLegacyFormFieldModule as MatFormFieldModule } from '@angular/material/legacy-form-field'; +import { MatGridListModule } from '@angular/material/grid-list'; +import { MatLegacyListModule as MatListModule } from '@angular/material/legacy-list'; +import { MatBadgeModule } from '@angular/material/badge'; +import { MatSidenavModule } from '@angular/material/sidenav'; +import { MatIconModule } from '@angular/material/icon'; +import { MatLegacyRadioModule as MatRadioModule } from '@angular/material/legacy-radio'; +import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; +import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; + +@NgModule({ +/* imports: [ + MatSnackBarModule, + MatTabsModule, + MatMenuModule, + CommonModule, + MatButtonModule, + MatToolbarModule, + MatIconModule, + MatSidenavModule, + MatBadgeModule, + MatListModule, + MatGridListModule, + MatFormFieldModule, + MatInputModule, + MatSelectModule, + MatRadioModule, + MatDatepickerModule, + MatNativeDateModule, + MatChipsModule, + MatTooltipModule, + MatTableModule, + MatPaginatorModule, + MatCardModule, + MatCheckboxModule, + MatDialogModule, + MatAutocompleteModule, + MatButtonToggleModule + + // NgxMatSelectSearchModule + ],*/ + exports: [ + MatSnackBarModule, + MatTabsModule, + MatMenuModule, + MatButtonModule, + MatToolbarModule, + MatIconModule, + MatSidenavModule, + MatBadgeModule, + MatListModule, + MatGridListModule, + MatInputModule, + MatFormFieldModule, + MatSelectModule, + MatRadioModule, + MatDatepickerModule, + MatChipsModule, + MatTooltipModule, + MatTableModule, + MatPaginatorModule, + MatCardModule, + MatProgressSpinnerModule, + MatCheckboxModule, + MatDialogModule, + MatAutocompleteModule, + MatButtonToggleModule + // NgxMatSelectSearchModule + ], + providers: [ + MatDatepickerModule, + ] +}) + +export class AngularMaterialModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfig.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfig.ts new file mode 100644 index 0000000..6fa59f9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfig.ts @@ -0,0 +1,80 @@ +import { Column } from 'devextreme/ui/data_grid'; + +export interface ILookup { + dataSource: any; + valueExpr: string; + displayExpr: string; +} + +export const enum EN_Alignment { + right = 'right', + left = 'left', + center = 'center', +} + +export const enum EN_SortOrder { + asc = 'asc', + desc = 'desc', +} + + +export type Type_FractionDigits = null | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6; +export type Type_Datentyp = string | number | Date; + +export class ColumnConfig { + allowSorting = true; + allowEditing = true; + private _sortIndex: number; + public get sortIndex(): number { + return this._sortIndex; + } + public set sortIndex(value: number) { + this._sortIndex = value; + if (!this.sortOrder) this.sortOrder = EN_SortOrder.asc; + } + sortOrder: EN_SortOrder; + alignment: EN_Alignment; + cellTemplate: string; + visible: boolean = true; + visibleIndex: number; + fixed: boolean = false; + headerCellTemplate: string; + width: string; + name: string; + minWidth: number; + _widthFactor: number = 1; + allowHeaderFiltering: boolean = false; + allowFiltering: boolean = true; + dataType: string; + groupIndex: number; + cssClass: string; + subColumns: ColumnConfig[] = []; + + lookup: ILookup; + format: any; + calculateCellValue: Function; + calculateDisplayValue: Function | string; + calculateGroupValue: Function | string; + calculateSortValue: Function | string; + customizeText: Function | string; + + + public get widthFactor(): number { + return this.groupIndex !== undefined ? 0 : this._widthFactor; + } + + public set widthFactor(v: number) { + this._widthFactor = v; + if (this._widthFactor < 0) this.width = '' + (- this._widthFactor) + 'px'; + else this.width = this._widthFactor + '%'; + } + + + constructor(public caption: string = '', public dataField: string = '', widthFactor: number = 1, fractionDigits?: Type_FractionDigits) { + if (fractionDigits || fractionDigits === 0) { + if (fractionDigits >= 0) this.cellTemplate = 'numberTemplate_' + fractionDigits; + this.alignment = EN_Alignment.right; + } + this.widthFactor = widthFactor; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfiglist.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfiglist.ts new file mode 100644 index 0000000..c511a3e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/grid-config/columnconfiglist.ts @@ -0,0 +1,138 @@ +import { GridExportButtonWidth } from '../../consts'; +import { ColumnConfig, EN_Alignment, EN_SortOrder, Type_FractionDigits } from './columnconfig'; + + +export interface SortInfo { + caption: string; + sortIndex: number; + sortOrder: EN_SortOrder; +} + + +export class ColumnConfigList { + public overHeaders: ColumnConfig[] = []; + private _columns: ColumnConfig[] = []; + public get columns(): ColumnConfig[] { + return this._columns; + } + public set columns(value: ColumnConfig[]) { + this._columns = value; + this.exportWasAdded = false; + } + + public withExport: boolean = true; + public curOverHeader: ColumnConfig; + private exportWasAdded: boolean = false; + + constructor() { + } + + clear() { + this.overHeaders = []; + this.columns = []; + } + + add(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor); + return this.addColumn(column, dataField === undefined); + } + + addCurrency(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = 0): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits); + column.cellTemplate = 'currencyTemnplate_' + fractionDigits; + + return this.addColumn(column, dataField === undefined); + } + + addNumber(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = 0): ColumnConfig { + if (dataField && dataField.slice(-2) === 'Id') fractionDigits = -1; + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits); + column.dataType = 'number'; + return this.addColumn(column, dataField === undefined); + } + + addId(caption: string = '', dataField?: string, widthFactor: number = 1, fractionDigits: Type_FractionDigits = -1): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor, fractionDigits); + column.dataType = 'number'; + return this.addColumn(column, dataField === undefined); + } + + addBoolean(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor); + column.dataType = 'boolean'; + return this.addColumn(column, dataField === undefined); + } + + addDate(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor); + column.dataType = 'date'; + column.alignment = EN_Alignment.center; + return this.addColumn(column, dataField === undefined); + } + + addDateTime(caption: string = '', dataField?: string, widthFactor: number = 1): ColumnConfig { + const column: ColumnConfig = new ColumnConfig(caption, dataField, widthFactor); + column.dataType = 'datetime'; + column.alignment = EN_Alignment.center; + return this.addColumn(column, dataField === undefined); + } + + private addColumn(column: ColumnConfig, overheader: boolean = false): ColumnConfig { + const arColums: ColumnConfig[] = overheader ? this.overHeaders : this.columns; + if (overheader) { + column.alignment = EN_Alignment.center; + this.curOverHeader = column; + } else { + if (this.curOverHeader) this.curOverHeader.subColumns.push(column); + } + arColums.push(column); + return column; + } + + //autorecalc after each add + recalcWidth(addAdditionalColumnForExport: boolean = true) { //Calculate the weighted width based on the widthFactor. + if (this.withExport && this.columns[this.columns.length - 1].alignment === EN_Alignment.right && !this.exportWasAdded && addAdditionalColumnForExport) { + this.add('', '', -GridExportButtonWidth); //last column for export + } + this.exportWasAdded = true; + + const totalWidthFactor: number = this.columns.reduce((sum, col) => sum + (col.visible && col.widthFactor > 0 ? col.widthFactor : 0), 0); + if (totalWidthFactor === 0) return; + const widthFactor_1percent: number = 100 / totalWidthFactor; //The total value may be max 100%; buffer - 0.01 + + let countPosWidth = 0; + this.columns.forEach(col => { + if (col.visible && col.widthFactor > 0) { + col.widthFactor = this.roundToTwo(col.widthFactor * widthFactor_1percent); + countPosWidth++; + } + }); + const delta = (100 - this.columns.reduce((sum, col) => sum + (col.visible && col.widthFactor > 0 ? col.widthFactor : 0), 0)); + + for (let i = this.columns.length - 1; i >= 0; i--) { + if (this.columns[i].visible && this.columns[i].widthFactor > 0) { + this.columns[i].widthFactor += delta; + break; + } + } + } + + roundToTwo(num: number, places = 2): number { + return Math.round((num + Number.EPSILON) * Math.pow(10, places)) / Math.pow(10, places); + } + + public setSorting(sortInfos: SortInfo[]) { + for (let inx = 0; inx < this.columns.length; inx++) { + const col = Object.assign(new ColumnConfig(), this.columns[inx]); + const sortInfo = sortInfos.find(el => el.caption === col.caption); + if (sortInfo) { + col.sortIndex = sortInfo.sortIndex; + col.sortOrder = sortInfo.sortOrder; + } else { + col.sortIndex = undefined; + col.sortOrder = undefined; + } + this.columns[inx] = col; + } + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.html new file mode 100644 index 0000000..ca3ee3e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.html @@ -0,0 +1,46 @@ +
+ + +
+ +
+ + + + + + + +
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.scss new file mode 100644 index 0000000..71a0bdf --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.scss @@ -0,0 +1,282 @@ +@import 'hr-core-consts'; + +.HRD_datetimepicker { + padding-top: 1px; + position: relative; + width: 100%; + height: auto; + // align-items: baseline; + // padding-bottom: 10px; + display: grid; + grid-template-columns: minmax(1px, 1fr); + grid-template-rows: minmax(auto, 0.65em) 1fr; //0.65em //10px + grid-template-areas: "dx-datebox-label""dxDateBox" +} + +.dxDateBox { + grid-area: dxDateBox; + background-color: transparent; + display: block; + // height: 28px; +} + +.dx-icon { + font-size: 24px; +} + +// ::ng-deep .dx-show-clear-button .dx-icon-clear { +// color: #000; +// background-color: white; +// /* background-color: #c2c2c2de; */ +// border-radius: 50%; +// position: absolute; +// top: 50%; +// margin-top: -9px; +// width: 16px; +// height: 16px; +// background-position: 0 0; +// background-size: 16px 16px; +// padding: 0; +// font-size: 10px; +// /* text-align: center; */ +// /* line-height: 10px; */ +// } + +::ng-deep .HRD_datetimepicker .dx-dropdowneditor-button .dx-button-content { + position: absolute; + left: -4px; +} + +::ng-deep .HRD_datetimepicker .dx-state-disabled .dx-dropdowneditor-button .dx-button-content { + height: 100%; + display: table-cell; + color: grey; + background-color: #0000; + -webkit-box-shadow: none; + box-shadow: none; +} +::ng-deep .HRD_datetimepicker .dx-texteditor-input { + height: auto; + padding-top: 6.3px !important; + padding-bottom: 5.1px !important; + margin: 0; + background-color: #0000; + font-size: 14px; + color: unset; +} + + +.dx-state-disabled .dx-widget, +.dx-state-disabled.dx-widget { + opacity: unset; //$hrColor-Alpha_Disabled; + color: rgba(0, 0, 0, $hrColor-Alpha_Disabled); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-touch-callout: none; + cursor: default; + background-image: linear-gradient(to right, rgba(0, 0, 0, .42) 0, rgba(0, 0, 0, .42) 33%, transparent 0); + background-position: bottom; + background-size: 4px 1px; + background-repeat: repeat-x +} + +.dx-datebox-label { + grid-area: dx-datebox-label; + color: rgba(0, 0, 0, 0.54); + top: 1.25em; + left: 0; + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 10px; + pointer-events: none; + // width: 133.33333%; + white-space: nowrap; + display: block; + text-overflow: ellipsis; + overflow: hidden; + cursor: default; + font-stretch: 100%; + font-weight: 400; + text-size-adjust: 100%; + visibility: visible; + +} + +::ng-deep .HRD_datetimepicker .dx-texteditor.dx-state-focused:before { + border-bottom: grey; + border-width: 1px; + outline-width: 0em; + transform: translateY(-1.34375em) scale(.75); +} + +::ng-deep .dx-calendar-cell.dx-calendar-selected-date span, +.dx-calendar-cell.dx-calendar-selected-date.dx-calendar-today span { + color: #fff; + background-color: $hrColor-DarkBlue; + font-weight: 400; +} + +::ng-deep .dx-calendar-navigator .dx-button { + height: 100%; + display: table-cell; + background-color: #0000; + color: $hrColor-DarkBlue; + -webkit-box-shadow: none; + box-shadow: none; +} + +::ng-deep .dx-datebox-wrapper-calendar .dx-button +// ::ng-deep .dx-datebox-wrapper-calendar .dx-timeview-hourarrow +// ::ng-deep .dx-datebox-wrapper-calendar .dx-timeview-minutearrow + { + color: $hrColor-DarkBlue; +} + +::ng-deep .dx-datebox-wrapper-calendar .dx-button-today { + color: $hrColor-Red; +} + + +::ng-deep .dx-datebox-wrapper-calendar .dx-calendar-cell.dx-calendar-today { + font-weight: 900; + color: $hrColor-LightBlue; +} + + + +::ng-deep .dx-show-clear-button .dx-clear-button-area { + width: 16px; + min-width: 16px; + right: -15px; +} + +::ng-deep .dx-calendar-navigator-previous-month.dx-button .dx-icon, +::ng-deep .dx-calendar-navigator-previous-view.dx-button .dx-icon { + color: $hrColor-DarkBlue; +} + +::ng-deep .dx-calendar-navigator-next-month.dx-button .dx-icon, +::ng-deep .dx-calendar-navigator-next-view.dx-button .dx-icon { + color: $hrColor-DarkBlue; +} + +::ng-deep .dx-texteditor.dx-editor-underlined.dx-state-disabled:after, +::ng-deep .dx-texteditor.dx-editor-underlined.dx-state-readonly.dx-state-hover:after, +::ng-deep .dx-texteditor.dx-editor-underlined.dx-state-readonly:after { + border-bottom-style: none; +} + +//------------------------------- +::ng-deep .dx-placeholder { + color: rgba(0, 0, 0, 0.54); + font-size: 14px; +} + +.hs_label_invalid, +::ng-deep .dx-invalid .dx-placeholder, +::ng-deep .hs_label_invalid .dx-placeholder { + color: rgb(244, 67, 54); +} + + + +// ::ng-deep .dx-state-focused .dx-placeholder { +// color: red; +// } + + +::ng-deep .HRD_datetimepicker .dx-state-focused .dx-dropdowneditor-input-wrapper { + padding-bottom: 2px; +} + +::ng-deep .dx-dropdowneditor-input-wrapper, +::ng-deep .dx-state-disabled .dx-dropdowneditor-input-wrapper { + padding-bottom: 1px; +} + +::ng-deep .dx-texteditor.dx-editor-underlined.dx-state-hover:after { + border-bottom: 1px solid rgba(0, 0, 0, .42); +} + +::ng-deep .HRD_datetimepicker .dx-texteditor.dx-editor-underlined.dx-state-focused:after { + border-bottom: 2px solid rgb(120, 183, 229); +} + +::ng-deep .HRD_datetimepicker .dx-texteditor.dx-editor-underlined.dx-invalid:after, +::ng-deep .HRD_datetimepicker .dx-texteditor.dx-editor-underlined.hs_label_invalid:after { + border-bottom-color: rgb(244, 67, 54); +} + + +.dx-invalid.dx-texteditor.dx-state-focused:before { + border: 0px none; +} + +.hs_label { + margin-top: -3px; + // height: 0.84375em; + height: 0.864em; + transform: scale(0.75) perspective(100px) translateZ(0.001px); + // transform: translateY(-1.28125em) scale(0.75) perspective(100px) translateZ(0.001px); + width: 133.33333%; + margin-left: -17%; + font-size: 14px; + overflow: inherit; +} + +// ::ng-deep .dx-state-focused .dx-placeholder { +// width: 133.33333%; +// } + + +.hs_label_focused { + color: rgb(120, 183, 229); +} + + +::ng-deep .HRD_datetimepicker .dx-invalid-message>.dx-overlay-content { + transform: none !important; + padding: 0 !important; + top: 21px !important; + background: white; + font-size: .85em; + color: rgb(244, 67, 54); +} + +::ng-deep .HRD_datetimepicker .dx-icon-close { + font-size: 14px; + font-family: Material Icons; +} + +::ng-deep .HRD_datetimepicker .dx-state-disabled .dx-icon-close { + color: rgba(11, 58, 98, 0.4); +} + +::ng-deep .HRD_datetimepicker .dx-icon-event { + // color: rgba(11, 58, 98, 0.84); //$hrColor-DarkBlue + color: rgba(0, 0, 0, 0.54); + +} + +::ng-deep .HRD_datetimepicker .dx-state-disabled .dx-icon-event { + color: rgba(0, 0, 0, 0.26); +} + +::ng-deep .HRD_datetimepicker .dx-icon-close:before { + content: "\e5cd"; +} + +::ng-deep .HRD_datetimepicker .dx-editor-underlined .dx-texteditor-buttons-container>.dx-button.dx-button-mode-text { + margin: 0; +} + +::ng-deep .HRD_datetimepicker .dx-invalid.dx-texteditor.dx-show-invalid-badge .dx-texteditor-input-container:after { + display: none; +} + + +// ::ng-deep .HRD_datetimepicker .dx-texteditor.dx-editor-underlined .dx-placeholder::before, +// ::ng-deep .HRD_datetimepicker .dx-texteditor.dx-editor-underlined .dx-texteditor-input { +// padding: 5.6px 0 5px; //allign top of dx-input box to mat-input +// } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.spec.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.spec.ts new file mode 100644 index 0000000..06c3571 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HenselDateTimePickerComponent } from './hensel-date-time-picker.component'; + +describe('HenselDateTimePickerComponent', () => { + let component: HenselDateTimePickerComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ HenselDateTimePickerComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(HenselDateTimePickerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.ts new file mode 100644 index 0000000..8d3c4c6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.component.ts @@ -0,0 +1,292 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { AfterViewInit, Component, EventEmitter, Inject, Input, LOCALE_ID, OnDestroy, OnInit, Optional, Output, ViewChild } from '@angular/core'; +import { FormControl, FormGroup, NgForm } from '@angular/forms'; +import { DxDateBoxComponent } from 'devextreme-angular'; +import { DisabledDate, dxCalendarOptions } from 'devextreme/ui/calendar'; +import { Subscription } from 'rxjs'; +import { EN_DateFormats } from '../../consts'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { getDateFormat } from '../../utils'; + +export const enum EN_PickerTpe { + date = 1, + datetime = 2 +} + +@Component({ + // tslint:disable-next-line: component-selector + selector: 'hensel-date-time-picker', + templateUrl: './hensel-date-time-picker.component.html', + styleUrls: ['./hensel-date-time-picker.component.scss'], +}) + +export class HenselDateTimePickerComponent implements OnDestroy, AfterViewInit, OnInit { + private defDdateOutOfRangeMessage: string = 'core.hdatepicker.dateoutofrange'; + @ViewChild(DxDateBoxComponent) dateBox: DxDateBoxComponent; + public itemsControl = new FormControl(); + + private _placeholder: string = ''; + public get placeholder(): string { + return this._placeholder + (!!this._placeholder && this.required && ! this.disabled ? ' *' : ''); + } + + @Input() + public set placeholder(value: string) { + this._placeholder = value; + } + + public get date(): Date { + return this.itemsControl.value; + } + + @Input() + public set date(value: Date) { + if (!!value && !(value instanceof Date)) value = new Date(value); + if (this.pickerType === EN_PickerTpe.date) value?.setHours(0, 0, 0, 0); + this.itemsControl.setValue(value); + this.change(value); + } + + @Input() name: string; + private _displayFormat: string = 'datetime'; + public get displayFormat(): string { + return this._displayFormat; + } + @Input() + public set displayFormat(value: string) { + this._displayFormat = value; + this.date = this.date; //to consider date format + this.initCalendarOptions(); + } + + + @Output() public dateChange = new EventEmitter(); + @Input() required: boolean; + @Input() minDate: Date; + @Input() maxDate: Date; + private _canClear: boolean = true; + public get canClear(): boolean { + return this._canClear; + } + @Input() + public set canClear(value: boolean) { + this._canClear = value; + this.btnClear.visible = value; + } + @Input() stepMinute: number = 15; + + + private _disabledDates?: Array | ((data: DisabledDate) => boolean); + public get disabledDates(): Array | ((data: DisabledDate) => boolean) { + return this._disabledDates; + } + @Input() public set disabledDates(value: Array | ((data: DisabledDate) => boolean)) { + this._disabledDates = value; + this.initCalendarOptions(); + } + + private _showWeekNumbers: boolean = true; + public get showWeekNumbers(): boolean { + return this._showWeekNumbers; + } + @Input() public set showWeekNumbers(value: boolean) { + this._showWeekNumbers = value; + this.initCalendarOptions(); + } + + private _showTodayButton: boolean = true; + public get showTodayButton(): boolean { + return this._showTodayButton; + } + @Input() public set showTodayButton(value: boolean) { + this._showTodayButton = value; + this.initCalendarOptions(); + } + + @Input() customValidationMessage: string; + + private _dateOutOfRangeMessage: string = this.defDdateOutOfRangeMessage; + public get dateOutOfRangeMessage(): string { + return this._dateOutOfRangeMessage; + } + + @Input() + public set dateOutOfRangeMessage(value: string) { + this._dateOutOfRangeMessage = !value ? undefined /*this.defDdateOutOfRangeMessage*/ : value; + } + + public get getDisplayFormat(): string { + return this.displayFormat === 'date' ? 'date' : 'datetime'; + } + + public get formControlName(): string { + return 'henselDateTimePickerControl_' + this.name; + } + + public get pickerType(): EN_PickerTpe { + if (this.getDisplayFormat === 'date') { + return EN_PickerTpe.date; + } else { + return EN_PickerTpe.datetime; + } + } + + public get timeIsShown(): boolean { + return this.pickerType === EN_PickerTpe.datetime; + } + + public get parentFormGroup(): FormGroup { + const group = {}; + group[this.formControlName] = this.itemsControl; + return this.parent ? this.parent.form : new FormGroup( + group + ); + } + + private _parent: NgForm; + public get parent(): NgForm { + return this._parent; + } + @Input() + public set parent(value: NgForm) { + this._parent = value; + // if (this._parent && this.required !== undefined && this._selectedItemIds.length ==== 0) this.parent.control.setErrors({ required: true }); + if (!this.parent) this.parent = this._parentForm; + this.itemsControl.markAllAsTouched(); + if (this._parent) { + this.parent.control.addControl(this.formControlName, this.itemsControl); + this.hsRequiredsubscription = this.parent.valueChanges.subscribe(() => { if (!this.isValid) this.parent.control.setErrors({ required: true }); }); + + +/* it is working without special code + this.hsRequiredsubscription = this.parent.valueChanges.subscribe(() => { + if (this.required && this.empty()) this.parent.control.setErrors({ required: true }); + if (!this.empty()) { + if (this.minDate && this.date < this.minDate) this.parent.control.setErrors({ matDatepickerMin: true }); + if (this.maxDate && this.date > this.maxDate) this.parent.control.setErrors({ matDatepickerMax: true }); + } + });*/ + } + } + + private _disabled: boolean = false; + public get disabled(): boolean { + return this._disabled; + } + + @Input() + public set disabled(value: boolean) { + if (value) this.itemsControl.disable(); + else this.itemsControl.enable(); + + this._disabled = value; + } + + private _autofocus: any = false; + public get autofocus(): any { + return this._autofocus; + } + @Input() + public set autofocus(value: any) { + this._autofocus = value; + } + + + public hasFocus: boolean = false; + + public btnClear: any = { + icon: 'close', + stylingMode: 'text', + tabIndex: -1, + onClick: () => { this.date = null; } + }; + + public calendarOptions: dxCalendarOptions = {}; + + private hsRequiredsubscription: Subscription; + + constructor( + public translate: HenselTranslateService, + @Optional() private _parentForm: NgForm, + @Inject(LOCALE_ID) private localeId: string + ) { } + + ngOnInit(): void { + this.initCalendarOptions(); + setTimeout(() => { + if (!this.parent) this.parent = this._parentForm; + }, 0); + } + + initCalendarOptions() { + this.calendarOptions = { + showWeekNumbers: this.showWeekNumbers, + showTodayButton: this.pickerType === EN_PickerTpe.datetime ? false : this.showTodayButton, + disabledDates: this.disabledDates + }; + } + + + isEmpty = () => { + return !(this.date); + } + + + public get pickerDisplayFormat(): string { + return getDateFormat(this.localeId, this.pickerType === EN_PickerTpe.datetime ? EN_DateFormats.DateTime : EN_DateFormats.Date); + } + + + public get isValid() { + return this.isNotEmpty && this.isValidDate(); + } + + change(e) { + if (this.parent?.control) { + this.parent.control.updateValueAndValidity(); + // setTimeout(() => {this.parent.control.updateValueAndValidity();}, 5000); + } + } + + public inputChanged(e) { + this.change(e); + this.date = this.date; //to return date w/o time if type of picker Date + this.dateChange.emit(this.date); + } + + + public get isNotEmpty(): boolean { + // wenn disabled: keine Validation anzeigen (also valid) + // wenn enabled: wenn required: date != null and != undefined + // wenn enabled: wenn nicht required: valid + return this.disabled || (!this.required || !this.isEmpty()) ; + } + + + public isValidDate() { + return this.disabled || !this.customNotValid() && (this.isEmpty() || ((!this.minDate || this.minDate <= this.date) && (!this.maxDate || this.maxDate >= this.date))); + } + + focused(el: any) { + const res = document?.activeElement?.parentElement?.parentElement?.parentElement?.parentElement === el.element.nativeElement; + return res; + } + + + public customNotValid(): boolean { + return !!this.customValidationMessage; + } + + ngAfterViewInit(): void { + const elInput = this.dateBox.instance.field(); // input element + (elInput).autofocus = this.autofocus || (this.autofocus === ''); //wenn set attribute autofocus it is == '' + } + ngOnDestroy(): void { + if (this.hsRequiredsubscription) this.hsRequiredsubscription.unsubscribe(); + } + + doKeyDown(e, tocheck: boolean): void { + if (e.event.keyCode === keycode.ESCAPE && tocheck) e.event.stopPropagation(); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.module.ts new file mode 100644 index 0000000..18800e6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-date-time-picker/hensel-date-time-picker.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; +import { AngularMaterialModule } from '../angular-material.module'; +import { HenselDateTimePickerComponent } from './hensel-date-time-picker.component'; +import { DxDateBoxModule, DxValidatorModule, DxValidationSummaryModule } from 'devextreme-angular'; +import { TranslateModule } from '@ngx-translate/core'; + + +@NgModule({ + declarations: [HenselDateTimePickerComponent], + imports: [ + CommonModule, + AngularMaterialModule, + FormsModule, + ReactiveFormsModule, + DxDateBoxModule, + DxValidatorModule, + DxValidationSummaryModule, + TranslateModule.forChild() + ], + exports: [HenselDateTimePickerComponent] +}) +export class HenselDateTimePickerModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.html new file mode 100644 index 0000000..c38c7e3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.html @@ -0,0 +1,29 @@ +
+
+ {{caption}} +
+
+ + + + + {{icon}} + +
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.scss new file mode 100644 index 0000000..eae15f5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.scss @@ -0,0 +1,110 @@ +@import 'hr-core-consts'; + + +.hensel-dnd { + height: calc(100% - 4px); + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + position: relative; + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-rows: auto minmax(0, 1fr); // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-column-gap: 0px; + grid-template-areas: "caption""dnd" +} + +.dnd-title { + grid-area: caption; + padding-bottom: 10px; +} + +.font-disabled { + color: rgba(0, 0, 0, 0.54) +} + +.font-enabled { + color: rgba(0, 0, 0, 0.87); + font-weight: bold; +} + + +.dnd-upload-container { + grid-area: dnd; + cursor: default; + height: calc(100% - 4px); + border-radius: $hrBorder-radius-big; + background-color: rgba(198, 231, 253, 0.3); +} + +.dnd-upload-container-disabled { + opacity: 0.6; + background-color: transparent; + border: 2px dashed gray; +} + +.dnd-upload-container-disabled-btn { + opacity: 1; + background-color: transparent; + border: 2px dashed gray; +} + +.dnd-upload-container-enabled { + opacity: 0.8; + border: 2px dashed #1C8ADB; +} + +.dnd-upload-container-enabled-btn { + opacity: 1; + border: 2px dashed #1C8ADB; +} + +.dnd-upload-container-enabled:hover { + cursor: pointer; + opacity: 1; +} + + +.dnd-upload-icon { + width: auto; + height: auto; + opacity: inherit; + cursor: inherit; + display: flex; + justify-content: center; + align-items: center; + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.dnd-upload-button { + cursor: pointer; +} + + +.overlay { + /* Height & width depends on how you want to reveal the overlay (see JS below) */ + height: calc(100% - 72px); + margin-top: 47px; + margin-bottom: 25px; + width: 0; + position: fixed; + /* Stay in place */ + z-index: 1; + /* Sit on top */ + left: 0; + top: 0; + background-color: #9ecbec; + /* Black fallback color */ + background-color: #9ecbec; + /* Black w/opacity */ + opacity: 0.8; + overflow-x: hidden; + /* Disable horizontal scroll */ + transition: 0.1s; + /* 0.5 second transition effect to slide in or slide down the overlay (height or width, depending on reveal) */ +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.ts new file mode 100644 index 0000000..08dc26b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.component.ts @@ -0,0 +1,111 @@ +import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; + +@Component({ + selector: 'app-hensel-drag-n-drop', + templateUrl: './hensel-drag-n-drop.component.html', + styleUrls: ['./hensel-drag-n-drop.component.scss'] +}) +export class HenselDragNDropComponent implements OnInit { + + @Input() accept: string = '.jpg,.png'; + @Input() multiple: boolean = true; + @Input() caption: string; + @Input() captionClass: string = ''; + @Input() buttonText: string; + @Input() icon: string = 'cloud_upload'; + @Input() iconSizePrc: number = 1; + @Input() onFileUpload: (any) => void; + @Input() title: string; + @Input() button: string = ''; + @Input() disabled: boolean = false; + @Input() uploadAsBase64: boolean = false; + @Input() onStartingUpload: (any) => void; + @Input() onStartingUploadAsync: () => Promise; + @Input() onFinishUpload: () => void; + @ViewChild('fileInput') fileInput: ElementRef; + + public fontSize: string = '100%'; + + + constructor() { + this.readMultipleFiles = this.readMultipleFiles.bind(this); + this.startUpload = this.startUpload.bind(this); + } + + ngOnInit() { + } + + selectFiles() { + if (!this.disabled) this.fileInput.nativeElement.click(); + } + + private uploadFile(file: File, indx: number, lastIndx: number) { + if (file) { + if (this.uploadAsBase64) { + const fr = new FileReader(); // FileReader instance + fr.onload = () => { + const fileBase64: string = fr.result.toString(); + if (this.onFileUpload) this.onFileUpload({ fileBase64: fileBase64, filename: file.name, index: indx, lastIndex: lastIndx }); + /* + const img = new Image(); + img.src = fileBase64; + img.onload = () => { + this.catalogDataService.newImage({ name: file.name, image: fileBase64.split(',')[1] }, img.width, img.height, indx, this.imageGrid); + }; + */ + }; + fr.readAsDataURL(file); //Read file as Binary + } else if (this.onFileUpload) this.onFileUpload(file); + } else { + alert('File not selected or browser incompatible!'); + } + } + + + public async startUpload(files: FileList) { + const _files: FileList = { length: files.length, item: null }; + Object.assign(_files, files); //must save clone of files, bcs orig get lost + if (this.onStartingUploadAsync) await this.onStartingUploadAsync(); + // this.readMultipleFiles(_files); + if (!this.onStartingUpload) this.readMultipleFiles(_files); + else { + const noOfFiles = _files.length; + for (let inx = 0; inx < noOfFiles; inx++) { + if (this.validExtension(_files[inx].name)) { + this.onStartingUpload(() => this.readMultipleFiles(_files)); + return; + } + } + } + } + + + public readMultipleFiles(files: FileList) { + const noOfFiles = files.length; + let startInx: number = 0; + for (let inx = 0; inx < noOfFiles; inx++) { + if (!this.validExtension(files[inx].name)) continue; + // if (startInx === 0 && this.onStartingUpload) this.onStartingUpload(); + this.uploadFile(files[inx], startInx, noOfFiles - 1); + if (!this.multiple) break; + startInx++; + } + if (this.onFinishUpload) this.onFinishUpload(); + } + + validExtension(name: string) { + if (!this.accept) return true; + let exts: string; + if (this.accept.toLowerCase() === 'image/*') exts = ',.jpg,.jpeg,.png,.tiff,.bmp,'; + else exts = ',' + this.accept.replace(' ', '').toLocaleLowerCase() + ','; + const re: RegExp = /(?:\.([^.]+))?$/; + const ext = re.exec(name)[1].toLocaleLowerCase(); + return exts.indexOf(',.' + ext + ',') !== -1; + } + + + calcFontSize(width: number, height: number) { + return ((Math.min(width, height) - 4) / 12 * 100 * this.iconSizePrc).toFixed() + '%'; + + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.module.ts new file mode 100644 index 0000000..a3e74e8 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-drag-n-drop/hensel-drag-n-drop.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HenselDragNDropComponent } from './hensel-drag-n-drop.component'; +import { HenselDnDDirective } from '../../directives/hensel-dnd.directive'; +import { AngularMaterialModule } from '../../components/angular-material.module'; +import { TranslateModule } from '@ngx-translate/core'; + +@NgModule({ + imports: [ + CommonModule, + AngularMaterialModule, + TranslateModule.forChild(), + HenselDnDDirective + ], + exports: [HenselDragNDropComponent], + declarations: [ + HenselDragNDropComponent, + ] +}) +export class HenselDragNDropModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.html new file mode 100644 index 0000000..a68d7bd --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.html @@ -0,0 +1,77 @@ + + + + + {{label}} + + +
+ {{hint | translate}} +
+
+ {{getIcon()}} + + + + + + + + + + + + {{errorMessageFn(value)}} + +
+ + +
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.scss new file mode 100644 index 0000000..776a27a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.scss @@ -0,0 +1,21 @@ +@import 'hr-core-consts'; +.hs_div { + outline: none; + pointer-events: auto; +} + + +.hs_pointer { + cursor: pointer; +} + + + +::ng-deep .hs_form:has(.material-icons.ng-star-inserted) .mat-form-field-suffix { + bottom: 8px; +} + + +::ng-deep .hs_form.no-placeholder .mat-form-field-infix { + border-top-width: 0px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.ts new file mode 100644 index 0000000..50db20a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/hensel-input.component.ts @@ -0,0 +1,316 @@ +import { CommonModule } from '@angular/common'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Optional, Output, Self, ViewChild } from '@angular/core'; +import { ControlValueAccessor, FormControl, FormGroup, FormsModule, NgControl, NgForm, ReactiveFormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import { DxButtonModule, DxDataGridModule, DxTooltipModule } from 'devextreme-angular'; +import { Subscription } from 'rxjs'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { + MatAutocompleteTrigger, MatFormField +} from '../angular-material-index'; +import { AngularMaterialModule } from '../angular-material.module'; +import { NgxMaskDirective, NgxMaskPipe } from 'ngx-mask'; +import { LocaleService } from '@app_core/services/localization/locale.service'; +import { HenselValidator } from '@app_core/validators/hensel-validator.directive'; +import { HenselMaskDecimalDirective } from '@app_core/directives/hensel-decimal.directive'; + + +@Component({ + // tslint:disable-next-line: component-selector + selector: 'hensel-input', + templateUrl: './hensel-input.component.html', + styleUrls: ['./hensel-input.component.scss'], + standalone: true, + imports: [ + CommonModule, + AngularMaterialModule, + FormsModule, + ReactiveFormsModule, + DxButtonModule, + DxTooltipModule, + TranslateModule, + DxDataGridModule, + NgxMaskDirective, + NgxMaskPipe, + HenselValidator, + HenselMaskDecimalDirective + ] +}) + +export class HenselInputComponent implements OnInit, AfterViewInit, OnDestroy { + + @ViewChild(MatAutocompleteTrigger) autocompleteTrigger: MatAutocompleteTrigger; + @ViewChild('cbInput') cbInput: ElementRef; + @ViewChild('hs_matformfield') hsMatFormField: MatFormField; + @ViewChild('hensel_input') hsElementRef: ElementRef; + + private hsRequiredsubscription: Subscription; + private _required: boolean; + public get required(): boolean { + return this._required; + } + @Input() public set required(value: boolean) { + if (typeof (value) === 'string') value = value !== 'false'; + this.setRequired(value); + this.updateParent(); + } + + private _disabled: boolean = false; + public get disabled(): boolean { + return this._disabled; + } + + @Input() public set disabled(value: boolean) { + this.setDisable(typeof (value) === 'string' ? value !== 'false' : value); + } + + @Input() public validate: (val: any) => boolean; + + public _value: any = null; + @Input() public set ngModel(val: any) { + this.setValueInternally(val, true); + this.lastValue = this._value; + } + public get ngModel(): any { + return this.value; + } + + @Output() public get value(): any { + return this._value; + } + + @Output() ngModelChange = new EventEmitter(); + @Input() label: string; + @Input() placeholder: string; + @Input() width: string = '100%'; + @Input() backgroundColor: string = 'inherit'; + + @Input() hint: string; + @Input() type: string = 'text'; + @Input() displayIconFn: (comp: HenselInputComponent) => string; + @Input() id: string = ''; + @Input() name: string = ''; + @Input() public hsClass: string = ''; + @Input() autofocus: any = false; + @Input() maxlength: number; + @Input() readonly: boolean; + @Input() autocomplete: string = ''; + + private _parent: NgForm = null; + public get parent(): NgForm { + return this._parent; + } + + @Input() + public set parent(value: NgForm) { + this._parent = value ?? this._parentForm; + this.hsRequiredsubscription?.unsubscribe(); + this.hsRequiredsubscription = this.parent?.valueChanges.subscribe(() => this.checkRequired()); //take cares about form.invalid, if the component invalid + this.markAsTouchedDirty(); + } + + + private _canClear: boolean = true; + public get canClear(): boolean { + return this._canClear; + } + @Input() public set canClear(value: boolean) { + this._canClear = value; + } + @Input() public defaultValue: any; + @Output() public focus = new EventEmitter(); + @Output() public blur = new EventEmitter(); + @Input() public tabindex: number = 0; + @Input() public errorMessageFn: ((value: any) => string); + + private _title: string = ''; + public get title(): string { + let resTitle = this._title; + // if (!resTitle && this.cbInput?.nativeElement?.clientWidth < this.cbInput?.nativeElement?.scrollWidth) resTitle = this.displayFn(this._value); + return resTitle; + } + @Input() public set title(value: string) { + this._title = value; + } + + //***** Using Mask derictive + @Input() mask: string; + @Input() suffix: string = ''; + @Input() prefix: string = ''; + @Input() decimalMarker: string; + @Input() thousandSeparator: string; + @Input() leadZero: boolean = true; + @Input() separatorLimit: string = '0'; + + + + //***** Using Hensel validator + @Input() greater: number; + @Input() notless: number; + @Input() notgreater: number; + @Input() less: number; + + //***** Using Hensel decimal directive + @Input() henselDecimal: number; + @Input() henselDecimalAllowEmpty: boolean; + + + public itemsControl = new FormControl(); + public hasFocus: boolean = false; + private _lastValue: any; + public get lastValue(): any { + return this._lastValue; + } + public set lastValue(value: any) { + this._lastValue = value; + } + public showInputField: boolean = true; + public initialised: boolean = false; + + private get formGroup(): FormGroup { + return this.parent?.control; + } + + public computedBackgroundColor: string; + + constructor( + public translate: HenselTranslateService, + public localeService: LocaleService, + @Optional() private _parentForm?: NgForm, + // @Self() public ngControl?: NgControl + ) { + } + + ngOnInit() { + setTimeout(() => { + if (!this.parent) this.parent = this._parent; + }, 0); + } + + ngAfterViewInit(): void { + setTimeout(() => { + this.initialised = true; + this.computedBackgroundColor = this.getBackgroundColor(this.hsElementRef.nativeElement); + }, 0); + } + + + private setDisable(value: boolean) { + this._disabled = value; + if (this.disabled) { + this.itemsControl.disable(); + } else this.itemsControl.enable(); + } + + + private setRequired(value: boolean) { + this._required = value; + } + + + private setValueInternally(value: any, externally = false) { + if (value === this._value) return; + this._value = value; + this.itemsControl.setValue(this._value); + if (externally) this.updateParent(); //otherwise if set programatically parent form doesn't change valid status + } + + + getBackgroundColor(htmlElemet: any): string { + const backgroundColor = window.getComputedStyle(htmlElemet, null).getPropertyValue('background-color'); + if (backgroundColor !== 'rgba(0, 0, 0, 0)' || !htmlElemet?.parentElement) return backgroundColor; + else return this.getBackgroundColor(htmlElemet.parentElement); + } + + + checkRequired() { + if (this.requiredError()) this.formGroup?.setErrors({ required: true }); + } + + requiredError(): boolean { + let req = this.required; + return !this.disabled && req !== undefined && req !== false && this.isEmpty(); + } + + + public isEmpty(): boolean { + return !this._value; + } + + + + public takeFocus = () => { //such declaration because of binding + this.hasFocus = true; + this.focus.emit(this); + } + + + public leaveFocus = () => { //such declaration because of binding + this.hasFocus = false; + this.blur.emit(this); + } + + public updateParent() { + //this.formGroup?.updateValueAndValidity(); + } + + + + // public clickClear($event: any) { + // $event.stopPropagation(); + // if (/*this.dropDownState === EN_DropDownState.Opened ||*/ this.lastFilter) { + // setTimeout(() => { + // this.itemsControl.setValue(''); + // this.cbInput?.nativeElement?.focus(); //to call opendropdown after close drop down if minlength>0 + // }, 300); + // } else { + // this.lastValue = this._value; + // if (this.defaultValue !== undefined && this.defaultValue !== null) this.setValueInternally([this.defaultValue]); + // else this.setValueInternally([]); + // this.selectionDone(); + // } + // } + + + ngOnDestroy(): void { + this.hsRequiredsubscription?.unsubscribe(); + } + + getIcon(): string { + if (this.displayIconFn) return this.displayIconFn(this); + return null; + } + + public markAsDirty() { + if (this.hsMatFormField?._control?.ngControl?.control) { + this.hsMatFormField._control.ngControl.control.markAsDirty(); + this.updateParent(); + } + } + + + public markAsTouched() { + if (this.hsMatFormField?._control?.ngControl?.control) { + this.hsMatFormField._control.ngControl.control.markAsTouched(); + this.updateParent(); + } + } + + + public markAsTouchedDirty() { + if (this.hsMatFormField?._control?.ngControl?.control && this.required && this.isEmpty()) { + this.hsMatFormField._control.ngControl.control.markAsTouched(); + this.hsMatFormField._control.ngControl.control.markAsDirty(); + this.updateParent(); + } + } + + onChange(value: any) { + if (value === this.value) return; + this._value = value; + console.log('--',value); + this.updateParent(); + this.ngModelChange.emit(value); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/readme.txt b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/readme.txt new file mode 100644 index 0000000..383e1b1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-input/readme.txt @@ -0,0 +1,24 @@ +Inputs: +placeholder (String): A placeholder value for your mat-select +selectPlaceholder(String): Placeholder for options filtering +options (Array of objects): Options object to be listed +selectedOptions (Array of Strings): To pre-populate or preselect options +display (String): Property of every option for display in dropdown +value (String): Property of every option to be returned on option selection; +required (Boolean): To make your mat-field required. Default : false; +multiple (Boolean): Able to select multiple or single. Default: true; +disabled (Boolean): To disable the mat-field. default: false; +appearance (String): Appearance of your mat-field. Supported options: 'legacy' | 'standard' | 'fill' | 'outline'; +formControl (String): If you’re using Angular reactive form, bind your formControl with mat-select-autocomplete output +showErrorMsg (Boolean): Whether show error message or not. Default: false; +errorMsg (String): Custom error message. Default: ‘Field is required’ +labelCount (Number): Number of selected options to be shown in display of mat-select. Default: 1. + +Outputs: +selectionChange (EventEmitter): On every option selection, +this event would be emitted. You could capture the selected options values [Array of Strings] from this event param. + +ViewChild: +If you want to toggle mat-select-autocomplete from your own component event, +you need to import MultiselectComponent in the component and take it’s reference as ViewChild element (eg: matSelect). +Now you could trigger this.matSelect.toggle() to toggle the dropdown. \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.html new file mode 100644 index 0000000..9344960 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.html @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + +
+
+ {{ cell.column.caption | translate}} +
+
+ +
+ + + + + +
{{'core.hensel-selection.nohits' | translate}}
+
+ +
+ {{'core.hensel-selection.inputminsybols' | translate: {value: minFilterLength4Search} }} +
+
+ + + + + {{getIcon4Selected()}} + + + +
+
+
+ + + + +
+ +
{{'core.caption.all' | translate}}
+ +
+ + +
{{'core.hensel-selection.selectedfirst' | translate}}
+
+ + +
{{'core.btn.apply' | translate}}
+
+ + +
{{'core.btn.cancel' | translate}}
+
+
+ +
+ +
+ + {{displayIconFn(item.link)}} + {{ item[displayExpr] }} + +
+ {{displayIconFn(item.link)}} + {{ item[displayExpr] }} +
+
+
+
+
+ +
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.scss new file mode 100644 index 0000000..5597d4c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.scss @@ -0,0 +1,197 @@ +@import 'hr-core-consts'; + +// (If you use Bootstrap, you'll have to add an override to your css file to make the clear button show in input field) +// input[type=search]::-webkit-search-cancel-button { +// -webkit-appearance: searchfield-cancel-button; +// } + + +// confirm button in drop down layout +.buttonLayoutOk { + cursor: pointer !important; + top: 5px; + right: 5px; + margin-left: 5px; + border-width: 0; +} + +.buttonLayoutCancel { + cursor: pointer !important; + top: 5px; + right: 5px; + margin-left: 5px !important; + border-width: 0; +} + +.cbCheckedFirst { + cursor: pointer !important; + margin-top: 12px; + right: 20px; + margin-left: auto !important; + border-width: 0; + font-size: smaller; + position: relative; +} + +.hs_arrow { + position: relative; + top: 50%; + transform: translate(0%, -50%) !important; +} + +.hs_arrowheader { + cursor: pointer; + float: right; + top: -5px; +} + +.selected { + background-color: rgba(0, 0, 0, .12) !important; + color: $hrColor-LightBlue !important; // #3f51b5; +} + +//set font size and width of drop down window +// ::ng-deep .cdk-overlay-pane { +// width: auto !important; +// min-width: 200px; +// font-size: 14px; +// } + +//******************* +::ng-deep .hs_form .mat-form-field-subscript-wrapper { + z-index: 2; +} + +::ng-deep .hs_form .mat-form-field-infix { + display: flex; //get down array button in the same row +} + +.hs_autocomplete { + padding-right: 0px; + max-height: 300px !important; +} + +::ng-deep .hs_autocomplete .cbCheckedFirst .mat-checkbox-inner-container { + order: 1; +} + +::ng-deep .hs_autocomplete .buttonLayoutOk .dx-icon-check { + font-size: 18px !important; + font-weight: bold !important; + color: green !important; +} + + +//set font size for items of drop down +::ng-deep .hs_autocomplete .mat-option { + font-size: inherit; +} + +::ng-deep .hs_autocomplete .dx-button-content { + padding: 0px !important; +} + +//label's color for the checked checkboxes if changed mark color not used +::ng-deep .hs_autocomplete .mat-option.multi_selected:not(.mat-option-disabled):not(.changedLabelColor) { + //:not(.changed) + color: $hrColor-LightBlue !important; // #78b7e5; +} + +//label's color for the checked checkboxes if changed mark color used (changedLabelColor) +::ng-deep .hs_autocomplete .mat-option.multi_selected.changedLabelColor:not(.mat-option-disabled):not(.changed) { + color: $hrColor-LightBlue !important; // #78b7e5; +} + +//label's color for the changed checkboxes ifused (changedLabelColor) +::ng-deep .hs_autocomplete .mat-option.changed.changedLabelColor:not(.mat-option-disabled) { + color: $hrColor-Green !important; // #78b7e5; +} + +//checked check box filling's color for changed mark if used (changedCBColor) +::ng-deep .hs_autocomplete .mat-option.changed.changedCBColor .mat-checkbox-checked.mat-accent .mat-checkbox-background { + background-color: $hrColor-Green !important; //transparent; //#78b7e5; +} + +// check box frame's color for changed mark if used (changedCBColor) +::ng-deep .hs_autocomplete .mat-option.changed.changedCBColor:not(.mat-option-disabled) .mat-checkbox-frame { + border-color: $hrColor-Green; +} + +/* +//check box's check symbol color/style +::ng-deep .hs_autocomplete mat-option.changed:not(.mat-option-disabled) .mat-checkbox-checkmark-path { + stroke: red !important; + stroke-width: 3 !important; +} +*/ +// ::ng-deep input:read-only{ + +// } + +// ::ng-deep .hs_autocomplete .mat-form-field-underline:read-only { +// border-bottom-style: dotted; +// } + +// outlined symbols in items match to filter +::ng-deep .hs_autocomplete .hs_marked { + background-color: rgba(0, 0, 0, .22); +} + +::ng-deep .hs_grid .dx-datagrid-export-button .dx-icon-export-excel-button:before { + content: "\f001" !important; +} + +::ng-deep .hs_grid .dx-datagrid-export-button .dx-icon-export-excel-button { + font-size: 25px !important; + color: rgba(0, 0, 0, 0.45) !important; +} + +::ng-deep .hs_grid .dx-datagrid-export-button .dx-icon-xlsxfile:before { + content: "\f001" !important; +} + +::ng-deep .hs_grid .dx-datagrid-export-button .dx-icon-xlsxfile { + font-size: 25px !important; + color: rgba(0, 0, 0, 0.45) !important; +} + +::ng-deep .hs_grid .dx-button .dx-button-content { + left: 0px; // -4px; +} + + +.hs_grid_header { + // font-family: inherit !important; + font-size: 14px; + font-weight: normal; +} + +.hs_required .hs_grid_header { + color: red; +} + +::ng-deep .hs_required .dx-datagrid-nodata { + color: red; +} + +.hs_pointer { + cursor: pointer; +} + +.hs_div { + outline: none; + pointer-events: auto; +} + +.zoom { + transform: scale(0.2); +} + +::ng-deep .hs_form:has(.material-icons.ng-star-inserted) .mat-form-field-suffix { + bottom: 8px; +} + + +::ng-deep .hs_form.no-placeholder .mat-form-field-infix { + border-top-width: 0px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.ts new file mode 100644 index 0000000..8a9992e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/hensel-selection.component.ts @@ -0,0 +1,940 @@ +import { AfterViewInit, Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnInit, Optional, Output, ViewChild } from '@angular/core'; +import * as keycode from '@angular/cdk/keycodes'; +import { FormControl, FormGroup, FormsModule, NgForm, ReactiveFormsModule } from '@angular/forms'; +import { DxButtonModule, DxDataGridComponent, DxDataGridModule, DxTooltipModule } from 'devextreme-angular'; +import { Observable, Subscription } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { + MatAutocomplete, MatAutocompleteTrigger, MatFormField, MatOptionSelectionChange, _countGroupLabelsBeforeOption, + _getOptionScrollPosition +} from '../angular-material-index'; +import { CommonModule } from '@angular/common'; +import { AngularMaterialModule } from '../angular-material.module'; +import { TranslateModule } from '@ngx-translate/core'; + + +const enum EN_DropDownState { + Closed = 0, + Opened = 1, + EmptyFilter = 2, +} + +@Component({ + // tslint:disable-next-line: component-selector + selector: 'hensel-selection', + templateUrl: './hensel-selection.component.html', + styleUrls: ['./hensel-selection.component.scss'], + standalone: true, + imports: [ + CommonModule, + AngularMaterialModule, + FormsModule, + ReactiveFormsModule, + DxButtonModule, + DxTooltipModule, + TranslateModule, + DxDataGridModule + ] +}) + +export class HenselSelectionComponent implements OnInit, AfterViewInit, OnDestroy { + + @ViewChild(MatAutocompleteTrigger) autocompleteTrigger: MatAutocompleteTrigger; + @ViewChild('cbInput') cbInput: ElementRef; + @ViewChild('hs_panel') autocompleteScrollPanel: ElementRef; + @ViewChild('hs_toolbar') autocompleteToolbar: ElementRef; + @ViewChild('hs_matformfield') hsMatFormField: MatFormField; + @ViewChild('grid_hensel') grid_hensel: DxDataGridComponent; + @ViewChild('hensel_selection') hsElementRef: ElementRef; + + // the dataSource of selectable items + public EN_DropDownStateClosed: EN_DropDownState = EN_DropDownState.Closed; + + public _dataSource: any[] = []; + private _origDataSource: any[]; + private currentScrollTop: number = 0; + private hsRequiredsubscription: Subscription; + + private lastDisabled: boolean; + private lastShowSpinner: boolean; + + @Input() public set dataSource(value: any[]) { + this._origDataSource = value; + this.applyCustomFilterAsync(); + } + + @Input() public set reprepareImmedeately(value: boolean) { + if (value) { + this.applyCustomFilterAsync(); + setTimeout(() => { //to avoid change after chek error + this.reprepareImmedeatelyChange.emit(this.reprepareImmedeately); + }); + } + } + public get reprepareImmedeately() { return false; } + @Output() reprepareImmedeatelyChange = new EventEmitter(); + + + private _keyExpr: string; + public get keyExpr(): string { + return this._keyExpr; + } + @Input() public set keyExpr(value: string) { + this._keyExpr = value; + this.applyCustomFilterAsync(); + } + + + private _displayExpr: string; + public get displayExpr(): string { + return this._displayExpr; + } + @Input() public set displayExpr(value: string) { + this._displayExpr = value; + this.applyCustomFilterAsync(); + } + + + private _required: boolean; + public get required(): boolean { + return this._required; + } + @Input() public set required(value: boolean) { + if (typeof (value) === 'string') value = value !== 'false'; + this.setRequired(value); + console.log('**** - Hensel-Sel: ' + this.placeholder + ' set required', value); + this.updateParent(); + } + + private orgRequired: boolean; + + private _disabled: boolean = false; + public get disabled(): boolean { + return this._disabled; + } + + @Input() + public set disabled(value: boolean) { + value = typeof (value) === 'string' ? value !== 'false' : value + if (!this.showSpinner) { + this.setDisable(value); + } + this.lastDisabled = value; + } + + // binding for selected items + private _selectedFirst: boolean = true; + public get selectedFirst(): boolean { + return this._dataSource && this._dataSource.length > 200 || !this.multiSelect ? false : this._selectedFirst; + } + @Input() public set selectedFirst(value: boolean) { + this._selectedFirst = value; + this.itemsControl.setValue(this.lastFilter); + } + + @Input() public validate: (items: any[]) => boolean; + + // ',' delimited & conditions without spaces (space means compare against null) + private _customFilter: string[] = []; + + @Input() public set customFilter(value: string) { + if (!value) this._customFilter = []; + else this._customFilter = value.split(','); + this.applyCustomFilterAsync(); + } + + private _customFilterFn: (item: any) => boolean = null; + + @Input() + public get customFilterFn(): (item: any) => boolean { + return this._customFilterFn; + } + public set customFilterFn(value: (item: any) => boolean) { + this._customFilterFn = value; + this.applyCustomFilterAsync(); + } + + public _selectedItemIds: any[] = []; + @Input() public set selectedItems(val: any[] | any) { + if (val instanceof Array) this.setValueInternally(val.slice(), true); //use copy of array + else this.setValueInternally(val, true); + this.lastSelection = this._selectedItemIds; + // console.log('!!!!!! ' + this.placeholder, val, this._selectedItemIds.length); + } + + public get selectedItems(): any[] | any { + return this._selectedItemIds; + } + + @Output() selectedItemsChange = new EventEmitter(); + @Output() selectedItemsDisplayChange = new EventEmitter(); + @Output() dropDownClosed = new EventEmitter(); + // Name of dataSource + @Input() placeholder: string; + @Input() multiSelect: boolean = true; + @Input() separator: string = ','; + @Input() width: string = '100%'; + @Input() height: string = '200px'; + @Input() displayTemplate: string = ''; //"${filedname}: ${filedname}" + @Input() displayIconFn: (item: any) => string; + @Input() id: string = ''; + @Input() name: string = ''; + @Input() useCloseButton: boolean = true; + @Input() useMarkFiltered: boolean = true; + @Input() useSelFirstButton: boolean = false; + @Input() useCBChangedColor: boolean = true; + private _useResultGrid: boolean = false; + @Input() + public get useResultGrid(): boolean { + return this._useResultGrid; + } + public set useResultGrid(value: boolean) { + this._useResultGrid = value; + } + + @Input() useLabelChangedColor: boolean = true; + @Input() backgroundColor: string = 'inherit'; + public backgroundColor4Grid: string; + + + private _minFilterLength4Search: number = -1; + public get minFilterLength4Search(): number { + let _minFilterLength4Search = 0; + if (this._minFilterLength4Search === 0) { + _minFilterLength4Search = this.getMinFilterLength4Search(this._dataSource.length); + } else { + if (this._minFilterLength4Search > 0) _minFilterLength4Search = this._minFilterLength4Search; + } + return (this._customFilter.length === 0 && !this._customFilterFn) ? _minFilterLength4Search : + Math.min(this.getMinFilterLength4Search(this._dataSource.length), _minFilterLength4Search); + } + + @Input() public set minFilterLength4Search(value: number) { + this._minFilterLength4Search = value; + } + private _sortField: string = null; + private sortDirection: -1 | 1 = 1; + @Input() set sortField(value: string) /*with leading "-" descendent*/ { + this._sortField = value; + if (this._sortField && this._sortField.slice(0, 1) === '-') { + this.sortDirection = -1; + this._sortField = this._sortField.slice(1); + } else this.sortDirection = 1; + this.applyCustomFilterAsync(); + } + get sortField(): string { return this._sortField; } + + public get formControlName(): string { + return 'henselSelectionControl_' + this.name; + } + + + private _parent: NgForm = null; + public get parent(): NgForm { + return this._parent; + } + + @Input() + public set parent(value: NgForm) { + this._parent = value ?? this._parentForm; + this.hsRequiredsubscription?.unsubscribe(); + this.hsRequiredsubscription = this.parent?.valueChanges.subscribe(() => this.checkRequired()); //take cares about form.invalid, if the component invalid + // this.formGroup?.addControl(this. formControlName, this.itemsControl); //if we add control to partner, form get changed event on dropdown + this.markAsTouchedDirty(); + } + + private _newfilter: string; + + public get openWithFilter(): string { + return this._newfilter; + } + + @Input() + public set openWithFilter(newfilter: string) { + this._newfilter = newfilter; + if (this.showSpinner || !this.initialised || !this._origDataSource || this._origDataSource.length === 0) return; //to avoid repeatedly calls during initialising + + if (newfilter !== undefined) { + setTimeout(() => { + this.itemsControl.setValue(newfilter); + if (!!newfilter) this.cbInput?.nativeElement?.focus(); + }); + } + } + + @Input() public hsClass: string = ''; + + @Input() selectionNotFound: (arg: number) => string; + @Input() autofocus: any = false; + + private _canClear: boolean = true; + public get canClear(): boolean { + return this._canClear; + } + @Input() public set canClear(value: boolean) { + this._canClear = value; + } + @Input() public defaultValue: any; + @Output() public focus = new EventEmitter(); + @Input() public tabindex: number = 0; + + private _title: string = ''; + public get title(): string { + let resTitle = this._title; + if (!resTitle && this.cbInput && this.cbInput.nativeElement && this.cbInput.nativeElement.clientWidth < this.cbInput.nativeElement.scrollWidth) { + resTitle = this.displayFn(this._selectedItemIds); + } + return resTitle; + } + + @Input() + public set title(value: string) { + this._title = value; + } + + private _showSpinner: boolean = false; + public get showSpinner(): boolean { + return this._showSpinner; + } + + @Input() + public set showSpinner(value: boolean) { + this.setShowSpinner(value); + this.lastShowSpinner = value; + this.openWithFilter = this.openWithFilter; + } + + private _disabledItems: any[] = []; + public get disabledItems(): any[] { + return this._disabledItems; + } + @Input() + public set disabledItems(value: any[]) { + this._disabledItems = value; + this.applyCustomFilterAsync(); + } + + + public itemsControl = new FormControl(); + + public get displayLength(): number { + return this.displayFn(this._selectedItemIds)?.length; + } + + public hasFocus: boolean = false; + public filteredItems: any[] = []; + public items2filter: Observable; + public selectedItemsGrid: any[] = []; + public selectedAllNonePart: number = 0; //-1 - none, 0 - part, 1 - all + private _dropDownState: EN_DropDownState = EN_DropDownState.Closed; //0-closed, 1-opened, 2-not shown because of empty filter + public get dropDownState(): EN_DropDownState { + return this._dropDownState; + } + public set dropDownState(value: EN_DropDownState) { + if (value === EN_DropDownState.Closed && this._dropDownState !== value) this.dropDownClosed.emit(); + this._dropDownState = value; + } + public lastFilter: string = ''; + private _lastSelectionString: string = ''; + private lastSelectedItemIds: any = ''; + public get lastSelection(): any { + return this._lastSelectionString; + } + public set lastSelection(value: any) { + this.lastSelectedItemIds = value.slice(); + this._lastSelectionString = this.getSelection(value); + } + public startLeaveFocus: boolean = false; + public showInputField: boolean = true; + + public initialised: boolean = false; + private lastActiveItemIndex: number; + + private get formGroup(): FormGroup { + return this.parent?.control; + } + + constructor( + public translate: HenselTranslateService, + @Optional() private _parentForm: NgForm + ) { + this.applyCustomFilterAsync = this.applyCustomFilterAsync.bind(this); + translate.onLangChange.subscribe(() => this.applyCustomFilterAsync()); + } + + ngOnInit() { + //document.getElementById('cbInput').addEventListener('blur', this.closeDropDown); //can be used (blur)="closeDropDown()" in html + //document.getElementById('cbInput').addEventListener('focus', this.openDropDown); + this.items2filter = this.itemsControl.valueChanges.pipe( + // startWith(''), + // debounceTime(300), + map(value => typeof value === 'string' ? value : this.lastFilter), + map(filter => this.applyFilter(filter)), + ); + + this.items2filter.subscribe(() => setTimeout(() => { //over time out - the list must be built + this.applyMarkFiltered(this.lastFilter); + })); + + this.showInputField = !this.useResultGrid; + setTimeout(() => { + if (!this.parent) this.parent = this._parent; + }, 0); + } + + ngAfterViewInit(): void { + if (this.lastShowSpinner === undefined) this.setShowSpinner(true); + setTimeout(() => { + this.initialised = true; + this.applyCustomFilterAsync(); + this.backgroundColor4Grid = this.getBackgroundColor(this.hsElementRef.nativeElement); + }, 0); + } + + + private getMinFilterLength4Search(count: number) { + return count > 5000 ? 4 : (count > 1000 ? 3 : (count > 300 ? 2 : 0)); + } + + + private setShowSpinner(value: boolean) { + //dettimeout interferiert with settimeout in open with filter + setTimeout(() => { //timeout because of ExpressionChangedAfterItHasBeenCheckedError + this._showSpinner = value; + if (value) this.setDisable(true); + else this.setDisable(this.lastDisabled); + this.openWithFilter = this.openWithFilter; + }, 0); + } + + + private setDisable(value: boolean) { + this._disabled = value; + if (this.disabled) { + this.autocompleteTrigger?.closePanel(); + this.itemsControl.disable(); + } else this.itemsControl.enable(); + } + + + private setRequired(value: boolean) { + this._required = value; + } + + + private setValueInternally(value: any[] | any, externally = false) { + + if (!this._selectedItemIds) this._selectedItemIds = []; + if (value instanceof Array) this._selectedItemIds.splice(0, this._selectedItemIds.length, ...value); //we replace here elements of array, otherwise the connected array will not be set w/o emit and values are not reset + // this._selectedItemIds = val; + else { + this._selectedItemIds.splice(0); + if (value) this._selectedItemIds.push(value); + } + + this.updateGrid(); + + // const lastState = this.dropDownState; + // this._dropDownState = EN_DropDownState.Opened; // to update the 1st time the dropdown ?? //results in keyinput delays + this.itemsControl.setValue(this._selectedItemIds); + console.log('**** - Hensel-Sel: ' + this.placeholder + ' set value internaly', value); + if (externally) this.updateParent(); //otherwise if set programatically parent form doesn't change valid status + // this._dropDownState = lastState; + } + + + getBackgroundColor(htmlElemet: any): string { + const backgroundColor = window.getComputedStyle(htmlElemet, null).getPropertyValue('background-color'); + if (backgroundColor !== 'rgba(0, 0, 0, 0)' || !htmlElemet?.parentElement) return backgroundColor; + else return this.getBackgroundColor(htmlElemet.parentElement); + } + + public checkInSelected(val: any) { + return this._selectedItemIds.indexOf(val[this.keyExpr]) >= 0; + } + + public checkChanged(val: any) { + const isSelected = this.checkInSelected(val); + const wasSelected = this.lastSelectedItemIds.indexOf(val[this.keyExpr]) >= 0; + // tslint:disable-next-line: no-bitwise + return isSelected ^ wasSelected; + } + + // @HostListener('window:keydown', ['$event']) - if not commented we get delay in keyinput for other input fields + public onKeyDown = (event?: KeyboardEvent): boolean => { + // tslint:disable-next-line: deprecation + if (event.keyCode === keycode.ENTER && this.multiSelect) { + this.selectionDone(); + event.stopPropagation(); + return false; //no further processing + } + return true; //default processing + } + + @HostListener('keydown', ['$event']) + public inputFilter(event?: KeyboardEvent) { + // tslint:disable-next-line: deprecation + if (event.keyCode === keycode.ENTER || event.keyCode === keycode.TAB && !this.multiSelect) //return + { + if (this.filteredItems.length === 1) this.toggleSelection(this.filteredItems[0]); + if (!this.multiSelect) this.cbInput.nativeElement.blur(); + // tslint:disable-next-line: deprecation + if (event.keyCode === keycode.ENTER) { + event.stopPropagation(); + return false; //was processed + } else return true; + // tslint:disable-next-line: deprecation + } else if (event.keyCode === keycode.UP_ARROW || event.keyCode === keycode.DOWN_ARROW) { + if (this.multiSelect) this.autocompleteTrigger.autocomplete._keyManager.setActiveItem(null); + else { + if (this.lastActiveItemIndex !== undefined) { + // tslint:disable-next-line: deprecation + this.autocompleteTrigger.autocomplete._keyManager.setActiveItem((this.lastActiveItemIndex + (event.keyCode === keycode.UP_ARROW ? -1 : 1) + this._dataSource.length) % this._dataSource.length); + } + this.lastActiveItemIndex = undefined; + this.scrollToOption(); + } + event.stopPropagation(); + return false; //was processed + } else if (event.keyCode !== keycode.TAB && event.keyCode !== keycode.ESCAPE && !this.lastFilter + || event.keyCode === keycode.ESCAPE && this.lastFilter) { //otherwise is cleared with tab + this.itemsControl.setValue(''); //clear filter if it was empty + } + return true; //default processing + } + + itemSelectedByKeyboard(event: MatOptionSelectionChange) { + if (event.isUserInput && this.autocompleteTrigger.autocomplete._keyManager.activeItem) this.toggleSelection(this.filteredItems[this.autocompleteTrigger.autocomplete._keyManager.activeItemIndex]); + } + + private displayItem(item: any, init: boolean = false): string { + if (init) { + const caption = this.translate.instant(item[this.displayExpr]); + if (this.displayTemplate) return this.displayTemplate.replace(/\${(.*?)}/g, (found: string, fldname: string) => item[fldname] ?? '').replace('', item[this.keyExpr] ?? '').replace('', caption); + else return caption; + } else return item[this.displayExpr]; + } + + checkRequired() { + if (this.requiredError()) this.formGroup?.setErrors({ required: true }); + } + + requiredError(): boolean { + let req = this.required; + if (this.dropDownState !== EN_DropDownState.Closed) req = this.orgRequired; + return !this.disabled && req !== undefined && req !== false && this.isEmpty(); + } + + + public applyFilter(filter: string): any[] { + + this.lastFilter = filter; + if (this.dropDownState !== EN_DropDownState.Closed) { + + if (filter.length < this.minFilterLength4Search) this.filteredItems.splice(0); + else + if (filter.length > 0) { + const _filter = filter.toLowerCase(); + this.filteredItems = this._dataSource.filter(item => this.displayItem(item).toLowerCase().indexOf(_filter) >= 0); + } else this.filteredItems = this._dataSource.slice(); + + if (this.selectedFirst) { + this.filteredItems.sort((item1, item2) => { + let retval: number = 0; + if (this.selectedFirst) retval = this.checkInSelected(item2) - this.checkInSelected(item1); + if (retval === 0 && this._sortField) retval = !item1[this._sortField] ? -1 : this.compare2items(item1, item2); + return retval; + } + ); + } + + const noSelectedInList: number = this.isEmpty() ? 0 : this.filteredItems.filter(item => this._selectedItemIds.indexOf(item[this.keyExpr]) >= 0).length; + this.selectedAllNonePart = noSelectedInList === 0 ? -1 : (noSelectedInList === this.filteredItems.length ? 1 : 0); + + //no close event is called if filter empty, but drop down is closed - therefore we set status manuelly + if (this.dropDownState === EN_DropDownState.Opened && this.filteredItems.length === 0) this.dropDownState = EN_DropDownState.EmptyFilter; + } + return this.filteredItems; + } + + + public displayFn = (value: any[] | string): (string | undefined) => { //such declaration because of binding + let displayValue: string = ''; + if (Array.isArray(value)) { + // value.forEach((key, index) => displayValue += (index === 0 ? '' : this.separator + ' ') + this._dataSource.find(op => op[this.keyExpr] === key)[this.displayExpr]); + if (this._dataSource) { + value.forEach(vl => { + const item = this._dataSource.find((it) => it[this.keyExpr] === vl); + if (item) { + displayValue += this.separator + ' ' + this.displayItem(item); + } else if (this.selectionNotFound) displayValue += this.separator + ' ' + this.selectionNotFound(vl); + }); + /* + this._dataSource.forEach((item, index) => { + if (value.indexOf(item[this.keyExpr]) >= 0) { + displayValue += this.separator + ' ' + this.displayItem(item); + } + });*/ + } + displayValue = displayValue.slice(this.separator.length + 1); + } else displayValue = value; + + return displayValue; + } + + + private prepareDataSource() { + if (this._customFilter.length > 0) { + this._dataSource = this._origDataSource.filter(item => { + return !this._customFilter.some(filterToken => { //_customFilter tokens are connected with && condition + let tokens: string[] = filterToken.split('!='); + if (tokens.length === 2) { + if (tokens[1] === ' ') return (item[tokens[0]] === null); + return !('' + item[tokens[0]] !== tokens[1]); + } + tokens = filterToken.split('='); + if (tokens.length === 2) { + return !('' + item[tokens[0]] === tokens[1]); + } + tokens = filterToken.split('<'); + if (tokens.length === 2) { + if (!Number.isNaN(Number(item[tokens[0]])) && !Number.isNaN(Number(tokens[1]))) { + return !(Number(item[tokens[0]]) < Number(tokens[1])); + } else return !('' + item[tokens[0]] < tokens[1]); + } + tokens = filterToken.split('>'); + if (tokens.length === 2) { + if (!Number.isNaN(Number(item[tokens[0]])) && !Number.isNaN(Number(tokens[1]))) { + return !(Number(item[tokens[0]]) > Number(tokens[1])); + } else return !('' + item[tokens[0]] > tokens[1]); + } + tokens = filterToken.split('<='); + if (tokens.length === 2) { + if (!Number.isNaN(Number(item[tokens[0]])) && !Number.isNaN(Number(tokens[1]))) { + return !(Number(item[tokens[0]]) <= Number(tokens[1])); + } else return !('' + item[tokens[0]] <= tokens[1]); + } + tokens = filterToken.split('>='); + if (tokens.length === 2) { + if (!Number.isNaN(Number(item[tokens[0]])) && !Number.isNaN(Number(tokens[1]))) { + return !(Number(item[tokens[0]]) >= Number(tokens[1])); + } else return !('' + item[tokens[0]] >= tokens[1]); + } + return false; + }); + }); + } else this._dataSource = this._origDataSource.slice(); + if (this.customFilterFn) this._dataSource = this._dataSource.filter(item => this.customFilterFn(item)); + } + + + private async applyCustomFilterAsync() { + if (!this.initialised || !this._origDataSource) return; //to avoid repeatedly calls during initialising + + const dataSourceWasEmpty = !this._dataSource?.length; + this.prepareDataSource(); + + if (!this.displayExpr) this._displayExpr = 'display'; + + if (this._sortField === '*') this._sortField = this.displayExpr; + + this._dataSource = this._dataSource.map((item, index, arr) => { + if (this._sortField && this._sortField !== this.displayExpr && this._sortField !== this.keyExpr) { + return Object({ + [this.keyExpr]: item[this.keyExpr], + [this.displayExpr]: this.displayItem(item, true), + [this.sortField]: this._sortField ? item[this._sortField] : '', + link: item, + disabled: this.disabledItems.indexOf(item[this.keyExpr]) > -1 + }); + } else { + return Object({ + [this.keyExpr]: item[this.keyExpr], + [this.displayExpr]: this.displayItem(item, true), + link: item, + disabled: this.disabledItems.indexOf(item[this.keyExpr]) > -1 + }); + } + }); + + //checks if the passed value for the selection in the filtered selection list, if not - delete + let selWasChanged: boolean = false; + if (this._dataSource.length > 0 || !dataSourceWasEmpty) { //w/o checking dataSourceWasNotEmpty after deleting the dataSource, selected value is kept + const filterIds = this._dataSource.map(item => item[this.keyExpr]); + for (let inx = this._selectedItemIds.length - 1; inx >= 0; inx--) { + if (filterIds.indexOf(this._selectedItemIds[inx]) === -1) { + if (!this.selectionNotFound) { + this._selectedItemIds.splice(inx, 1); + selWasChanged = true; + } + } + } + } + + + if (this._sortField) this._dataSource.sort((item1, item2) => this.compare2items(item1, item2)); + + console.log('**** - Hensel-Sel: ' + this.placeholder + ' current id=', this._selectedItemIds, 'lenght=', this._dataSource.length, ' wasempty=', !dataSourceWasEmpty, 'waschanged=', selWasChanged); + this.itemsControl.setValue(this._selectedItemIds); + + this.updateGrid(); + + if (this._origDataSource.length > 0 && this.lastShowSpinner === undefined) this.setShowSpinner(false); //if was not set explicetely + else this.openWithFilter = this.openWithFilter; //only in else, bcs is set in setShowSpinner(false) + + if (selWasChanged) { + console.log('**** - Hensel-mark ' + this.placeholder + ' indirect changed'); + setTimeout(() => this.updateParent()); + } + this.markAsTouchedDirty(); + } + + + updateGrid() { + if (this.useResultGrid) { + if (this._dataSource && this._selectedItemIds && this._selectedItemIds.length > 0) { + this.selectedItemsGrid = this._dataSource.filter((item: any) => this._selectedItemIds.indexOf(item[this.keyExpr]) >= 0); + } else this.selectedItemsGrid = []; + } + } + + + compare2items = (item1, item2): number => { + if (item1[this._sortField]) { + if (typeof (item1[this._sortField]) === 'number') return (item1[this._sortField] - item2[this._sortField]) * this.sortDirection; + else return item1[this._sortField].localeCompare(item2[this._sortField]) * this.sortDirection; + } else return 0; + } + + + private applyMarkFiltered(filter: string) { + if (!this.useMarkFiltered || this.dropDownState !== EN_DropDownState.Opened) return; + const inputTexts = this.autocompleteScrollPanel.nativeElement.getElementsByClassName('item'); + if (!inputTexts) return; + for (let index = 0; index < Math.min(this.filteredItems.length, inputTexts.length); index++) { + const iconHtmlInd = inputTexts[index].innerHTML.indexOf(''); + const iconHtml = iconHtmlInd < 0 ? '' : inputTexts[index].innerHTML.slice(0, iconHtmlInd + 11); + if (filter === '') inputTexts[index].innerHTML = iconHtml + this.displayItem(this.filteredItems[index]); + else { //inputTexts[index].innerHTML = this.filteredItems[index][this.displayExpr].replace(filter, '' + filter + ''); + inputTexts[index].innerHTML = iconHtml + this.displayItem(this.filteredItems[index]).replace( + new RegExp(filter + '(?!([^<]+)?<)', 'gi'), '$&'); + } + } + } + + + public itemClicked(event: Event, item: any) { + event.stopPropagation(); + this.toggleSelection(item); + } + + + public toggleSelection(item: any) { + if (item.disabled) return; + if (!this.multiSelect) this._selectedItemIds = []; + if (!this.checkInSelected(item)) { + this._selectedItemIds.push(item[this.keyExpr]); + } else { + const i = this._selectedItemIds.indexOf(item[this.keyExpr]); + this._selectedItemIds.splice(i, 1); + } + + if (!this.minFilterLength4Search) { + //show the complete list again (multiselect), after checking an option + //is not working if we have limitations for search + this.lastFilter = ''; + this.itemsControl.setValue(this.lastFilter); + } + + if (!this.multiSelect) { + this.itemsControl.setValue(this.displayFn(this._selectedItemIds)); + this.selectionDone(); + } else this.itemsControl.setValue(this._selectedItemIds); + + } + + + + public isEmpty(): boolean { + return this._selectedItemIds.length === 0; + } + + + public openDropDown = () => { //such declaration because of binding + if (this.disabled) return; + if (this.dropDownState === EN_DropDownState.Closed) {//if is opened at the first time + if (this.multiSelect) window.addEventListener('keydown', this.onKeyDown, { once: true } as AddEventListenerOptions /*fires one time and is removed*/); + this.orgRequired = this.required; + if (!this.isEmpty()) this.setRequired(false); + this.lastSelection = this._selectedItemIds; + if (!this.multiSelect && this._selectedItemIds.length > 0) { + setTimeout(() => { + this.lastActiveItemIndex = this._dataSource.findIndex(item => item[this.keyExpr] === this._selectedItemIds[0]); + this.autocompleteTrigger.autocomplete._keyManager.setActiveItem(this.lastActiveItemIndex); + this.scrollToOption(); + }, 0); + } + } + if (this.filteredItems.length > 0) this.dropDownState = EN_DropDownState.Opened; + else { + if (this.dropDownState === EN_DropDownState.Opened && this.autocompleteTrigger.panelOpen) this.autocompleteTrigger.closePanel(); + this.dropDownState = EN_DropDownState.EmptyFilter; + } + this.itemsControl.setValue(this.lastFilter); // important the order, must be after setting of dropDownIsOpened + } + + + scrollToOption() { + const autocomplete: MatAutocomplete = this.autocompleteTrigger.autocomplete; + const index = autocomplete._keyManager.activeItemIndex || 0; + const labelCount = _countGroupLabelsBeforeOption(index, autocomplete.options, autocomplete.optionGroups); + if (index === 0 && labelCount === 1) { + // If we've got one group label before the option and we're at the top option, + // scroll the list to the top. This is better UX than scrolling the list to the + // top of the option, because it allows the user to read the top group's label. + autocomplete._setScrollTop(0); + // this.autocompleteScrollPanel.nativeElement.scrollTop = 0; + } else if (index > -1 && autocomplete.panel) { + const panelheight = autocomplete.panel.nativeElement.offsetHeight - (this.autocompleteToolbar?.nativeElement.offsetHeight || 0); + const itemHeight = (autocomplete.options.first)?._element?.nativeElement?.offsetHeight || 30; + this.currentScrollTop = _getOptionScrollPosition((index + labelCount) * itemHeight, itemHeight, this.currentScrollTop, panelheight); + autocomplete._setScrollTop(this.currentScrollTop); + // this.autocompleteScrollPanel.nativeElement.scrollTop = this.currentScrollTop; + } + } + + + public closeDropDown = () => { //such declaration because of binding + this.currentScrollTop = 0; + if (this.hasFocus && this.dropDownState === EN_DropDownState.EmptyFilter) return; //the input box is still focused + + setTimeout(() => { + this.lastFilter = ''; + }); //timeout is needed to avoid open/close drop down effect after click out of component + this.setValueInternally(this.lastSelectedItemIds); + this.dropDownState = EN_DropDownState.Closed; + this.setRequired(this.orgRequired); + if (this.multiSelect) window.removeEventListener('keydown', this.onKeyDown, { once: true } as AddEventListenerOptions /*fires one time and is removed*/); + } + + + public takeFocus = () => { //such declaration because of binding + this.startLeaveFocus = false; + this.hasFocus = true; + this.openDropDown(); + this.focus.emit(this); + } + + + public leaveFocus = () => { //such declaration because of binding + this.hasFocus = false; + if (this.dropDownState !== EN_DropDownState.EmptyFilter) return; //reset the last value if searched string was not matched + this.startLeaveFocus = true; + setTimeout(() => { //gives time to cancel closeDropdown if the clear button is focused + if (this.startLeaveFocus) this.closeDropDown(); + this.startLeaveFocus = false; + }); + } + + public setAll(completed: boolean) { + if (completed) this.selectAll(); + else this.deselectAll(); + } + + + public selectAll() { + this.setValueInternally(this._selectedItemIds.concat(this.filteredItems.map(item => item[this.keyExpr]).filter(item => this._selectedItemIds.indexOf(item) === -1))); + } + + + public deselectAll() { + const filterIds = this.filteredItems.map(item => item[this.keyExpr]); + this.setValueInternally(this._selectedItemIds.filter(id => filterIds.indexOf(id) === -1)); + } + + + public getSelection(val: any[]): string { + return val.sort((a, b) => a - b).join(); + } + + + public updateParent() { + this.formGroup?.updateValueAndValidity(); + } + + + public selectionDone() { + const curSelection = this.getSelection(this._selectedItemIds); + if (this.lastSelection !== curSelection) { + if (this.validate && !this.validate(this._selectedItemIds)) return; + this.lastSelection = this._selectedItemIds; + console.log('**** - Hensel-Sel: ' + this.placeholder + ' selection done'); + this.updateParent(); + this.selectedItemsChange.emit(this.multiSelect ? this._selectedItemIds.slice() : (this._selectedItemIds.length > 0 ? this._selectedItemIds[0] : null)); + this.selectedItemsDisplayChange.emit(this.displayFn(this._selectedItemIds)); + } + this.autocompleteTrigger.closePanel(); + } + + + public clickClear($event: any) { + $event.stopPropagation(); + if (/*this.dropDownState === EN_DropDownState.Opened ||*/ this.lastFilter) { + setTimeout(() => { + this.itemsControl.setValue(''); + this.cbInput?.nativeElement?.focus(); //to call opendropdown after close drop down if minlength>0 + }, 300); + } else { + this.lastSelection = this._selectedItemIds; + if (this.defaultValue !== undefined && this.defaultValue !== null) this.setValueInternally([this.defaultValue]); + else this.setValueInternally([]); + this.selectionDone(); + } + } + + + clickArrow(event?: any) { + if (this.disabled) return; + this.showInputField = true; + setTimeout(() => { this.cbInput?.nativeElement?.focus(); }, 0); + if (event) event.cancel = true; + } + + ngOnDestroy(): void { + if (this.hsRequiredsubscription) this.hsRequiredsubscription.unsubscribe(); + } + + getIcon4Selected(): string { + if (this.displayIconFn) return this.displayIconFn(this._dataSource.find(_item => _item[this.keyExpr] === this._selectedItemIds[0])?.link); + return null; + } + + public markAsDirty() { + if (this.hsMatFormField?._control?.ngControl?.control) { + this.hsMatFormField._control.ngControl.control.markAsDirty(); + console.log('**** - Hensel-mark ' + this.placeholder + ' as dirty'); + this.updateParent(); + } + } + + + public markAsTouched() { + if (this.hsMatFormField?._control?.ngControl?.control) { + this.hsMatFormField._control.ngControl.control.markAsTouched(); + console.log('**** - Hensel-mark ' + this.placeholder + ' as touched'); + this.updateParent(); + } + } + + + public markAsTouchedDirty() { + if (this.hsMatFormField?._control?.ngControl?.control && this.required && this.isEmpty()) { + this.hsMatFormField._control.ngControl.control.markAsTouched(); + this.hsMatFormField._control.ngControl.control.markAsDirty(); + console.log('**** - Hensel-mark ' + this.placeholder + ' as touched/dirty'); + this.updateParent(); + } + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/readme.txt b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/readme.txt new file mode 100644 index 0000000..383e1b1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-selection/readme.txt @@ -0,0 +1,24 @@ +Inputs: +placeholder (String): A placeholder value for your mat-select +selectPlaceholder(String): Placeholder for options filtering +options (Array of objects): Options object to be listed +selectedOptions (Array of Strings): To pre-populate or preselect options +display (String): Property of every option for display in dropdown +value (String): Property of every option to be returned on option selection; +required (Boolean): To make your mat-field required. Default : false; +multiple (Boolean): Able to select multiple or single. Default: true; +disabled (Boolean): To disable the mat-field. default: false; +appearance (String): Appearance of your mat-field. Supported options: 'legacy' | 'standard' | 'fill' | 'outline'; +formControl (String): If you’re using Angular reactive form, bind your formControl with mat-select-autocomplete output +showErrorMsg (Boolean): Whether show error message or not. Default: false; +errorMsg (String): Custom error message. Default: ‘Field is required’ +labelCount (Number): Number of selected options to be shown in display of mat-select. Default: 1. + +Outputs: +selectionChange (EventEmitter): On every option selection, +this event would be emitted. You could capture the selected options values [Array of Strings] from this event param. + +ViewChild: +If you want to toggle mat-select-autocomplete from your own component event, +you need to import MultiselectComponent in the component and take it’s reference as ViewChild element (eg: matSelect). +Now you could trigger this.matSelect.toggle() to toggle the dropdown. \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.html new file mode 100644 index 0000000..9c5919a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.html @@ -0,0 +1,36 @@ +
+ + + + + + + + + + + + + +
+ + +
+ + image_not_supported + +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.scss new file mode 100644 index 0000000..333d055 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.scss @@ -0,0 +1,83 @@ +@import 'hr-core-consts'; + + +.btn-question-picture { + width: 160px; + height: 50px; + background-color: white; + color: $hrColor-DarkBlue; +} + +.webcam-grid { + height: 100%; + width: 100%; + display: grid; + position: relative; + grid-template-rows: auto minmax(0, 1fr); + grid-template-columns: 0px auto minmax(0, 1fr); + grid-template-areas: + ". webcam-container snapshot ." + ". arrow-take-picture btn-delete ."; + grid-gap: 15px; +} + + + +.no-photo-icon { + // font-size: 250px; + opacity: 20%; +} + +.snapshot { + margin-left: 35px; + grid-area: snapshot; +} + +.webcam_button_icons{ + padding-right: 5px; +} + + +.webcam-container { + grid-area: webcam-container; +} + +.btn-delete { + margin-left: 35px; + grid-area: btn-delete; + width: 160px; + height: 50px; + background-color: white; + color: $hrColor-DarkBlue; +} + +.snapshot, +.webcam-container { + padding: 2px; + // margin-left: 4px; +} + +.arrow-take-picture { + grid-area: arrow-take-picture; + width: 160px; + height: 50px; + background-color: white; + color: $hrColor-DarkBlue; +} + +.DeleteButton { + // color: $hrColor-Green; + // color: $hrColor-DarkBlue; + // position: absolute; + // top: 0px; + // left: 100%; + // transform: translate(-40px); + position: absolute; + top: 12px; + right: 20px; +} + +.DeleteIcon { + font-size: 40px; + color: white; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.ts new file mode 100644 index 0000000..1979d6e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.component.ts @@ -0,0 +1,58 @@ +import { Component, EventEmitter, Input, OnDestroy, Output, ViewChild } from '@angular/core'; +import { WebcamComponent, WebcamImage } from 'ngx-webcam'; +import { Observable, Subject } from 'rxjs'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; + +@Component({ + // tslint:disable-next-line:component-selector + selector: 'hensel-webcam', + templateUrl: 'hensel-webcam.component.html', + styleUrls: ['hensel-webcam.component.scss'], +}) + +export class HenselWebcamComponent implements OnDestroy { + @ViewChild(WebcamComponent) webCam: WebcamComponent; + @Output() public pictureTaken = new EventEmitter(); + @Input() public picture: string; + @Input() public canDelete: boolean = true; + @Input() public disabled: boolean = false; + @Input() public size: number = 250; + + + public videoOptions: MediaTrackConstraints = { + width: { ideal: this.size }, // must be same size + height: { ideal: this.size }, // must be same size (look html) TODO: Input width/height + }; + + public get isInitialized(): boolean { + return this.webCam?.videoInitialized ?? false; + } + + // webcam snapshot trigger + private trigger: Subject = new Subject(); + + + constructor( + public translate: HenselTranslateService, + ) {} + + // tslint:disable-next-line:use-life-cycle-interface + ngOnInit() {} + + public triggerSnapshot(): void { + this.trigger.next(); + } + + + public processSnapshot(webcamImage: WebcamImage): void { + this.pictureTaken.emit(webcamImage); + } + + public get triggerObservable(): Observable { + return this.trigger.asObservable(); + } + + + ngOnDestroy(): void { + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.module.ts new file mode 100644 index 0000000..882c62c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/hensel-webcam/hensel-webcam.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; +import { AngularMaterialModule } from '../angular-material.module'; +import { DxButtonModule, DxTooltipModule, DxDataGridModule } from 'devextreme-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { HenselWebcamComponent } from './hensel-webcam.component'; +import { WebcamModule } from 'ngx-webcam'; + + + +@NgModule({ + declarations: [HenselWebcamComponent], + imports: [ + CommonModule, + AngularMaterialModule, + FormsModule, + ReactiveFormsModule, + DxButtonModule, + DxTooltipModule, + WebcamModule, + TranslateModule.forChild(), + DxDataGridModule + ], + exports: [HenselWebcamComponent] +}) +export class HenselWebcamModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.html new file mode 100644 index 0000000..3e6c1ee --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.html @@ -0,0 +1,75 @@ +
+ +
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.scss new file mode 100644 index 0000000..a695c9f --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.scss @@ -0,0 +1,80 @@ +@import 'hr-core-consts'; + +.divFooter { + background-color: $hrColor-DarkBlue; + // position: absolute; + flex-direction: row; + box-sizing: border-box; + // display: flex; + // top: 8em; + width: 100%; //99.4%; + padding: 5px; + // margin: 0 5px 0 5px; + font-size: 10px; + font-weight: 500; + text-align: left; + border-radius: $hrBorder-radius-small $hrBorder-radius-small; +} + +.divFooter>a, span { + color: white; +} + +.data { + padding-left: 5px; + padding-right: 10px !important; + color: $hrColor-LightBlueMain !important; +} + +.data1 { + padding-left: 5px !important; + padding-right: 2px !important; + color: $hrColor-LightBlueMain !important; +} + +/* + * ---------------------------------------- + * animation slide-top + * ---------------------------------------- + */ +/* +.slide-top { + -webkit-animation: slide-top 0.3s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; + animation: slide-top 0.3s cubic-bezier(0.250, 0.460, 0.450, 0.940) both; + animation-delay: 3s; +} + +@-webkit-keyframes slide-top { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 50% { + -webkit-transform: translateY(-50px); + transform: translateY(-50px); + } + + 100% { + -webkit-transform: translateY(-102px); + transform: translateY(-102px); + } +} + +@keyframes slide-top { + 0% { + -webkit-transform: translateY(0); + transform: translateY(0); + } + + 50% { + -webkit-transform: translateY(-50px); + transform: translateY(-50px); + } + + 100% { + -webkit-transform: translateY(-102px); + transform: translateY(-102px); + } +} +*/ diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.ts new file mode 100644 index 0000000..585cff7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/footer/footer.component.ts @@ -0,0 +1,64 @@ +import { HttpClient } from '@angular/common/http'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Globals } from '../../../services/globals'; +import { AuthorizeService } from '../../../services/authorize.service'; +import { ServerInfoService } from '../../../services/serverinfo.service'; +import { now } from '../../../utils'; + +const + second = 1000, + minute = second * 60, + hour = minute * 60, + day = hour * 24; + +@Component({ + selector: 'app-footer', + templateUrl: './footer.component.html', + styleUrls: ['./footer.component.scss'] +}) + +export class FooterComponent implements OnInit, OnDestroy { + counter: any; + + days: number; + hours: number; + mins: number; + secs: number; + public package_json; + public coreVersion: string; + public devextremeVersion: string; + + constructor( + public globals: Globals, + public serverInfoService: ServerInfoService, + public authService: AuthorizeService, + private http: HttpClient + ) { + this.counter = setInterval(() => this.updateTimer(), 1000); + } + + updateTimer = () => { + if (!this.authService.useJWT || !this.authService.HR_JWT) return; + let distance = this.authService.HR_JWT?.expiresAt?.valueOf() - now(); + if (distance < -3 * second) return; + if (distance < 0) distance = 0; + + this.days = Math.floor(distance / day); + this.hours = this.days > 0 ? 0 : Math.floor((distance % day) / hour); + this.mins = this.days > 0 || this.hours > 1 ? 0 : Math.floor((distance % hour) / minute); + this.secs = this.days > 0 || this.hours > 0 || this.mins > 1 ? 0 : Math.floor((distance % minute) / second); + } + + ngOnInit() { + this.http.get('../../../assets/json/package.json').subscribe((data) => { + this.package_json = data; + this.coreVersion = this.package_json?.version; + this.devextremeVersion = !this.package_json?.peerDependencies || !this.package_json?.peerDependencies['devextreme-angular'] ? undefined : this.package_json?.peerDependencies['devextreme-angular'] + this.devextremeVersion = this.devextremeVersion ?? this.package_json?.dependencies['devextreme-angular']; + }); + } + + ngOnDestroy(): void { + clearInterval(this.counter); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/favicon.ico b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d65b48a2b1957b4794f466a0e441348341a48eac GIT binary patch literal 15086 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 + + + + + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.scss new file mode 100644 index 0000000..25d5847 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.scss @@ -0,0 +1,58 @@ +@import 'hr-core-consts'; + +a { + text-decoration: none; + color: white; +} + +a:hover, +a:active { + color: $hrColor-LightBlue; +} + + +.selected { + color: $hrColor-LightBlue; +} + +.navigation-icon { + margin: -3px; +} + +.navigation-items { + list-style-type: none; + padding: 0; + margin: 0; +} + +::ng-deep .ng-star-inserted { + margin-right: 0px !important; +} + +.ng-star-inserted-item { + margin-right: 15px !important; + ; +} + +.restarticon { + color: white; + vertical-align: middle; + cursor: pointer; +} + +a:hover .restarticon { + color: $hrColor-LightBlue; +} + +.redcolor { + color: red; +} + +.nav-icon { + color: inherit; + vertical-align: text-top; +} + +.router-bar { + margin-left: auto; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.ts new file mode 100644 index 0000000..a2183a5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/header/header.component.ts @@ -0,0 +1,44 @@ +import { Component, EventEmitter, inject, Input, OnInit, Output } from '@angular/core'; +import { ACCOUNT_PAGE, Globals, IAppPage, LOGIN_PAGE } from '../../../services/globals'; +import { APPICON4NAVBAR_TOKEN, APPICON4TEST_TOKEN } from '../../../injection-tokens'; +import { AuthorizeService } from '../../../services/authorize.service'; +import { HenselTranslateService } from '../../../services/localization/hensel-translate.service'; +import { ServerInfoService } from '../../../services/serverinfo.service'; + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.scss'] +}) + +export class HeaderComponent implements OnInit { + @Input() public title: string; + @Output() public sidenavToggle = new EventEmitter(); + + public pageLogin: IAppPage = LOGIN_PAGE; + public pageAccount: IAppPage = ACCOUNT_PAGE; + private cnst_AppIcon4Navbar = inject(APPICON4NAVBAR_TOKEN); + private cnst_AppIcon4Test = inject(APPICON4TEST_TOKEN); + public get navBarIconPath(): string { + return this.serverInfoService.isLive() ? this.cnst_AppIcon4Navbar : this.cnst_AppIcon4Test; + } + + constructor( + public globals: Globals, + public authService: AuthorizeService, + public serverInfoService: ServerInfoService, + public translate: HenselTranslateService, + ) { } + + ngOnInit() { + } + + public onToggleSidenav = () => { + this.sidenavToggle.emit(); + } + + refreshPage() { + window.location.reload(); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.html new file mode 100644 index 0000000..8c806e7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.html @@ -0,0 +1,14 @@ +
+ + + + + + +
+ +
+ +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.scss new file mode 100644 index 0000000..9168305 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.scss @@ -0,0 +1,56 @@ +mat-sidenav-container, +mat-sidenav-content, +mat-sidenav { + height: 100%; +} + +mat-sidenav { + width: 300px; +} + +main { + padding: 5px; +} + +.layout-wrapper { + height: 100%; +} + +.flex-wrapper { + height: 100%; +} + +.HeaderMainFooterComponent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid + width: 100%; // 100 % view width (hardware screen) + height: 100%; // 100% view height + grid-template-areas: + 'head' + 'main' + 'foot'; // 3 Rows + grid-template-rows: auto minmax(0, 1fr) auto; // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship +} + +.HeaderComponent { + margin: 0 5px 0 5px; // padding around the header +// padding: 5px; // padding around the header + top: 0; // component + padding = top line + left: 0; // component + padding = left line + right: 0; // component + padding = right line + // ==> with these 3 informations we knew that the component will be stretched at the top of the view + grid-area: head; // grid area: auto height 1fr width +} + +.MainComponent { + grid-area: main; + overflow: hidden; +} + +.FooterComponent { + grid-area: foot; + margin: 0 5px 0 5px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.ts new file mode 100644 index 0000000..bf39d57 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit, Input } from '@angular/core'; + +@Component({ + selector: 'app-layout', + templateUrl: './layout.component.html', + styleUrls: ['./layout.component.scss'] +}) +export class LayoutComponent implements OnInit { + @Input() title: string; + constructor() { } + + ngOnInit() { + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.module.ts new file mode 100644 index 0000000..e24926b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/layout.module.ts @@ -0,0 +1,21 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { AngularMaterialModule } from '../angular-material.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { FooterComponent } from './footer/footer.component'; +import { HeaderComponent } from './header/header.component'; +import { LayoutComponent } from './layout.component'; +import { SidenavListComponent } from './sidenav-list/sidenav-list.component'; + +@NgModule({ + declarations: [LayoutComponent, FooterComponent, HeaderComponent, SidenavListComponent], + imports: [ + CommonModule, + AngularMaterialModule, + TranslateModule.forChild(), + RouterModule, + ], + exports: [LayoutComponent, FooterComponent, HeaderComponent, SidenavListComponent] +}) +export class LayoutModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.html new file mode 100644 index 0000000..faa89fa --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.html @@ -0,0 +1,14 @@ + + + + {{page.icon}} + {{page.caption | translate}} + {{'core.caption.logout'| translate}} ({{authService.userName}}) + + + + + menu_open + + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.scss new file mode 100644 index 0000000..19681d0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.scss @@ -0,0 +1,23 @@ +@import 'hr-core-consts'; + +a { + text-decoration: none; + color: white; +} + +a:hover { + color: $hrColor-LightBlue; +} + +a:hover.selected { + color: white; +} + +.nav-caption { + display: inline-block; + padding-left: 6px; +} + +.selected { + background-color: $hrColor-LightBlue !important; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.ts new file mode 100644 index 0000000..3e60d7d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/layout/sidenav-list/sidenav-list.component.ts @@ -0,0 +1,29 @@ +import { Component, OnInit, Output, EventEmitter, Input, Inject } from '@angular/core'; +import { AuthorizeService } from '../../../services/authorize.service'; +import { Globals, IAppPage, LOGIN_PAGE } from '../../../services/globals'; + +@Component({ + selector: 'app-sidenav-list', + templateUrl: './sidenav-list.component.html', + styleUrls: ['./sidenav-list.component.scss'] +}) +export class SidenavListComponent implements OnInit { + @Input() title: string; + @Output() sidenavClose = new EventEmitter(); + + public pageLogin: IAppPage = LOGIN_PAGE; + public listPages: IAppPage[] = this.globals.appPages; + + constructor( + public authService: AuthorizeService, + public globals: Globals + ) { } + + ngOnInit() { + } + + public onSidenavClose = () => { + this.sidenavClose.emit(); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.html new file mode 100644 index 0000000..72a0975 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.html @@ -0,0 +1,69 @@ +
+ {{overHeader}} +

{{header}}

+ + + + + + + + + + + + + + + + +
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.scss new file mode 100644 index 0000000..ca36e9c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.scss @@ -0,0 +1,94 @@ +@import 'hr-core-consts'; + +.PopupContainer { + width: 330px; + padding-top: 4px; + padding-left: 20px; + padding-right: 20px; + padding-bottom: 10px; + font-size: 14px; +} + +@media only screen and (max-width: 520px) { + .PopupContainer { + width: calc(100% - 40px); + } +} + +.messageOverHeader { + // color: rgba(0, 0, 0, 0.4); + color: $hrColor-DarkBlue; + display: block; + height: 0px; + top: -15px; + left: -25px; + position: relative; +} + +.login-header { + color: $hrColor-DarkBlue; + font-size: 30px; + margin: 30px 0; + font-weight: bold; +} + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto auto auto; // row relationships + grid-template-columns: minmax(0, 1fr); // column relationship + grid-column-gap: 15px; + grid-template-areas: + 'login-name' + 'login-password' + 'login-btn-block' + 'login-error' +} + +.messageBoxHeader { + text-align: center; +} + +.mat-stroked-button.mat-accent { + color: white; + background: $hrColor-DarkBlue; +} + + +.login-error { + padding: 16px; + color: $hrColor-Error; + background-color: $hrColor-LightBlue; + // border-radius: $hrBorder-radius-small; + // border: 1px solid; + border-color: $hrColor-DarkBlue; +} + +.login-btn-block { + margin-top: 20px; + grid-area: login-btn-block; +} + + +.login-name { + grid-area: login-name; +} + +.login-password { + grid-area: login-password; +} + +.spinner { + margin-top: -140px; + margin-left: 35%; + z-index: 10; +} + + +.mat-stroked-button[disabled] { + background-color: rgba(0, 0, 0, 0.26); + color: rgba(0, 0, 0, 0.46); +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.ts new file mode 100644 index 0000000..11c336b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-popup/login-popup.component.ts @@ -0,0 +1,70 @@ +import { AfterViewInit, Component, Inject, OnDestroy, ViewChild } from '@angular/core'; +import { Subscription } from 'rxjs'; +import { Globals } from '../../../services/globals'; +import { ENVIRONMENT_TOKEN, IENVIRONMENT } from '../../../injection-tokens'; +import { AuthorizeService } from '../../../services/authorize.service'; +import { HenselTranslateService } from '../../../services/localization/hensel-translate.service'; +import { MAT_DIALOG_DATA, MatDialogRef } from '../../../components/angular-material-index'; +import { HenselInputComponent } from '@app_core/components/hensel-input/hensel-input.component'; + + +@Component({ + selector: 'app-login-popup', + templateUrl: 'login-popup.component.html', + styleUrls: ['login-popup.component.scss'], +}) + +export class LoginPopupComponent implements AfterViewInit, OnDestroy { + public static LOGIN_IS_SHOWN: boolean = false; + public overHeader: string; + public header: string; + public errorMsg: string; + public hide: boolean = true; + public authorizationService: AuthorizeService; + private userSubscription: Subscription; + public showSpinner: boolean = false; + + constructor( + public dialogRef: MatDialogRef, + public globals: Globals, + public translate: HenselTranslateService, + @Inject(MAT_DIALOG_DATA) data: any, + @Inject(ENVIRONMENT_TOKEN) public environment: IENVIRONMENT + ) { + this.overHeader = this.globals.appTitleWithVersion; + this.header = translate.instant('core.caption.registration'); + this.errorMsg = data.errorMsg; + this.authorizationService = data.authorizationService; + this.userSubscription = this.authorizationService.loginAction$.subscribe((resultObject) => { + this.showSpinner = false; + if (resultObject.result) this.close(); + else { + this.errorMsg = resultObject.errMsg; + } + }); + } + + + ngAfterViewInit(): void { + LoginPopupComponent.LOGIN_IS_SHOWN = true; + } + + + close() { + this.dialogRef.close(); + } + + + ngOnDestroy() { + this.userSubscription.unsubscribe(); + LoginPopupComponent.LOGIN_IS_SHOWN = false; + // if (!this.authorizationService.isLoggedIn()) this.authorizationService.loginPopup(); - is not realy needed + } + + login(loginname: string, passw: string) { + if (!loginname || !passw) return; + this.showSpinner = true; + this.authorizationService.login(loginname, passw); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-routing.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-routing.module.ts new file mode 100644 index 0000000..c03dafa --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { LoginComponent } from './login.component'; + + +const routes: Routes = [ + { + path: '**', + component: LoginComponent, + // canActivate: [AuthGuard], + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) + +export class LoginRoutingModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.html new file mode 100644 index 0000000..ecef1ea --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.html @@ -0,0 +1,32 @@ + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.scss new file mode 100644 index 0000000..2b6ba2c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.scss @@ -0,0 +1,52 @@ +@import 'hr-core-consts'; + +.login-wrapper { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 0; + margin: 0; + overflow: visible; + display: grid; + grid-column-gap: 15px; + grid-row-gap: 0; + grid-template-columns: repeat(1, minmax(0, auto)); + grid-template-rows: auto repeat(1, minmax(0, 1fr)); + grid-template-areas: + "login-header" + "login-body" +} + +.login-body { + grid-area: login-body; +} + + +.login-header { + grid-area: login-header; + color: $hrColor-DarkBlue; + font-size: 30px; + text-align: center; + margin: 0; +} + +.box { + margin: 2px; + padding: 50px; + width: auto; + border-radius: $hrBorder-radius-big; + max-width: 330px; +} + + +.sub-box { + display: flex; + justify-content: center; + width: auto; +} + +.mat-stroked-button.mat-accent { + color: white; + background: $hrColor-DarkBlue; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.spec.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.spec.ts new file mode 100644 index 0000000..7cb1f3c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoginComponent } from './login.component'; + +describe('LoginComponent', () => { + let component: LoginComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [LoginComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LoginComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.ts new file mode 100644 index 0000000..1bee0cf --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.component.ts @@ -0,0 +1,95 @@ +import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { interval, Subscription } from 'rxjs'; +import { Globals } from '../../services/globals'; +import { ServerInfo } from '../../models/serverinfo'; +import { AppLogsService } from '../../services/applogs.service'; +import { AuthorizeService } from '../../services/authorize.service'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { UINotifierService } from '../../services/notification/uinotifier.service'; +import { PageLoadingService } from '../../services/pageloading.service'; +import { ServerInfoService } from '../../services/serverinfo.service'; +import { LoginPopupComponent } from './login-popup/login-popup.component'; + +@Component({ + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.scss'], +}) + +export class LoginComponent implements OnInit, OnDestroy, AfterViewInit { + + public title: string; + private userLoginSubscription: Subscription; + public serverInfo: ServerInfo; + private returnUrl: string; + private connectionReadySubscription: Subscription; + private checkLoginPopupSubscription: Subscription; + constructor( + public translate: HenselTranslateService, + private globals: Globals, + private serverInfoService: ServerInfoService, + private routerService: Router, + public authorizationService: AuthorizeService, + private appLogsService: AppLogsService, + private uiNotifier: UINotifierService, + private route: ActivatedRoute, + protected pageLoadingService: PageLoadingService, + + ) { + this.title = this.globals.appTitle; + this.userLoginSubscription = this.authorizationService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { + if (!this.globals.isTheMainPage(this.returnUrl) && this.authorizationService.isLoggedUserChanged()) this.returnUrl = '/' + globals.mainPage.path; + const path = this.returnUrl; //'/' + globals.mainPage.path + this.appLogsService.dlog('After login goto ' + path); + this.routerService.navigate([path]); + } else { + if (this.authorizationService.loginStatus !== this.authorizationService.EN_LoginStatus_Password) { + this.authorizationService.loginPopup(resultObject.errMsg); //show popup only if automatically authorization failed + } + } + }); + } + + + ngOnInit(): void { + this.connectionReadySubscription = this.serverInfoService.connectionReady.subscribe((si: ServerInfo) => { + if (si) { + this.serverInfo = si; + this.doLogin(); + } + }); + + this.checkLoginPopupSubscription = interval(500).subscribe(() => { + if (this.serverInfo + && !this.authorizationService.isLoggedIn() + && this.authorizationService.loginStatus !== this.authorizationService.EN_LoginStatus_Unknown + && !LoginPopupComponent.LOGIN_IS_SHOWN) { + this.doLogin(); + } + }); + } + + ngAfterViewInit() { } + + private doLogin() { + this.returnUrl = this.route.snapshot.queryParams['returnUrl']; + this.appLogsService.dlog('show login', this.authorizationService.user); + if (!this.returnUrl) this.returnUrl = '/' + this.globals.mainPage.path; + + if (this.authorizationService.loginStatus === this.authorizationService.EN_LoginStatus_Unknown) { //first time is called + this.authorizationService.login(); + } else { + this.serverInfoService.serverInfoVisible = this.serverInfoService.defaultServerInfoVisible || this.serverInfoService.serverInfoVisible; + this.authorizationService.loginPopup(null, true /* clears last used login and calls logout$ event */); + } + } + + ngOnDestroy() { + this.userLoginSubscription?.unsubscribe(); + this.connectionReadySubscription?.unsubscribe(); + this.checkLoginPopupSubscription?.unsubscribe(); + + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.module.ts new file mode 100644 index 0000000..15c9281 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/login/login.module.ts @@ -0,0 +1,25 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { LoginRoutingModule } from './login-routing.module'; +import { LoginComponent } from './login.component'; +import { AngularMaterialModule } from '../angular-material.module'; +import { LoginPopupComponent } from './login-popup/login-popup.component'; +import { FormsModule } from '@angular/forms'; +import { TranslateModule } from '@ngx-translate/core'; +import { HenselInputComponent } from '../hensel-input/hensel-input.component'; + +@NgModule({ + declarations: [LoginComponent, LoginPopupComponent], + imports: [ + CommonModule, + LoginRoutingModule, + AngularMaterialModule, + FormsModule, + HenselInputComponent, + TranslateModule.forChild() + ], + exports: [LoginComponent] +}) + +export class LoginModule { +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.html new file mode 100644 index 0000000..36936e1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.html @@ -0,0 +1,23 @@ +
+ + {{overHeader}} +

{{header}}

+ + info + warning + error_outline + contact_support + {{message}} + +
+ +
+
+
diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.scss new file mode 100644 index 0000000..0ba08c1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.scss @@ -0,0 +1,237 @@ +@import 'hr-core-consts'; + +.PopupContainer { + max-width: 500px; +} + +.large .PopupContainer { + max-width: 600px; +} + +.buttonClose { + font-size: 16px; + cursor: pointer; + text-align: center; + margin-left: auto; + float: right; +} + + +.messageOverHeader { + // color: rgba(0, 0, 0, 0.4); + color: $hrColor-DarkBlue; + display: block; + height: 0px; + top: -20px; + left: -15px; + position: relative; +} + +.large .messageOverHeader { + font-size: initial; +} + +.large .messageBoxHeader { + font-size: x-large; +} + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: 100%; + grid-template-columns: auto minmax(0, 1fr); + grid-template-rows: auto auto; + grid-column-gap: 15px; + grid-row-gap: 20px; + grid-template-areas: + 'icon message' + 'buttons buttons' +} + +.icon { + grid-area: icon; + font-size: 65px; + // float: left; + // padding: 10px 10px 0px 10px; +} + +.large .icon { + font-size: 80px; +} + +.infoIcon { + color: $hrColor-DarkBlue; +} + +.errorIcon { + color: red; +} + + +.warningIcon { + color: $hrColor-DarkBlue; +} + + +.message { + grid-area: message; + font-size: larger; + overflow-wrap: break-word; + max-width: 100%; + margin: auto; + margin-left: 0; + white-space: pre-wrap; +} + +.large .message { + font-size: large; +} + +.buttons1 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: auto; + grid-template-rows: auto; + grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-column-gap: 30px; + grid-template-areas: + '. btn1 .' +} + + +.buttons2 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: auto; + grid-template-rows: auto; + grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-column-gap: 30px; + grid-template-areas: + '. btn1 btn2 .' +} + + +.buttons3 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin-left: 0px; + margin-top: 10px; + margin-right: 0px; + margin-bottom: 0px; + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: auto; + grid-template-rows: auto; + grid-template-columns: minmax(0, 1fr) repeat(3, minmax(0, 2fr)) minmax(0, 1fr); + grid-column-gap: 30px; + grid-template-areas: + '. btn1 btn2 btn3 .' +} + + +.btn1 { + grid-area: btn1; +} + +.btn2 { + grid-area: btn2; +} + +.btn3 { + grid-area: btn3; +} + + +.large .btn, +.large .new-btn { + font-size: medium; +} + +.new-buttons1 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: auto; + grid-template-rows: auto; + grid-column-gap: 10px; + grid-template-columns: repeat(3, 1fr); + grid-template-areas: + '. . btn1' +} + +.new-buttons2 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; + height: auto; + grid-template-rows: auto; + grid-column-gap: 10px; + grid-template-columns: repeat(4, 1fr); + grid-template-areas: + '. . btn1 btn2' +} + + +.new-buttons3 { + grid-area: buttons; + padding: 0; // no extra padding -> padding is calculated in the child comp + margin-left: 0px; + margin-top: 10px; + margin-right: 0px; + margin-bottom: 0px; + overflow: hidden; // overflow hidden => all "to big" child components are hidden + height: auto; + display: grid; + grid-template-rows: auto; + grid-column-gap: 10px; + grid-template-columns: repeat(5, 1fr); + grid-template-areas: + '. . btn1 btn2 btn3' +} + +@media only screen and (max-width: 600px) { + .new-buttons1 { + grid-template-columns: 0.5fr 1fr 0.5fr; + grid-template-areas: + '. btn1 .' + } +} + +@media only screen and (max-width: 600px) { + .new-buttons3 .mat-button, + .new-buttons3 .mat-fab, + .new-buttons3 .mat-flat-button, + .new-buttons3 .mat-icon-button, + .new-buttons3 .mat-mini-fab, + .new-buttons3 .mat-raised-button, + .new-buttons3 .mat-stroked-button { + font-size: 3v; + } + + .new-buttons2 { + grid-template-columns: repeat(2, 1fr); + grid-template-areas: + 'btn1 btn2' + } + + .new-buttons3 { + grid-template-columns: repeat(3, 1fr); + grid-template-areas: + 'btn1 btn2 btn3' + } +} + + +// ::ng-deep .mat-button-focus-overlay { background-color: inherit; } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.ts new file mode 100644 index 0000000..92a47c8 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.component.ts @@ -0,0 +1,85 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { AfterViewInit, Component, HostListener, Inject, ViewChild } from '@angular/core'; +import { NgForm } from '@angular/forms'; +import * as Cnst from '../../consts'; +import { Globals, IMessageBoxButton, IMessageBoxData } from '../../services/globals'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { MAT_DIALOG_DATA, MatDialogRef } from '../angular-material-index'; + +const enum EN_MessageBoxInterfaceType { + old = '', + new = 'new-' +} + +@Component({ + // tslint:disable-next-line: component-selector + selector: 'hr-message-box', + templateUrl: 'message-box.component.html', + styleUrls: ['message-box.component.scss'], +}) + +export class MessageBoxComponent implements AfterViewInit { + @ViewChild('popupForm') detailForm: NgForm; + + public description: string; + public readOnly: boolean = false; + public messageBoxInterfaceType: EN_MessageBoxInterfaceType = EN_MessageBoxInterfaceType.new; + + public overHeader: string; + public header: string; + public message: string; + public buttons: IMessageBoxButton[]; + public cancelButtonIdx: number; + public defaultButtonIdx: number; + public messageType: Cnst.EN_LogType; + + constructor( + public dialogRef: MatDialogRef, + public translate: HenselTranslateService, + public globals: Globals, + @Inject(MAT_DIALOG_DATA) data: IMessageBoxData + ) { + this.overHeader = this.translate.translateString(data.overHeader); + this.header = this.translate.translateString(data.header); + this.message = this.translate.translateString(data.message); + this.buttons = data.buttons; + this.messageType = data.type; + if (this.buttons.length === 1) { + this.buttons[0].default = true; + this.buttons[0].cancel = true; + } + this.buttons.forEach((btn: IMessageBoxButton, index: number) => { + if (btn.default) this.defaultButtonIdx = index; + if (btn.cancel) this.cancelButtonIdx = index; + if (!btn.code) btn.code = 0; + }); + } + + ngAfterViewInit(): void { + setTimeout(() => document.getElementById('btn' + (this.defaultButtonIdx + 1))?.focus()); + } + + close(code: number) { + this.dialogRef.close(code); + } + + btnClick(btn: IMessageBoxButton) { + this.close(btn?.code || 0); + } + + + @HostListener('window:keydown', ['$event']) + popupKeyboardInput(event: any) { + switch (event.which) { + case keycode.ESCAPE: + event.stopPropagation(); + this.btnClick(this.buttons[this.cancelButtonIdx]); + return false; + case keycode.ENTER: + event.stopPropagation(); + this.btnClick(this.buttons[this.defaultButtonIdx]); + return false; + } + return true; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.module.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.module.ts new file mode 100644 index 0000000..2404f05 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/message-box/message-box.module.ts @@ -0,0 +1,21 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { AngularMaterialModule } from '../angular-material.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { MessageBoxComponent } from './message-box.component'; +import { MatDialogModule } from '../angular-material-index'; + + +@NgModule({ + declarations: [MessageBoxComponent], + imports: [ + CommonModule, + AngularMaterialModule, + MatDialogModule, + FormsModule, + TranslateModule.forChild(), + ], + exports: [MessageBoxComponent], +}) +export class MessageBoxModule { } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.html b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.html new file mode 100644 index 0000000..244bae6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.html @@ -0,0 +1,29 @@ + diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.scss b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.scss new file mode 100644 index 0000000..6904b86 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.scss @@ -0,0 +1,66 @@ +// .PopupContainer { +// // padding: 20px; +// } + + +.buttonLayoutCancel { + font-size: 16px; + cursor: pointer; + text-align: center; + margin-left: auto; + float: right; +} + + +.HeaderInfo { + font-size: 16px; + margin-left: -5px; +} + + +.PopupContent { + padding: 0 0 0; // no extra padding -> padding is calculated in the child comp + margin: 0; // see above + overflow: hidden; // overflow hidden => all "to big" child components are hidden + display: grid; // we define a grid: ; + height: 100%; // 100% view height + grid-template-rows: auto auto; // row relationships + grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); // column relationship + grid-column-gap: 15px; + grid-template-areas: + 'field1 field2' + 'buttons buttons' +} + +.buttons { + grid-area: buttons; + padding: 0; + margin: 0; + overflow: hidden; + display: grid; + height: 100%; + grid-template-rows: auto; + grid-template-columns: repeat(4, minmax(0, 1fr)); + grid-column-gap: 30px; + grid-template-areas: + 'empty1 btnsave btncancel empty2' +} + + +.btnSave { + margin-top: 10px; + grid-area: btnsave; +} + +.btnCancel { + margin-top: 10px; + grid-area: btncancel; +} + +.field1 { + grid-area: field1; +} + +.field2 { + grid-area: field2; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.ts b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.ts new file mode 100644 index 0000000..29229a7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/components/popup-base/popup-base.component.ts @@ -0,0 +1,91 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { AfterViewInit, Component, HostListener, inject, Inject, QueryList, ViewChild, ViewChildren } from '@angular/core'; +import { NgForm } from '@angular/forms'; +import { Globals } from '../../services/globals'; +import { BaseEntity } from '../../models/generics/baseentity'; +import { BaseEntityWrapper } from '../../models/generics/baseentity.wrapper'; +import { BaseEntityListWrapper } from '../../models/generics/baseentitylist.wrapper'; +import { MAT_DIALOG_DATA, MatDialogRef, MatFormField } from '../angular-material-index'; + + +@Component({ + selector: 'app-popup-base', + templateUrl: 'popup-base.component.html', + styleUrls: ['popup-base.component.scss'], +}) + +export class PopupBaseComponent implements AfterViewInit { + @ViewChild('popupForm') detailForm: NgForm; + @ViewChildren(MatFormField) materialInputFields: QueryList; + + public description: string; + public readOnly: boolean = false; + + public keyItemName: string; + public baseEntityWrapper: BaseEntityWrapper; + + protected _focusedItem: BaseEntity; + public get focusedItem(): BaseEntity { + return this._focusedItem; + } + public set focusedItem(value: BaseEntity) { + this._focusedItem = value; + } + + public list: BaseEntityListWrapper; + + public data = inject(MAT_DIALOG_DATA); + public globals = inject(Globals); + public dialogRef = inject(MatDialogRef); + private lastDetailForm; + + constructor( + ) { + this.save = this.save.bind(this); + this.baseEntityWrapper = this.data.baseEntityWrapper; + this.keyItemName = this.data.keyItemName; + this.description = this.data.description; + this.readOnly = this.data.readOnly; + this.list = this.data.list; + this._focusedItem = this.baseEntityWrapper?.entity; + } + + ngAfterViewInit(): void { + this.lastDetailForm = this.baseEntityWrapper.detailForm; + this.baseEntityWrapper.detailForm = this.detailForm; + // this.baseEntityWrapper.entityWasChanged = false; //!!!, if set false we cannot control that form could be opened already ready to save + const self = this; + setTimeout(() => { //to avoid ExpressionChangedAfterItHasBeenCheckedError + //mark as changed, otherwise required mat-form-field does not get class "mat-form-field-invalid" as should because of required + self.materialInputFields.forEach(matField => matField._control.ngControl.control.markAsDirty()); + // self.hsInputFields.forEach(hs => hs.markAsDirty()); + }, 0); + + } + + close(result: any) { + this.baseEntityWrapper.detailForm = this.lastDetailForm; + this.dialogRef.close(result); + } + + @HostListener('window:keydown', ['$event']) + popupKeyboardInput(event: any) { + if (!this.baseEntityWrapper.keyDownListenerStopped) { + switch (event.which) { + case keycode.ESCAPE: // ESC + event.stopPropagation(); + this.cancel(); + return false; + } + } + return true; + } + + cancel() { + this.baseEntityWrapper.cancelWithSave(this.save, () => this.close(false)); + } + + save() { + this.baseEntityWrapper.save(() => this.close(true)); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/consts.ts b/ClientApp/staff-db-ui/src/app/shared/core/consts.ts new file mode 100644 index 0000000..4cfc222 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/consts.ts @@ -0,0 +1,140 @@ +import { formatDate } from '@angular/common'; +import { ɵDEFAULT_LOCALE_ID } from '@angular/core'; +import * as moment_ from 'moment'; + +export const cnst_IP_ADDRESS_SOURCE_URL = 'https://api.ipify.org/?format=json'; +export const cnst_HEADER_KEY_LOGINNAME = 'Loginname'; +export const cnst_LoginAuth_URL = 'LoginWithAuthorization'; +export const cnst_LoginJWT_URL = 'LoginWithJWT'; +export const cnst_LoginPassw_URL = 'LoginWithNameAndPassword'; +export const cnst_JWT_Expired = 'Benutzerauthentifizierung ist abgelaufen!'; +export const cnst_CANCEL_ERROR = 'cancel_error'; +export const cnst_ErrorCode4Unauthorized = 401; + +export enum EN_AppColors { + returnRequestColor = 'green', + startRequestColor = 'blue', + + showSpinnerColor = 'gray', + hideSpinnerColor = 'red', +} + + +export const DATE_FORMATS = { + parse: { + dateInput: 'DD.MM.YYYY', + }, + display: { + dateInput: 'DD.MM.YYYY', + monthYearLabel: 'MMM YYYY', + dateA11yLabel: 'LL', + monthYearA11yLabel: 'MMMM YYYY', + monthShortName: 'MMM', + date4WebAPI: 'yyyy-MM-dd', + dateTime4JSON: 'yyyy-MM-ddTHH:mm:ss.SSS', + dateFormat: 'dd.MM.yyyy', + dateTimeFormat: 'dd.MM.yyyy HH:mm', + dateFormatHensel: 'd MMM YYYY', + momentFormat: { + date4WebAPI: 'YYYY-MM-DD', + dateTime4JSON: 'YYYY-MM-DDTHH:mm:ss.SSS', + dateFormat: 'DD.MM.YYYY', + dateTimeFormat: 'DD.MM.YYYY HH:mm', + }, + timeFormat: 'HH:mm', + }, +}; + + + +//Date format for dates in Web API +// Values for All/None in filter drop down list +export const enum EN_DropDownConst4Filter { + AllCaption = 'core.dropdown-option.all', + AllValueString = '*', + AllValueInt = 0, + NoneCaption = 'core.dropdown-option.none', + NoneValueString = '_', + NoneValueInt = -1 +} + + +export const enum EN_EntityEditingStates { + View = 0, + Edit = 1, + New = 2, + EditKey = 3, + Idle = 4 +} + +export const enum EN_EntityBeforeSaveCallBackResults { + Ok_Continue = 0, + Ok_Break = 1, + Error_Continue = 2, + Error_Break = 3 +} + +export const enum EN_Error { + Save = 'Saving unsucceeded' +} + +export enum EN_LogType { + message = 'Message', + warning = 'Warning', + error = 'Error', + confirmation = 'Question', + guid_message = 'HTTPtiming', + + debug_message = 'Debug', +} + +export enum EN_LoginStatus { + unknown = 0, + loginWithNameAndPassword = 1, + jwt = 2, + windowsAuthorizatoin = 3 +} + +export enum EN_DateFormats { + WebAPI = 0, + Date = 1, + DateTime = 2, + JSON = 3 +} + +Date.prototype.toJSON = function () { return formatDate(this, DATE_FORMATS.display.dateTime4JSON, ɵDEFAULT_LOCALE_ID /* does not matter a culture, we are using explicit date format*/); }; + +moment_.fn.toJSON = function () { return this.format(DATE_FORMATS.display.momentFormat.dateTime4JSON); }; + +export const GridExportButtonWidth = 21; + +export interface SupportedCulture { + culture: string; + country: string; + languageName: string; + flag?: string; +} + + +export interface SupportedLanguage { + langCode: string; + languageName: string; +} + +export const SUPPORTED_CULTURES: SupportedCulture[] = [ + {culture: 'de-DE', country: 'core.caption.country-ge', languageName: 'core.caption.lang-ge'}, + {culture: 'de-AT', country: 'core.caption.country-at', languageName: 'core.caption.lang-at'}, + {culture: 'en-GB', country: 'core.caption.country-gb', languageName: 'core.caption.lang-gb'}, + {culture: 'en-US', country: 'core.caption.country-us', languageName: 'core.caption.lang-us'}, + {culture: 'en-AU', country: 'core.caption.country-au', languageName: 'core.caption.lang-au'}, + {culture: 'fr-FR', country: 'core.caption.country-fr', languageName: 'core.caption.lang-fr'}, + {culture: 'en-MY', country: 'core.caption.country-my', languageName: 'core.caption.lang-my'}, + // {culture: 'ko-KR', country: 'core.caption.country-kr', languageName: 'core.caption.lang-kr'}, +]; + +export const SUPPORTED_LANGUAGES: SupportedLanguage[] = [ + {langCode: 'de', languageName: 'core.caption.lang-ge'}, + {langCode: 'en', languageName: 'core.caption.lang-us'}, + {langCode: 'fr', languageName: 'core.caption.lang-fr'}, + // {langCode: 'ko', languageName: 'core.caption.lang-kr'}, +]; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/0_base-dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/0_base-dir.scss new file mode 100644 index 0000000..d5b4c8c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/0_base-dir.scss @@ -0,0 +1,6 @@ +/*====================================== + BASE-DIRECTORY +======================================*/ + +@import 'hr-typography.scss'; +@import 'hr-spacing.scss'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core-consts.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core-consts.scss new file mode 100644 index 0000000..618e430 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core-consts.scss @@ -0,0 +1,47 @@ +/*==================================== + CI-COLORS +======================================*/ +$hrColor-DarkBlue: #0b3a62; +$hrColor-LightBlueMain: #76a9cb; +$hrColor-LightBlue: #78b7e5; +$hrColor-DarkGrey: #3c3c3b; +$hrColor-LightGrey: #878787; +$hrColor-Green: #76b82a; +$hrColor-Red: #B22222; +$hrColor-Error: #e71010; +$hrColor-Orange: #FF4500; +$hrColor-Alpha_Disabled: 0.8; +$hrColor-Link: #0180b9; + +/*==================================== + BORDER +======================================*/ +//radius +$hrBorder-radius-small: 4px; +$hrBorder-radius-middle: 8px; +$hrBorder-radius-big: 10px; + +//style +$hr-Border-style: solid; + +//border-color +$hr-Border-color: $hrColor-LightGrey; + +/*==================================== + Typography +======================================*/ +$hr-Fonts-small: 10px; +$hr-Fonts-medium: 15px; +$hr-Fonts-big: 30px; + +/*==================================== + Miscellaneous +======================================*/ +//positiv cell output +::ng-deep .cell_positive_balance { + color: $hrColor-Green; +} +//negativ cell output +::ng-deep .cell_negative_balance { + color: $hrColor-Red; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core.scss new file mode 100644 index 0000000..5233474 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-core.scss @@ -0,0 +1,10 @@ +/*====================================== + BASE-IMPORT +======================================*/ + +//Import all DIR @ once +@import 'hr-core-consts.scss'; +@import '../3-vendor/3_vendor-dir.scss'; +@import '0_base-dir.scss'; +@import '../1-components/1_components_dir.scss'; +@import '../2-helpers/2_helper-dir.scss'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-spacing.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-spacing.scss new file mode 100644 index 0000000..99ac738 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-spacing.scss @@ -0,0 +1,43 @@ +/*===================================== + GLOBAL +======================================*/ +//margins, overflows or padding stylings +.summarySum { + overflow: inherit; +} + +.summaryAvg { + overflow: inherit; +} + +.summaryPercent { + overflow: inherit; +} + +.summarySumOdd { + overflow: visible; +} + +/*==================================== + BUTTON +======================================*/ +.btn_spacing { + margin-right: 10px; +} + +/*==================================== + Angular specific +======================================*/ +::ng-deep .ng-star-inserted { + margin-right: 0px !important; +} + +.ng-star-inserted-item { + margin-right: 15px !important; +} + + +//Number alligment +.number { + text-align: right !important; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-typography.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-typography.scss new file mode 100644 index 0000000..9c927c3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/0-base/hr-typography.scss @@ -0,0 +1,47 @@ +@import 'hr-core-consts.scss'; +/*===================================== + TYPOGRAPHY +======================================*/ +// Acitve link styling for navbar +a { + text-decoration: none; + color: white; +} + +a:hover, +a:active { + color: $hrColor-LightBlue; +} + +a:hover.selected { + color: white; +} + +.selected { + color: $hrColor-LightBlue; +} + +/*=========================================================================================================================*/ + +// Sum styling before and after +.summarySum::before { + // content: "\2211\0020"; //summ symbol+space + font-size: larger; +} + +.summaryAvg::before { + content: "\2300\0020"; //avg symbol+space + font-size: 17px; + zoom: 1.4; + vertical-align: top; +} + +.summarySumOdd::before { + content: "\2211\0020"; //summ symbol+space + font-size: larger; +} + +.summaryPercent::after { + content: "\0025"; //space+% symbol + font-size: larger; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/1_components_dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/1_components_dir.scss new file mode 100644 index 0000000..8513cf7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/1_components_dir.scss @@ -0,0 +1,10 @@ +/*==================================== + COMPONENTS-DIRECTORY +======================================*/ + +@import 'hr-grids.scss'; +@import 'hr-toolbars.scss'; +@import 'hr-button.scss'; +@import 'hr-checkbox.scss'; +@import 'hr-additional.scss'; +@import 'hr-badge.scss'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-additional.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-additional.scss new file mode 100644 index 0000000..fa6257e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-additional.scss @@ -0,0 +1,35 @@ +/*==================================== + HR-ADDITIONAL +======================================*/ + +.datePicker { + border-bottom: 1px dotted gray; +} + +.hensel-notifier { + background-color: rgba(0, 0, 0, 0.4); + // color: rgba(0, 0, 0, 0.7); + color: rgba(255, 255, 255, 1); + // color: $hrColor-DarkBlue; +} + +.mat-calendar-next-button::after, +.mat-calendar-previous-button::after { + margin: 7.5px !important; +} + + +.messageBoxHeader { + font-size: large !important; + font-weight: bold !important; + margin-bottom: 0px !important; + padding: 0 0 10px 0 !important; +} + +.glowButton { + box-shadow: 0 5px 20px orangered !important; +} + +.mat-sidenav { + --mat-sidenav-container-background-color: white; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-badge.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-badge.scss new file mode 100644 index 0000000..6c8dcaf --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-badge.scss @@ -0,0 +1,192 @@ +[hr-badge-after], +[hr-badge-before] { + --badge-offset-x: calc(0px - var(--badge-size) / 3); + --badge-offset-y: calc(0px - var(--badge-size) / 3); + --badge-size: 1.5rem; + --circle-size: 2rem; + --dot-offset: 0.5rem; + --dot-size: 0.5rem; + + --badge-bottom: initial; + --badge-background-color: hsl(195, 100%, 30%); + --badge-border-radius: 0; + --badge-color: hsl(195, 100%, 99%); + --badge-display: inline-flex; + --badge-font-size: 0.625rem; + --badge-font-weight: 700; + --badge-hight: auto; + --badge-left: initial; + --badge-padding: 0; + --badge-position: static; + --badge-right: initial; + --badge-top: initial; + --badge-text-transform: uppercase; + --badge-width: initial; + + position: relative; +} + +[hr-badge-after]:not([hr-badge-after=""])::after { + content: attr(hr-badge-after); +} + +[hr-badge-font-size]:not([hr-badge-font-size=""]) { + --badge-font-size: attr(hr-badge-font-size); +} + +[hr-badge-before]:not([hr-badge-before=""])::before { + content: attr(hr-badge-before); +} + +[hr-badge-after]:not([hr-badge-after=""])::after, +[hr-badge-before]:not([hr-badge-before=""])::before { + align-items: center; + background: var(--badge-background-color) !important; + border-radius: var(--badge-border-radius); + bottom: var(--badge-bottom); + box-shadow: var(--bxsh); + box-sizing: border-box; + color: var(--badge-color); + display: var(--badge-display); + font-size: var(--badge-font-size); + font-weight: var(--badge-font-weight); + height: var(--badge-hight); + justify-content: center; + left: var(--badge-left); + padding: var(--badge-padding); + position: var(--badge-position); + right: var(--badge-right); + text-decoration: none; + text-transform: var(--badge-text-transform); + top: var(--badge-top); + width: var(--badge-width); +} + +/* MODIFIERS */ +[hr-badge-after-type*="badge"]::after, +[hr-badge-before-type*="badge"]::before { + --badge-border-radius: var(--badge-size); + --bxsh: 0 0 0 2px rgba(255, 255, 255, 0.5); + --badge-hight: var(--badge-size); + --badge-padding: 0; + --badge-position: absolute; + --badge-width: var(--badge-size); +} +[hr-badge-after-type*="circle"], +[hr-badge-before-type*="circle"]{ + align-items: center; + display: flex; +} +[hr-badge-after-type*="circle"]::after, +[hr-badge-before-type*="circle"]::before { + --badge-border-radius: 50%; + --badge-font-weight: 400; + --badge-hight: var(--circle-size); + // --badge-position: relative; + // --badge-top: -0.75em; + --badge-text-transform: initial; + --badge-width: var(--circle-size); +} +[hr-badge-after-type*="circle"]::after, +[hr-badge-after-type*="pill"]::after { + margin-inline-start: 1ch; +} +[hr-badge-before-type*="circle"]::before, +[hr-badge-before-type*="dot"]::before, +[hr-badge-before-type*="pill"]::before { + margin-inline-end: 1ch; +} +[hr-badge-after-type*="dot"]::after, +[hr-badge-before-type*="dot"]::before { + --badge-border-radius: 50%; + --badge-display: inline-block; + --badge-font-size: 50%; + --badge-hight: var(--dot-size); + --badge-padding: 0; + --badge-position: relative; + --badge-top: -1px; + --badge-width: var(--dot-size); +} +[hr-badge-after-type*="dot"]::after, +[hr-badge-before-type*="dot"]::before { + content: "" !important; +} +[hr-badge-after-type*="pill"]::after, +[hr-badge-before-type*="pil"]::before { + --badge-border-radius: 1rem; + --badge-padding: 0.25rem 0.75rem; + --badge-position: relative; + --badge-top: -1px; +} + +/* COLORS */ +[hr-badge-after-type*="blue"]::after, +[hr-badge-before-type*="blue"]::before { + --badge-background-color: #007acc; +} +[hr-badge-after-type*="darkgray"]::after, +[hr-badge-before-type*="darkgray"]::before { + --badge-background-color: #706e6b; + --badge-color: #fff; +} +[hr-badge-after-type*="green"]::after, +[hr-badge-before-type*="green"]::before { + --badge-background-color: #04844b; +} +[hr-badge-after-type*="lightgray"]::after, +[hr-badge-before-type*="lightgray"]::before { + --badge-background-color: #ecebea; + --badge-color: #080707; +} +[hr-badge-after-type*="orange"]::after, +[hr-badge-before-type*="orange"]::before { + --badge-background-color: #ffb75d; + --badge-color: #080707; +} + +[hr-badge-after-type*="red"]::after, +[hr-badge-before-type*="red"]::before { + --badge-background-color: #ff0900;//#c23934; +} + +/* POSITION */ +[hr-badge-after-type*="top"]::after, +[hr-badge-before-type*="top"]::before { + --badge-bottom: auto; + --badge-position: absolute; + --badge-top: var(--dot-offset); +} +[hr-badge-after-type*="right"]::after, +[hr-badge-before-type*="right"]::before { + --badge-left: auto; + --badge-position: absolute; + --badge-right: var(--dot-offset); +} +[hr-badge-after-type*="bottom"]::after, +[hr-badge-before-type*="bottom"]::before { + --badge-bottom: var(--dot-offset); + --badge-position: absolute; + --badge-top: auto; +} +[hr-badge-after-type*="left"]::after, +[hr-badge-before-type*="left"]::before { + --badge-position: absolute; + --badge-right: auto; + --badge-left: var(--dot-offset); +} +[hr-badge-after-type*="badge"][hr-badge-after-type*="top"]::after, +[hr-badge-before-type*="badge"][hr-badge-before-type*="top"]::before { + --badge-top: var(--badge-offset-y); +} +[hr-badge-after-type*="badge"][hr-badge-after-type*="right"]::after, +[hr-badge-before-type*="badge"][hr-badge-before-type*="right"]::before { + --badge-right: var(--badge-offset-x); +} +[hr-badge-after-type*="badge"][hr-badge-after-type*="bottom"]::after, +[hr-badge-before-type*="badge"][hr-badge-before-type*="bottom"]::before { + --badge-bottom: var(--badge-offset-y); +} +[hr-badge-after-type*="badge"][hr-badge-after-type*="left"]::after, +[hr-badge-before-type*="badge"][hr-badge-before-type*="left"]::before { + --badge-left: var(--badge-offset-x); +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-button.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-button.scss new file mode 100644 index 0000000..73f55fa --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-button.scss @@ -0,0 +1,11 @@ +/*===================================== + HR-BUTTON +======================================*/ +.filterButtons .filterBtn { + margin-left: 2px; + // margin-right: 1px; + margin-top: 6px; + padding-right: 5px !important; + padding-left: 5px !important; + width: 90px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-checkbox.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-checkbox.scss new file mode 100644 index 0000000..c20bd75 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-checkbox.scss @@ -0,0 +1,9 @@ +/*===================================== + Checkboxes +======================================*/ + +.hr-check-box { + margin-top: 13px; + float: right; + text-align: right; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-grids.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-grids.scss new file mode 100644 index 0000000..a1b1e69 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-grids.scss @@ -0,0 +1,3 @@ +/*===================================== + Grid's +======================================*/ diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-toolbars.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-toolbars.scss new file mode 100644 index 0000000..4b37489 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/1-components/hr-toolbars.scss @@ -0,0 +1,32 @@ +/*===================================== + Toolbar's +======================================*/ + +//--- tool bar settings +.mat-toolbar { + --mat-toolbar-title-text-weight: 500; + --mat-toolbar-title-text-size: 20px; +} + +.toolbar-button-row { + display: table; +} + +.toolbar-button-row button { + display: table-cell; + margin-right: 1px !important; +} + +.toolbar-flex-container { + display: flex; + justify-content: space-between; + width: auto; + height: 100%; + padding-top: 1px; + padding-left: 2px; + flex-direction: column; +} + +.toolbar-button-last { + margin-right: 0 !important; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/2_helper-dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/2_helper-dir.scss new file mode 100644 index 0000000..ee3ba51 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/2_helper-dir.scss @@ -0,0 +1,5 @@ +/*==================================== + HELPER'S-DIRECTORY +======================================*/ + +@import 'hr-functionalities.scss'; \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/hr-functionalities.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/hr-functionalities.scss new file mode 100644 index 0000000..18384c5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/2-helpers/hr-functionalities.scss @@ -0,0 +1,53 @@ +@import '0_base-dir.scss'; +/*===================================== + Functionalities +======================================*/ + +//disable clicks in selected area +.disableClicks { + background-color: rgba(1, 1, 1, 0.4); + // pointer-events: none; + // background: rgba(0, 0, 0, 0.32); + // opacity: 1; + position: fixed; + bottom: 0; + left: 0; + right: 0; + top: 0; + z-index: 3; +} + + +//disable certain/choosen html elements +.HTMLelement_disabled { + pointer-events: none; + cursor: default; + color: rgba(255, 255, 255, 0.6) !important; +} + + +//hover over url turns CI blue +.url:hover { + color: $hrColor-DarkBlue; + cursor: pointer; +} + +.underline { + text-decoration: underline; +} + +.url { + color: $hrColor-Link; + @extend .underline; +} + +.cdk-global-scrollblock { + overflow-y: inherit; +} + +.cdk-overlay-pane { + width: auto !important; + min-width: 200px; + font-size: 14px; + max-width: calc(100vw - 100px) !important; //max-width of popups +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/3_vendor-dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/3_vendor-dir.scss new file mode 100644 index 0000000..3235233 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/3_vendor-dir.scss @@ -0,0 +1,10 @@ +/*==================================== + VENDOR'S-DIRECTORY +======================================*/ + +//vendor scss libary imports +@import './external-vendor/indigo-pink.scss'; + +//hr vendor styling imports +@import 'hr-devextreme-styling/3_dx-dir.scss'; +@import 'hr-material-styling/3_mat-dir.scss'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/external-vendor/indigo-pink.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/external-vendor/indigo-pink.scss new file mode 100644 index 0000000..39e41f5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/external-vendor/indigo-pink.scss @@ -0,0 +1,2918 @@ +.mat-badge-content { + font-weight: 600; + font-size: 12px; + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-badge-small .mat-badge-content { + font-size: 9px +} + +.mat-badge-large .mat-badge-content { + font-size: 24px +} + +.mat-h1, +.mat-headline, +.mat-typography h1 { + font: 400 24px/32px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 16px +} + +.mat-h2, +.mat-title, +.mat-typography h2 { + font: 500 20px/32px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 16px +} + +.mat-h3, +.mat-subheading-2, +.mat-typography h3 { + font: 400 16px/28px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 16px +} + +.mat-h4, +.mat-subheading-1, +.mat-typography h4 { + font: 400 15px/24px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 16px +} + +.mat-h5, +.mat-typography h5 { + font: 400 11.62px/20px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 12px +} + +.mat-h6, +.mat-typography h6 { + font: 400 9.38px/20px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 12px +} + +.mat-body-2, +.mat-body-strong { + font: 500 14px/24px Roboto, "Helvetica Neue", sans-serif +} + +.mat-body, +.mat-body-1, +.mat-typography { + font: 400 14px/20px Roboto, "Helvetica Neue", sans-serif +} + +.mat-body p, +.mat-body-1 p, +.mat-typography p { + margin: 0 0 12px +} + +.mat-caption, +.mat-small { + font: 400 12px/20px Roboto, "Helvetica Neue", sans-serif +} + +.mat-display-4, +.mat-typography .mat-display-4 { + font: 300 112px/112px Roboto, "Helvetica Neue", sans-serif; + letter-spacing: -.05em; + margin: 0 0 56px +} + +.mat-display-3, +.mat-typography .mat-display-3 { + font: 400 56px/56px Roboto, "Helvetica Neue", sans-serif; + letter-spacing: -.02em; + margin: 0 0 64px +} + +.mat-display-2, +.mat-typography .mat-display-2 { + font: 400 45px/48px Roboto, "Helvetica Neue", sans-serif; + letter-spacing: -.005em; + margin: 0 0 64px +} + +.mat-display-1, +.mat-typography .mat-display-1 { + font: 400 34px/40px Roboto, "Helvetica Neue", sans-serif; + margin: 0 0 64px +} + +.mat-bottom-sheet-container { + font: 400 14px/20px Roboto, "Helvetica Neue", sans-serif +} + +.mat-button, +.mat-fab, +.mat-flat-button, +.mat-icon-button, +.mat-mini-fab, +.mat-raised-button, +.mat-stroked-button { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: 500 +} + +.mat-button-toggle { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-card { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-card-title { + font-size: 24px; + font-weight: 500 +} + +.mat-card-header .mat-card-title { + font-size: 20px +} + +.mat-card-content, +.mat-card-subtitle { + font-size: 14px +} + +.mat-checkbox { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-checkbox-layout .mat-checkbox-label { + line-height: 24px +} + +.mat-chip { + font-size: 14px; + font-weight: 500 +} + +.mat-chip .mat-chip-remove.mat-icon, +.mat-chip .mat-chip-trailing-icon.mat-icon { + font-size: 18px +} + +.mat-table { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-header-cell { + font-size: 12px; + font-weight: 500 +} + +.mat-cell, +.mat-footer-cell { + font-size: 14px +} + +.mat-calendar { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-calendar-body { + font-size: 13px +} + +.mat-calendar-body-label, +.mat-calendar-period-button { + font-size: 14px; + font-weight: 500 +} + +.mat-calendar-table-header th { + font-size: 11px; + font-weight: 400 +} + +.mat-dialog-title { + font: 500 20px/32px Roboto, "Helvetica Neue", sans-serif +} + +.mat-expansion-panel-header { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 15px; + font-weight: 400 +} + +.mat-expansion-panel-content { + font: 400 14px/20px Roboto, "Helvetica Neue", sans-serif +} + +.mat-form-field { + font-size: inherit; + font-weight: 400; + line-height: 1.125; + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-form-field-wrapper { + padding-bottom: 1.34375em +} + +.mat-form-field-prefix .mat-icon, +.mat-form-field-suffix .mat-icon { + font-size: 150%; + line-height: 1.125 +} + +.mat-form-field-prefix .mat-icon-button, +.mat-form-field-suffix .mat-icon-button { + height: 1.5em; + width: 1.5em +} + +.mat-form-field-prefix .mat-icon-button .mat-icon, +.mat-form-field-suffix .mat-icon-button .mat-icon { + height: 1.125em; + line-height: 1.125 +} + +.mat-form-field-infix { + padding: .5em 0; + border-top: .84375em solid transparent +} + +.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label, +.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { + transform: translateY(-1.34375em) scale(.75); + width: 133.33333% +} + +.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.34374em) scale(.75); + width: 133.33334% +} + +.mat-form-field-label-wrapper { + top: -.84375em; + padding-top: .84375em +} + +.mat-form-field-label { + top: 1.34375em +} + +.mat-form-field-underline { + bottom: 1.34375em +} + +.mat-form-field-subscript-wrapper { + font-size: 75%; + margin-top: .66667em; + top: calc(100% - 1.79167em) +} + +.mat-form-field-appearance-legacy .mat-form-field-wrapper { + padding-bottom: 1.25em +} + +.mat-form-field-appearance-legacy .mat-form-field-infix { + padding: .4375em 0 +} + +.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label, +.mat-form-field-appearance-legacy.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { + transform: translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.001px); + -ms-transform: translateY(-1.28125em) scale(.75); + width: 133.33333% +} + +.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-form-field-autofill-control:-webkit-autofill+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00101px); + -ms-transform: translateY(-1.28124em) scale(.75); + width: 133.33334% +} + +.mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.28125em) scale(.75) perspective(100px) translateZ(.00102px); + -ms-transform: translateY(-1.28123em) scale(.75); + width: 133.33335% +} + +.mat-form-field-appearance-legacy .mat-form-field-label { + top: 1.28125em +} + +.mat-form-field-appearance-legacy .mat-form-field-underline { + bottom: 1.25em +} + +.mat-form-field-appearance-legacy .mat-form-field-subscript-wrapper { + margin-top: .54167em; + top: calc(100% - 1.66667em) +} + +@media print { + + .mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label, + .mat-form-field-appearance-legacy.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { + transform: translateY(-1.28122em) scale(.75) + } + + .mat-form-field-appearance-legacy.mat-form-field-can-float .mat-form-field-autofill-control:-webkit-autofill+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.28121em) scale(.75) + } + + .mat-form-field-appearance-legacy.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.2812em) scale(.75) + } +} + +.mat-form-field-appearance-fill .mat-form-field-infix { + padding: .25em 0 .75em 0 +} + +.mat-form-field-appearance-fill .mat-form-field-label { + top: 1.09375em; + margin-top: -.5em +} + +.mat-form-field-appearance-fill.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label, +.mat-form-field-appearance-fill.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { + transform: translateY(-.59375em) scale(.75); + width: 133.33333% +} + +.mat-form-field-appearance-fill.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-.59374em) scale(.75); + width: 133.33334% +} + +.mat-form-field-appearance-outline .mat-form-field-infix { + padding: 1em 0 1em 0 +} + +.mat-form-field-appearance-outline .mat-form-field-label { + top: 1.84375em; + margin-top: -.25em +} + +.mat-form-field-appearance-outline.mat-form-field-can-float .mat-input-server:focus+.mat-form-field-label-wrapper .mat-form-field-label, +.mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float .mat-form-field-label { + transform: translateY(-1.59375em) scale(.75); + width: 133.33333% +} + +.mat-form-field-appearance-outline.mat-form-field-can-float .mat-input-server[label]:not(:label-shown)+.mat-form-field-label-wrapper .mat-form-field-label { + transform: translateY(-1.59374em) scale(.75); + width: 133.33334% +} + +.mat-grid-tile-footer, +.mat-grid-tile-header { + font-size: 14px +} + +.mat-grid-tile-footer .mat-line, +.mat-grid-tile-header .mat-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + box-sizing: border-box +} + +.mat-grid-tile-footer .mat-line:nth-child(n+2), +.mat-grid-tile-header .mat-line:nth-child(n+2) { + font-size: 12px +} + +input.mat-input-element { + margin-top: -.0625em +} + +.mat-menu-item { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: 400 +} + +.mat-paginator, +.mat-paginator-page-size .mat-select-trigger { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 12px +} + +.mat-radio-button { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-select { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-select-trigger { + height: 1.125em +} + +.mat-slide-toggle-content { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-slider-thumb-label-text { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 12px; + font-weight: 500 +} + +.mat-stepper-horizontal, +.mat-stepper-vertical { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-step-label { + font-size: 14px; + font-weight: 400 +} + +.mat-step-sub-label-error { + font-weight: 400 +} + +.mat-step-label-error { + font-size: 14px +} + +.mat-step-label-selected { + font-size: 14px; + font-weight: 500 +} + +.mat-tab-group { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-tab-label, +.mat-tab-link { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: 500 +} + +.mat-toolbar, +.mat-toolbar h1, +.mat-toolbar h2, +.mat-toolbar h3, +.mat-toolbar h4, +.mat-toolbar h5, +.mat-toolbar h6 { + font: 500 20px/32px Roboto, "Helvetica Neue", sans-serif; + margin: 0 +} + +.mat-tooltip { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 10px; + padding-top: 6px; + padding-bottom: 6px +} + +.mat-tooltip-handset { + font-size: 14px; + padding-top: 8px; + padding-bottom: 8px +} + +.mat-list-item { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-list-option { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-list-base .mat-list-item { + font-size: 16px +} + +.mat-list-base .mat-list-item .mat-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + box-sizing: border-box +} + +.mat-list-base .mat-list-item .mat-line:nth-child(n+2) { + font-size: 14px +} + +.mat-list-base .mat-list-option { + font-size: 16px +} + +.mat-list-base .mat-list-option .mat-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + box-sizing: border-box +} + +.mat-list-base .mat-list-option .mat-line:nth-child(n+2) { + font-size: 14px +} + +.mat-list-base .mat-subheader { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px; + font-weight: 500 +} + +.mat-list-base[dense] .mat-list-item { + font-size: 12px +} + +.mat-list-base[dense] .mat-list-item .mat-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + box-sizing: border-box +} + +.mat-list-base[dense] .mat-list-item .mat-line:nth-child(n+2) { + font-size: 12px +} + +.mat-list-base[dense] .mat-list-option { + font-size: 12px +} + +.mat-list-base[dense] .mat-list-option .mat-line { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + box-sizing: border-box +} + +.mat-list-base[dense] .mat-list-option .mat-line:nth-child(n+2) { + font-size: 12px +} + +.mat-list-base[dense] .mat-subheader { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 12px; + font-weight: 500 +} + +.mat-option { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 16px +} + +.mat-optgroup-label { + font: 500 14px/24px Roboto, "Helvetica Neue", sans-serif +} + +.mat-simple-snackbar { + font-family: Roboto, "Helvetica Neue", sans-serif; + font-size: 14px +} + +.mat-simple-snackbar-action { + line-height: 1; + font-family: inherit; + font-size: inherit; + font-weight: 500 +} + +.mat-tree { + font-family: Roboto, "Helvetica Neue", sans-serif +} + +.mat-nested-tree-node, +.mat-tree-node { + font-weight: 400; + font-size: 14px +} + +.mat-ripple { + overflow: hidden; + position: relative +} + +.mat-ripple.mat-ripple-unbounded { + overflow: visible +} + +.mat-ripple-element { + position: absolute; + border-radius: 50%; + pointer-events: none; + transition: opacity, transform 0s cubic-bezier(0, 0, .2, 1); + transform: scale(0) +} + +@media (-ms-high-contrast:active) { + .mat-ripple-element { + display: none + } +} + +.cdk-visually-hidden { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + outline: 0; + -webkit-appearance: none; + -moz-appearance: none +} + +.cdk-global-overlay-wrapper, +.cdk-overlay-container { + pointer-events: none; + top: 0; + left: 0; + height: 100%; + width: 100% +} + +.cdk-overlay-container { + position: fixed; + z-index: 1000 +} + +.cdk-overlay-container:empty { + display: none +} + +.cdk-global-overlay-wrapper { + display: flex; + position: absolute; + z-index: 1000 +} + +.cdk-overlay-pane { + position: absolute; + pointer-events: auto; + box-sizing: border-box; + z-index: 1000; + display: flex; + max-width: 100%; + max-height: 100% +} + +.cdk-overlay-backdrop { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1000; + pointer-events: auto; + -webkit-tap-highlight-color: transparent; + transition: opacity .4s cubic-bezier(.25, .8, .25, 1); + opacity: 0 +} + +.cdk-overlay-backdrop.cdk-overlay-backdrop-showing { + opacity: 1 +} + +@media screen and (-ms-high-contrast:active) { + .cdk-overlay-backdrop.cdk-overlay-backdrop-showing { + opacity: .6 + } +} + +.cdk-overlay-dark-backdrop { + background: rgba(0, 0, 0, .32) +} + +.cdk-overlay-transparent-backdrop, +.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing { + opacity: 0 +} + +.cdk-overlay-connected-position-bounding-box { + position: absolute; + z-index: 1000; + display: flex; + flex-direction: column; + min-width: 1px; + min-height: 1px +} + +.cdk-global-scrollblock { + position: fixed; + width: 100%; + overflow-y: scroll +} + +@keyframes cdk-text-field-autofill-start { + /*!*/ +} + +@keyframes cdk-text-field-autofill-end { + /*!*/ +} + +.cdk-text-field-autofill-monitored:-webkit-autofill { + animation-name: cdk-text-field-autofill-start +} + +.cdk-text-field-autofill-monitored:not(:-webkit-autofill) { + animation-name: cdk-text-field-autofill-end +} + +textarea.cdk-textarea-autosize { + resize: none +} + +textarea.cdk-textarea-autosize-measuring { + height: auto !important; + overflow: hidden !important; + padding: 2px 0 !important; + box-sizing: content-box !important +} + +.mat-ripple-element { + background-color: rgba(0, 0, 0, .1) +} + +.mat-option { + color: rgba(0, 0, 0, .87) +} + +.mat-option:focus:not(.mat-option-disabled), +.mat-option:hover:not(.mat-option-disabled) { + background: rgba(0, 0, 0, .04) +} + +.mat-option.mat-selected:not(.mat-option-multiple):not(.mat-option-disabled) { + background: rgba(0, 0, 0, .04) +} + +.mat-option.mat-active { + background: rgba(0, 0, 0, .04); + color: rgba(0, 0, 0, .87) +} + +.mat-option.mat-option-disabled { + color: rgba(0, 0, 0, .38) +} + +.mat-primary .mat-option.mat-selected:not(.mat-option-disabled) { + color: #78b7e5 +} + +.mat-accent .mat-option.mat-selected:not(.mat-option-disabled) { + color: #78b7e5 +} + +.mat-warn .mat-option.mat-selected:not(.mat-option-disabled) { + color: #f44336 +} + +.mat-optgroup-label { + color: rgba(0, 0, 0, .54) +} + +.mat-optgroup-disabled .mat-optgroup-label { + color: rgba(0, 0, 0, .38) +} + +.mat-pseudo-checkbox { + color: rgba(0, 0, 0, .54) +} + +.mat-pseudo-checkbox::after { + color: #fafafa +} + +.mat-pseudo-checkbox-disabled { + color: #b0b0b0 +} + +.mat-accent .mat-pseudo-checkbox-checked, +.mat-accent .mat-pseudo-checkbox-indeterminate, +.mat-pseudo-checkbox-checked, +.mat-pseudo-checkbox-indeterminate { + background: #78b7e5 +} + +.mat-primary .mat-pseudo-checkbox-checked, +.mat-primary .mat-pseudo-checkbox-indeterminate { + background: #78b7e5 +} + +.mat-warn .mat-pseudo-checkbox-checked, +.mat-warn .mat-pseudo-checkbox-indeterminate { + background: #f44336 +} + +.mat-pseudo-checkbox-checked.mat-pseudo-checkbox-disabled, +.mat-pseudo-checkbox-indeterminate.mat-pseudo-checkbox-disabled { + background: #b0b0b0 +} + +.mat-elevation-z0 { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z1 { + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z2 { + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z3 { + box-shadow: 0 3px 3px -2px rgba(0, 0, 0, .2), 0 3px 4px 0 rgba(0, 0, 0, .14), 0 1px 8px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z4 { + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z5 { + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 5px 8px 0 rgba(0, 0, 0, .14), 0 1px 14px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z6 { + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 6px 10px 0 rgba(0, 0, 0, .14), 0 1px 18px 0 rgba(0, 0, 0, .12) +} + +.mat-elevation-z7 { + box-shadow: 0 4px 5px -2px rgba(0, 0, 0, .2), 0 7px 10px 1px rgba(0, 0, 0, .14), 0 2px 16px 1px rgba(0, 0, 0, .12) +} + +.mat-elevation-z8 { + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12) +} + +.mat-elevation-z9 { + box-shadow: 0 5px 6px -3px rgba(0, 0, 0, .2), 0 9px 12px 1px rgba(0, 0, 0, .14), 0 3px 16px 2px rgba(0, 0, 0, .12) +} + +.mat-elevation-z10 { + box-shadow: 0 6px 6px -3px rgba(0, 0, 0, .2), 0 10px 14px 1px rgba(0, 0, 0, .14), 0 4px 18px 3px rgba(0, 0, 0, .12) +} + +.mat-elevation-z11 { + box-shadow: 0 6px 7px -4px rgba(0, 0, 0, .2), 0 11px 15px 1px rgba(0, 0, 0, .14), 0 4px 20px 3px rgba(0, 0, 0, .12) +} + +.mat-elevation-z12 { + box-shadow: 0 7px 8px -4px rgba(0, 0, 0, .2), 0 12px 17px 2px rgba(0, 0, 0, .14), 0 5px 22px 4px rgba(0, 0, 0, .12) +} + +.mat-elevation-z13 { + box-shadow: 0 7px 8px -4px rgba(0, 0, 0, .2), 0 13px 19px 2px rgba(0, 0, 0, .14), 0 5px 24px 4px rgba(0, 0, 0, .12) +} + +.mat-elevation-z14 { + box-shadow: 0 7px 9px -4px rgba(0, 0, 0, .2), 0 14px 21px 2px rgba(0, 0, 0, .14), 0 5px 26px 4px rgba(0, 0, 0, .12) +} + +.mat-elevation-z15 { + box-shadow: 0 8px 9px -5px rgba(0, 0, 0, .2), 0 15px 22px 2px rgba(0, 0, 0, .14), 0 6px 28px 5px rgba(0, 0, 0, .12) +} + +.mat-elevation-z16 { + box-shadow: 0 8px 10px -5px rgba(0, 0, 0, .2), 0 16px 24px 2px rgba(0, 0, 0, .14), 0 6px 30px 5px rgba(0, 0, 0, .12) +} + +.mat-elevation-z17 { + box-shadow: 0 8px 11px -5px rgba(0, 0, 0, .2), 0 17px 26px 2px rgba(0, 0, 0, .14), 0 6px 32px 5px rgba(0, 0, 0, .12) +} + +.mat-elevation-z18 { + box-shadow: 0 9px 11px -5px rgba(0, 0, 0, .2), 0 18px 28px 2px rgba(0, 0, 0, .14), 0 7px 34px 6px rgba(0, 0, 0, .12) +} + +.mat-elevation-z19 { + box-shadow: 0 9px 12px -6px rgba(0, 0, 0, .2), 0 19px 29px 2px rgba(0, 0, 0, .14), 0 7px 36px 6px rgba(0, 0, 0, .12) +} + +.mat-elevation-z20 { + box-shadow: 0 10px 13px -6px rgba(0, 0, 0, .2), 0 20px 31px 3px rgba(0, 0, 0, .14), 0 8px 38px 7px rgba(0, 0, 0, .12) +} + +.mat-elevation-z21 { + box-shadow: 0 10px 13px -6px rgba(0, 0, 0, .2), 0 21px 33px 3px rgba(0, 0, 0, .14), 0 8px 40px 7px rgba(0, 0, 0, .12) +} + +.mat-elevation-z22 { + box-shadow: 0 10px 14px -6px rgba(0, 0, 0, .2), 0 22px 35px 3px rgba(0, 0, 0, .14), 0 8px 42px 7px rgba(0, 0, 0, .12) +} + +.mat-elevation-z23 { + box-shadow: 0 11px 14px -7px rgba(0, 0, 0, .2), 0 23px 36px 3px rgba(0, 0, 0, .14), 0 9px 44px 8px rgba(0, 0, 0, .12) +} + +.mat-elevation-z24 { + box-shadow: 0 11px 15px -7px rgba(0, 0, 0, .2), 0 24px 38px 3px rgba(0, 0, 0, .14), 0 9px 46px 8px rgba(0, 0, 0, .12) +} + +.mat-app-background { + background-color: #fafafa; + color: rgba(0, 0, 0, .87) +} + +.mat-theme-loaded-marker { + display: none +} + +.mat-autocomplete-panel { + background: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-autocomplete-panel:not([class*=mat-elevation-z]) { + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12) +} + +.mat-autocomplete-panel .mat-option.mat-selected:not(.mat-active):not(:hover) { + background: #fff +} + +.mat-autocomplete-panel .mat-option.mat-selected:not(.mat-active):not(:hover):not(.mat-option-disabled) { + color: rgba(0, 0, 0, .87) +} + +.mat-badge-content { + color: #fff; + background: #78b7e5 +} + +@media (-ms-high-contrast:active) { + .mat-badge-content { + outline: solid 1px; + border-radius: 0 + } +} + +.mat-badge-accent .mat-badge-content { + background: #78b7e5; + color: #fff +} + +.mat-badge-warn .mat-badge-content { + color: #fff; + background: #f44336 +} + +.mat-badge { + position: relative +} + +.mat-badge-hidden .mat-badge-content { + display: none +} + +.mat-badge-disabled .mat-badge-content { + background: #b9b9b9; + color: rgba(0, 0, 0, .38) +} + +.mat-badge-content { + position: absolute; + text-align: center; + display: inline-block; + border-radius: 50%; + transition: transform .2s ease-in-out; + transform: scale(.6); + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + pointer-events: none +} + +.mat-badge-content._mat-animation-noopable, +.ng-animate-disabled .mat-badge-content { + transition: none +} + +.mat-badge-content.mat-badge-active { + transform: none +} + +.mat-badge-small .mat-badge-content { + width: 16px; + height: 16px; + line-height: 16px +} + +.mat-badge-small.mat-badge-above .mat-badge-content { + top: -8px +} + +.mat-badge-small.mat-badge-below .mat-badge-content { + bottom: -8px +} + +.mat-badge-small.mat-badge-before .mat-badge-content { + left: -16px +} + +[dir=rtl] .mat-badge-small.mat-badge-before .mat-badge-content { + left: auto; + right: -16px +} + +.mat-badge-small.mat-badge-after .mat-badge-content { + right: -16px +} + +[dir=rtl] .mat-badge-small.mat-badge-after .mat-badge-content { + right: auto; + left: -16px +} + +.mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: -8px +} + +[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: auto; + right: -8px +} + +.mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: -8px +} + +[dir=rtl] .mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: auto; + left: -8px +} + +.mat-badge-medium .mat-badge-content { + width: 22px; + height: 22px; + line-height: 22px +} + +.mat-badge-medium.mat-badge-above .mat-badge-content { + top: -11px +} + +.mat-badge-medium.mat-badge-below .mat-badge-content { + bottom: -11px +} + +.mat-badge-medium.mat-badge-before .mat-badge-content { + left: -22px +} + +[dir=rtl] .mat-badge-medium.mat-badge-before .mat-badge-content { + left: auto; + right: -22px +} + +.mat-badge-medium.mat-badge-after .mat-badge-content { + right: -22px +} + +[dir=rtl] .mat-badge-medium.mat-badge-after .mat-badge-content { + right: auto; + left: -22px +} + +.mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: -11px +} + +[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: auto; + right: -11px +} + +.mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: -11px +} + +[dir=rtl] .mat-badge-medium.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: auto; + left: -11px +} + +.mat-badge-large .mat-badge-content { + width: 28px; + height: 28px; + line-height: 28px +} + +.mat-badge-large.mat-badge-above .mat-badge-content { + top: -14px +} + +.mat-badge-large.mat-badge-below .mat-badge-content { + bottom: -14px +} + +.mat-badge-large.mat-badge-before .mat-badge-content { + left: -28px +} + +[dir=rtl] .mat-badge-large.mat-badge-before .mat-badge-content { + left: auto; + right: -28px +} + +.mat-badge-large.mat-badge-after .mat-badge-content { + right: -28px +} + +[dir=rtl] .mat-badge-large.mat-badge-after .mat-badge-content { + right: auto; + left: -28px +} + +.mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: -14px +} + +[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-before .mat-badge-content { + left: auto; + right: -14px +} + +.mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: -14px +} + +[dir=rtl] .mat-badge-large.mat-badge-overlap.mat-badge-after .mat-badge-content { + right: auto; + left: -14px +} + +.mat-bottom-sheet-container { + box-shadow: 0 8px 10px -5px rgba(0, 0, 0, .2), 0 16px 24px 2px rgba(0, 0, 0, .14), 0 6px 30px 5px rgba(0, 0, 0, .12); + background: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-button, +.mat-icon-button, +.mat-stroked-button { + color: inherit; + background: 0 0 +} + +.mat-button.mat-primary, +.mat-icon-button.mat-primary, +.mat-stroked-button.mat-primary { + color: #78b7e5 +} + +.mat-button.mat-accent, +.mat-icon-button.mat-accent, +.mat-stroked-button.mat-accent { + color: #78b7e5 +} + +.mat-button.mat-warn, +.mat-icon-button.mat-warn, +.mat-stroked-button.mat-warn { + color: #f44336 +} + +.mat-button.mat-accent[disabled], +.mat-button.mat-primary[disabled], +.mat-button.mat-warn[disabled], +.mat-button[disabled][disabled], +.mat-icon-button.mat-accent[disabled], +.mat-icon-button.mat-primary[disabled], +.mat-icon-button.mat-warn[disabled], +.mat-icon-button[disabled][disabled], +.mat-stroked-button.mat-accent[disabled], +.mat-stroked-button.mat-primary[disabled], +.mat-stroked-button.mat-warn[disabled], +.mat-stroked-button[disabled][disabled] { + color: rgba(0, 0, 0, .26) +} + +.mat-button.mat-primary .mat-button-focus-overlay, +.mat-icon-button.mat-primary .mat-button-focus-overlay, +.mat-stroked-button.mat-primary .mat-button-focus-overlay { + background-color: #78b7e5 +} + +.mat-button.mat-accent .mat-button-focus-overlay, +.mat-icon-button.mat-accent .mat-button-focus-overlay, +.mat-stroked-button.mat-accent .mat-button-focus-overlay { + background-color: #78b7e5 +} + +.mat-button.mat-warn .mat-button-focus-overlay, +.mat-icon-button.mat-warn .mat-button-focus-overlay, +.mat-stroked-button.mat-warn .mat-button-focus-overlay { + background-color: #f44336 +} + +.mat-button[disabled] .mat-button-focus-overlay, +.mat-icon-button[disabled] .mat-button-focus-overlay, +.mat-stroked-button[disabled] .mat-button-focus-overlay { + background-color: transparent +} + +.mat-button .mat-ripple-element, +.mat-icon-button .mat-ripple-element, +.mat-stroked-button .mat-ripple-element { + opacity: .1; + background-color: currentColor +} + +.mat-button-focus-overlay { + background: #000 +} + +.mat-stroked-button:not([disabled]) { + border-color: rgba(0, 0, 0, .12) +} + +.mat-fab, +.mat-flat-button, +.mat-mini-fab, +.mat-raised-button { + color: rgba(0, 0, 0, .87); + background-color: #fff +} + +.mat-fab.mat-primary, +.mat-flat-button.mat-primary, +.mat-mini-fab.mat-primary, +.mat-raised-button.mat-primary { + color: #fff +} + +.mat-fab.mat-accent, +.mat-flat-button.mat-accent, +.mat-mini-fab.mat-accent, +.mat-raised-button.mat-accent { + color: #fff +} + +.mat-fab.mat-warn, +.mat-flat-button.mat-warn, +.mat-mini-fab.mat-warn, +.mat-raised-button.mat-warn { + color: #fff +} + +.mat-fab.mat-accent[disabled], +.mat-fab.mat-primary[disabled], +.mat-fab.mat-warn[disabled], +.mat-fab[disabled][disabled], +.mat-flat-button.mat-accent[disabled], +.mat-flat-button.mat-primary[disabled], +.mat-flat-button.mat-warn[disabled], +.mat-flat-button[disabled][disabled], +.mat-mini-fab.mat-accent[disabled], +.mat-mini-fab.mat-primary[disabled], +.mat-mini-fab.mat-warn[disabled], +.mat-mini-fab[disabled][disabled], +.mat-raised-button.mat-accent[disabled], +.mat-raised-button.mat-primary[disabled], +.mat-raised-button.mat-warn[disabled], +.mat-raised-button[disabled][disabled] { + color: rgba(0, 0, 0, .26) +} + +.mat-fab.mat-primary, +.mat-flat-button.mat-primary, +.mat-mini-fab.mat-primary, +.mat-raised-button.mat-primary { + background-color: #78b7e5 +} + +.mat-fab.mat-accent, +.mat-flat-button.mat-accent, +.mat-mini-fab.mat-accent, +.mat-raised-button.mat-accent { + background-color: #78b7e5 +} + +.mat-fab.mat-warn, +.mat-flat-button.mat-warn, +.mat-mini-fab.mat-warn, +.mat-raised-button.mat-warn { + background-color: #f44336 +} + +.mat-fab.mat-accent[disabled], +.mat-fab.mat-primary[disabled], +.mat-fab.mat-warn[disabled], +.mat-fab[disabled][disabled], +.mat-flat-button.mat-accent[disabled], +.mat-flat-button.mat-primary[disabled], +.mat-flat-button.mat-warn[disabled], +.mat-flat-button[disabled][disabled], +.mat-mini-fab.mat-accent[disabled], +.mat-mini-fab.mat-primary[disabled], +.mat-mini-fab.mat-warn[disabled], +.mat-mini-fab[disabled][disabled], +.mat-raised-button.mat-accent[disabled], +.mat-raised-button.mat-primary[disabled], +.mat-raised-button.mat-warn[disabled], +.mat-raised-button[disabled][disabled] { + background-color: rgba(0, 0, 0, .12) +} + +.mat-fab.mat-primary .mat-ripple-element, +.mat-flat-button.mat-primary .mat-ripple-element, +.mat-mini-fab.mat-primary .mat-ripple-element, +.mat-raised-button.mat-primary .mat-ripple-element { + background-color: rgba(255, 255, 255, .1) +} + +.mat-fab.mat-accent .mat-ripple-element, +.mat-flat-button.mat-accent .mat-ripple-element, +.mat-mini-fab.mat-accent .mat-ripple-element, +.mat-raised-button.mat-accent .mat-ripple-element { + background-color: rgba(255, 255, 255, .1) +} + +.mat-fab.mat-warn .mat-ripple-element, +.mat-flat-button.mat-warn .mat-ripple-element, +.mat-mini-fab.mat-warn .mat-ripple-element, +.mat-raised-button.mat-warn .mat-ripple-element { + background-color: rgba(255, 255, 255, .1) +} + +.mat-flat-button:not([class*=mat-elevation-z]), +.mat-stroked-button:not([class*=mat-elevation-z]) { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-raised-button:not([class*=mat-elevation-z]) { + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12) +} + +.mat-raised-button:not([disabled]):active:not([class*=mat-elevation-z]) { + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12) +} + +.mat-raised-button[disabled]:not([class*=mat-elevation-z]) { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-fab:not([class*=mat-elevation-z]), +.mat-mini-fab:not([class*=mat-elevation-z]) { + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 6px 10px 0 rgba(0, 0, 0, .14), 0 1px 18px 0 rgba(0, 0, 0, .12) +} + +.mat-fab:not([disabled]):active:not([class*=mat-elevation-z]), +.mat-mini-fab:not([disabled]):active:not([class*=mat-elevation-z]) { + box-shadow: 0 7px 8px -4px rgba(0, 0, 0, .2), 0 12px 17px 2px rgba(0, 0, 0, .14), 0 5px 22px 4px rgba(0, 0, 0, .12) +} + +.mat-fab[disabled]:not([class*=mat-elevation-z]), +.mat-mini-fab[disabled]:not([class*=mat-elevation-z]) { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-button-toggle-group, +.mat-button-toggle-standalone { + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12) +} + +.mat-button-toggle-group-appearance-standard, +.mat-button-toggle-standalone.mat-button-toggle-appearance-standard { + box-shadow: none +} + +.mat-button-toggle { + color: rgba(0, 0, 0, .38) +} + +.mat-button-toggle .mat-button-toggle-focus-overlay { + background-color: rgba(0, 0, 0, .12) +} + +.mat-button-toggle-appearance-standard { + color: rgba(0, 0, 0, .87); + background: #fff +} + +.mat-button-toggle-appearance-standard .mat-button-toggle-focus-overlay { + background-color: #000 +} + +.mat-button-toggle-group-appearance-standard .mat-button-toggle+.mat-button-toggle { + border-left: solid 1px rgba(0, 0, 0, .12) +} + +[dir=rtl] .mat-button-toggle-group-appearance-standard .mat-button-toggle+.mat-button-toggle { + border-left: none; + border-right: solid 1px rgba(0, 0, 0, .12) +} + +.mat-button-toggle-group-appearance-standard.mat-button-toggle-vertical .mat-button-toggle+.mat-button-toggle { + border-left: none; + border-right: none; + border-top: solid 1px rgba(0, 0, 0, .12) +} + +.mat-button-toggle-checked { + background-color: #e0e0e0; + color: rgba(0, 0, 0, .54) +} + +.mat-button-toggle-checked.mat-button-toggle-appearance-standard { + color: rgba(0, 0, 0, .87) +} + +.mat-button-toggle-disabled { + color: rgba(0, 0, 0, .26); + background-color: #eee +} + +.mat-button-toggle-disabled.mat-button-toggle-appearance-standard { + background: #fff +} + +.mat-button-toggle-disabled.mat-button-toggle-checked { + background-color: #bdbdbd +} + +.mat-button-toggle-group-appearance-standard, +.mat-button-toggle-standalone.mat-button-toggle-appearance-standard { + border: solid 1px rgba(0, 0, 0, .12) +} + +.mat-card { + background: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-card:not([class*=mat-elevation-z]) { + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12) +} + +.mat-card.mat-card-flat:not([class*=mat-elevation-z]) { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-card-subtitle { + color: rgba(0, 0, 0, .54) +} + +.mat-checkbox-frame { + border-color: rgba(0, 0, 0, .54) +} + +.mat-checkbox-checkmark { + fill: #fafafa +} + +.mat-checkbox-checkmark-path { + stroke: #fafafa !important +} + +@media (-ms-high-contrast:black-on-white) { + .mat-checkbox-checkmark-path { + stroke: #000 !important + } +} + +.mat-checkbox-mixedmark { + background-color: #fafafa +} + +.mat-checkbox-checked.mat-primary .mat-checkbox-background, +.mat-checkbox-indeterminate.mat-primary .mat-checkbox-background { + background-color: #78b7e5 +} + +.mat-checkbox-checked.mat-accent .mat-checkbox-background, +.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { + background-color: #78b7e5 +} + +.mat-checkbox-checked.mat-warn .mat-checkbox-background, +.mat-checkbox-indeterminate.mat-warn .mat-checkbox-background { + background-color: #f44336 +} + +.mat-checkbox-disabled.mat-checkbox-checked .mat-checkbox-background, +.mat-checkbox-disabled.mat-checkbox-indeterminate .mat-checkbox-background { + background-color: #b0b0b0 +} + +.mat-checkbox-disabled:not(.mat-checkbox-checked) .mat-checkbox-frame { + border-color: #b0b0b0 +} + +.mat-checkbox-disabled .mat-checkbox-label { + color: rgba(0, 0, 0, .54) +} + +@media (-ms-high-contrast:active) { + .mat-checkbox-disabled { + opacity: .5 + } +} + +@media (-ms-high-contrast:active) { + .mat-checkbox-background { + background: 0 0 + } +} + +.mat-checkbox .mat-ripple-element { + background-color: #000 +} + +.mat-checkbox-checked:not(.mat-checkbox-disabled).mat-primary .mat-ripple-element, +.mat-checkbox:active:not(.mat-checkbox-disabled).mat-primary .mat-ripple-element { + background: #78b7e5 +} + +.mat-checkbox-checked:not(.mat-checkbox-disabled).mat-accent .mat-ripple-element, +.mat-checkbox:active:not(.mat-checkbox-disabled).mat-accent .mat-ripple-element { + background: #78b7e5 +} + +.mat-checkbox-checked:not(.mat-checkbox-disabled).mat-warn .mat-ripple-element, +.mat-checkbox:active:not(.mat-checkbox-disabled).mat-warn .mat-ripple-element { + background: #f44336 +} + +.mat-chip.mat-standard-chip { + background-color: #e0e0e0; + color: rgba(0, 0, 0, .87) +} + +.mat-chip.mat-standard-chip .mat-chip-remove { + color: rgba(0, 0, 0, .87); + opacity: .4 +} + +.mat-chip.mat-standard-chip:not(.mat-chip-disabled):active { + box-shadow: 0 3px 3px -2px rgba(0, 0, 0, .2), 0 3px 4px 0 rgba(0, 0, 0, .14), 0 1px 8px 0 rgba(0, 0, 0, .12) +} + +.mat-chip.mat-standard-chip:not(.mat-chip-disabled) .mat-chip-remove:hover { + opacity: .54 +} + +.mat-chip.mat-standard-chip.mat-chip-disabled { + opacity: .4 +} + +.mat-chip.mat-standard-chip::after { + background: #000 +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary { + background-color: #78b7e5; + color: #fff +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary .mat-chip-remove { + color: #fff; + opacity: .4 +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-primary .mat-ripple-element { + background: rgba(255, 255, 255, .1) +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn { + background-color: #f44336; + color: #fff +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn .mat-chip-remove { + color: #fff; + opacity: .4 +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-warn .mat-ripple-element { + background: rgba(255, 255, 255, .1) +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent { + background-color: #78b7e5; + color: #fff +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent .mat-chip-remove { + color: #fff; + opacity: .4 +} + +.mat-chip.mat-standard-chip.mat-chip-selected.mat-accent .mat-ripple-element { + background: rgba(255, 255, 255, .1) +} + +.mat-table { + background: #fff +} + +.mat-table tbody, +.mat-table tfoot, +.mat-table thead, +.mat-table-sticky, +[mat-footer-row], +[mat-header-row], +[mat-row], +mat-footer-row, +mat-header-row, +mat-row { + background: inherit +} + +mat-footer-row, +mat-header-row, +mat-row, +td.mat-cell, +td.mat-footer-cell, +th.mat-header-cell { + border-bottom-color: rgba(0, 0, 0, .12) +} + +.mat-header-cell { + color: rgba(0, 0, 0, .54) +} + +.mat-cell, +.mat-footer-cell { + color: rgba(0, 0, 0, .87) +} + +.mat-calendar-arrow { + border-top-color: rgba(0, 0, 0, .54) +} + +.mat-datepicker-content .mat-calendar-next-button, +.mat-datepicker-content .mat-calendar-previous-button, +.mat-datepicker-toggle { + color: rgba(0, 0, 0, .54) +} + +.mat-calendar-table-header { + color: rgba(0, 0, 0, .38) +} + +.mat-calendar-table-header-divider::after { + background: rgba(0, 0, 0, .12) +} + +.mat-calendar-body-label { + color: rgba(0, 0, 0, .54) +} + +.mat-calendar-body-cell-content { + color: rgba(0, 0, 0, .87); + border-color: transparent +} + +.mat-calendar-body-disabled>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected) { + color: rgba(0, 0, 0, .38) +} + +.cdk-keyboard-focused .mat-calendar-body-active>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected), +.cdk-program-focused .mat-calendar-body-active>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected), +.mat-calendar-body-cell:not(.mat-calendar-body-disabled):hover>.mat-calendar-body-cell-content:not(.mat-calendar-body-selected) { + background-color: rgba(0, 0, 0, .04) +} + +.mat-calendar-body-today:not(.mat-calendar-body-selected) { + border-color: rgba(0, 0, 0, .38) +} + +.mat-calendar-body-disabled>.mat-calendar-body-today:not(.mat-calendar-body-selected) { + border-color: rgba(0, 0, 0, .18) +} + +.mat-calendar-body-selected { + background-color: #78b7e5; + color: #fff +} + +.mat-calendar-body-disabled>.mat-calendar-body-selected { + background-color: rgba(120, 183, 229, .4) +} + +.mat-calendar-body-today.mat-calendar-body-selected { + box-shadow: inset 0 0 0 1px #fff +} + +.mat-datepicker-content { + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12); + background-color: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-datepicker-content.mat-accent .mat-calendar-body-selected { + background-color: #78b7e5; + color: #fff +} + +.mat-datepicker-content.mat-accent .mat-calendar-body-disabled>.mat-calendar-body-selected { + background-color: rgba(255, 64, 129, .4) +} + +.mat-datepicker-content.mat-accent .mat-calendar-body-today.mat-calendar-body-selected { + box-shadow: inset 0 0 0 1px #fff +} + +.mat-datepicker-content.mat-warn .mat-calendar-body-selected { + background-color: #f44336; + color: #fff +} + +.mat-datepicker-content.mat-warn .mat-calendar-body-disabled>.mat-calendar-body-selected { + background-color: rgba(244, 67, 54, .4) +} + +.mat-datepicker-content.mat-warn .mat-calendar-body-today.mat-calendar-body-selected { + box-shadow: inset 0 0 0 1px #fff +} + +.mat-datepicker-content-touch { + box-shadow: 0 0 0 0 rgba(0, 0, 0, .2), 0 0 0 0 rgba(0, 0, 0, .14), 0 0 0 0 rgba(0, 0, 0, .12) +} + +.mat-datepicker-toggle-active { + color: #78b7e5 +} + +.mat-datepicker-toggle-active.mat-accent { + color: #78b7e5 +} + +.mat-datepicker-toggle-active.mat-warn { + color: #f44336 +} + +.mat-dialog-container { + box-shadow: 0 11px 15px -7px rgba(0, 0, 0, .2), 0 24px 38px 3px rgba(0, 0, 0, .14), 0 9px 46px 8px rgba(0, 0, 0, .12); + background: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-divider { + border-top-color: rgba(0, 0, 0, .12) +} + +.mat-divider-vertical { + border-right-color: rgba(0, 0, 0, .12) +} + +.mat-expansion-panel { + background: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-expansion-panel:not([class*=mat-elevation-z]) { + box-shadow: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12) +} + +.mat-action-row { + border-top-color: rgba(0, 0, 0, .12) +} + +.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]).cdk-keyboard-focused, +.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]).cdk-program-focused, +.mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:not([aria-disabled=true]):hover { + background: rgba(0, 0, 0, .04) +} + +@media (hover:none) { + .mat-expansion-panel:not(.mat-expanded):not([aria-disabled=true]) .mat-expansion-panel-header:hover { + background: #fff + } +} + +.mat-expansion-panel-header-title { + color: rgba(0, 0, 0, .87) +} + +.mat-expansion-indicator::after, +.mat-expansion-panel-header-description { + color: rgba(0, 0, 0, .54) +} + +.mat-expansion-panel-header[aria-disabled=true] { + color: rgba(0, 0, 0, .26) +} + +.mat-expansion-panel-header[aria-disabled=true] .mat-expansion-panel-header-description, +.mat-expansion-panel-header[aria-disabled=true] .mat-expansion-panel-header-title { + color: inherit +} + +.mat-form-field-label { + color: rgba(0, 0, 0, .6) +} + +.mat-hint { + color: rgba(0, 0, 0, .6) +} + +.mat-form-field.mat-focused .mat-form-field-label { + color: #78b7e5 +} + +.mat-form-field.mat-focused .mat-form-field-label.mat-accent { + color: #78b7e5 +} + +.mat-form-field.mat-focused .mat-form-field-label.mat-warn { + color: #f44336 +} + +.mat-focused .mat-form-field-required-marker { + color: #78b7e5 +} + +.mat-form-field-ripple { + background-color: rgba(0, 0, 0, .87) +} + +.mat-form-field.mat-focused .mat-form-field-ripple { + background-color: #78b7e5 +} + +.mat-form-field.mat-focused .mat-form-field-ripple.mat-accent { + background-color: #78b7e5 +} + +.mat-form-field.mat-focused .mat-form-field-ripple.mat-warn { + background-color: #f44336 +} + +.mat-form-field-type-mat-native-select.mat-focused:not(.mat-form-field-invalid) .mat-form-field-infix::after { + color: #78b7e5 +} + +.mat-form-field-type-mat-native-select.mat-focused:not(.mat-form-field-invalid).mat-accent .mat-form-field-infix::after { + color: #78b7e5 +} + +.mat-form-field-type-mat-native-select.mat-focused:not(.mat-form-field-invalid).mat-warn .mat-form-field-infix::after { + color: #f44336 +} + +.mat-form-field.mat-form-field-invalid .mat-form-field-label { + color: #f44336 +} + +.mat-form-field.mat-form-field-invalid .mat-form-field-label .mat-form-field-required-marker, +.mat-form-field.mat-form-field-invalid .mat-form-field-label.mat-accent { + color: #f44336 +} + +.mat-form-field.mat-form-field-invalid .mat-form-field-ripple, +.mat-form-field.mat-form-field-invalid .mat-form-field-ripple.mat-accent { + background-color: #f44336 +} + +.mat-error { + color: #f44336 +} + +.mat-form-field-appearance-legacy .mat-form-field-label { + color: rgba(0, 0, 0, .54) +} + +.mat-form-field-appearance-legacy .mat-hint { + color: rgba(0, 0, 0, .54) +} + +.mat-form-field-appearance-legacy .mat-form-field-underline { + background-color: rgba(0, 0, 0, .42) +} + +.mat-form-field-appearance-legacy.mat-form-field-disabled .mat-form-field-underline { + background-image: linear-gradient(to right, rgba(0, 0, 0, .42) 0, rgba(0, 0, 0, .42) 33%, transparent 0); + background-size: 4px 100%; + background-repeat: repeat-x +} + +.mat-form-field-appearance-standard .mat-form-field-underline { + background-color: rgba(0, 0, 0, .42) +} + +.mat-form-field-appearance-standard.mat-form-field-disabled .mat-form-field-underline { + background-image: linear-gradient(to right, rgba(0, 0, 0, .42) 0, rgba(0, 0, 0, .42) 33%, transparent 0); + background-size: 4px 100%; + background-repeat: repeat-x +} + +.mat-form-field-appearance-fill .mat-form-field-flex { + background-color: rgba(0, 0, 0, .04) +} + +.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-flex { + background-color: rgba(0, 0, 0, .02) +} + +.mat-form-field-appearance-fill .mat-form-field-underline::before { + background-color: rgba(0, 0, 0, .42) +} + +.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-label { + color: rgba(0, 0, 0, .38) +} + +.mat-form-field-appearance-fill.mat-form-field-disabled .mat-form-field-underline::before { + background-color: transparent +} + +.mat-form-field-appearance-outline .mat-form-field-outline { + color: rgba(0, 0, 0, .12) +} + +.mat-form-field-appearance-outline .mat-form-field-outline-thick { + color: rgba(0, 0, 0, .87) +} + +.mat-form-field-appearance-outline.mat-focused .mat-form-field-outline-thick { + color: #78b7e5 +} + +.mat-form-field-appearance-outline.mat-focused.mat-accent .mat-form-field-outline-thick { + color: #78b7e5 +} + +.mat-form-field-appearance-outline.mat-focused.mat-warn .mat-form-field-outline-thick { + color: #f44336 +} + +.mat-form-field-appearance-outline.mat-form-field-invalid.mat-form-field-invalid .mat-form-field-outline-thick { + color: #f44336 +} + +.mat-form-field-appearance-outline.mat-form-field-disabled .mat-form-field-label { + color: rgba(0, 0, 0, .38) +} + +.mat-form-field-appearance-outline.mat-form-field-disabled .mat-form-field-outline { + color: rgba(0, 0, 0, .06) +} + +.mat-icon.mat-primary { + color: #78b7e5 +} + +.mat-icon.mat-accent { + color: #78b7e5 +} + +.mat-icon.mat-warn { + color: #f44336 +} + +.mat-form-field-type-mat-native-select .mat-form-field-infix::after { + color: rgba(0, 0, 0, .54) +} + +.mat-form-field-type-mat-native-select.mat-form-field-disabled .mat-form-field-infix::after, +.mat-input-element:disabled { + color: rgba(0, 0, 0, .38) +} + +.mat-input-element { + caret-color: #78b7e5 +} + +.mat-input-element::placeholder { + color: rgba(0, 0, 0, .42) +} + +.mat-input-element::-moz-placeholder { + color: rgba(0, 0, 0, .42) +} + +.mat-input-element::-webkit-input-placeholder { + color: rgba(0, 0, 0, .42) +} + +.mat-input-element:-ms-input-placeholder { + color: rgba(0, 0, 0, .42) +} + +.mat-accent .mat-input-element { + caret-color: #78b7e5 +} + +.mat-form-field-invalid .mat-input-element, +.mat-warn .mat-input-element { + caret-color: #f44336 +} + +.mat-form-field-type-mat-native-select.mat-form-field-invalid .mat-form-field-infix::after { + color: #f44336 +} + +.mat-list-base .mat-list-item { + color: rgba(0, 0, 0, .87) +} + +.mat-list-base .mat-list-option { + color: rgba(0, 0, 0, .87) +} + +.mat-list-base .mat-subheader { + color: rgba(0, 0, 0, .54) +} + +.mat-list-item-disabled { + background-color: #eee +} + +.mat-action-list .mat-list-item:focus, +.mat-action-list .mat-list-item:hover, +.mat-list-option:focus, +.mat-list-option:hover, +.mat-nav-list .mat-list-item:focus, +.mat-nav-list .mat-list-item:hover { + background: rgba(0, 0, 0, .04) +} + +.mat-menu-panel { + background: #fff +} + +.mat-menu-panel:not([class*=mat-elevation-z]) { + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12) +} + +.mat-menu-item { + background: 0 0; + color: rgba(0, 0, 0, .87) +} + +.mat-menu-item[disabled], +.mat-menu-item[disabled]::after { + color: rgba(0, 0, 0, .38) +} + +.mat-menu-item .mat-icon-no-color, +.mat-menu-item-submenu-trigger::after { + color: rgba(0, 0, 0, .54) +} + +.mat-menu-item-highlighted:not([disabled]), +.mat-menu-item.cdk-keyboard-focused:not([disabled]), +.mat-menu-item.cdk-program-focused:not([disabled]), +.mat-menu-item:hover:not([disabled]) { + background: rgba(0, 0, 0, .04) +} + +.mat-paginator { + background: #fff +} + +.mat-paginator, +.mat-paginator-page-size .mat-select-trigger { + color: rgba(0, 0, 0, .54) +} + +.mat-paginator-decrement, +.mat-paginator-increment { + border-top: 2px solid rgba(0, 0, 0, .54); + border-right: 2px solid rgba(0, 0, 0, .54) +} + +.mat-paginator-first, +.mat-paginator-last { + border-top: 2px solid rgba(0, 0, 0, .54) +} + +.mat-icon-button[disabled] .mat-paginator-decrement, +.mat-icon-button[disabled] .mat-paginator-first, +.mat-icon-button[disabled] .mat-paginator-increment, +.mat-icon-button[disabled] .mat-paginator-last { + border-color: rgba(0, 0, 0, .38) +} + +.mat-progress-bar-background { + fill: #c5cae9 +} + +.mat-progress-bar-buffer { + background-color: #c5cae9 +} + +.mat-progress-bar-fill::after { + background-color: #78b7e5 +} + +.mat-progress-bar.mat-accent .mat-progress-bar-background { + fill: #ff80ab +} + +.mat-progress-bar.mat-accent .mat-progress-bar-buffer { + background-color: #ff80ab +} + +.mat-progress-bar.mat-accent .mat-progress-bar-fill::after { + background-color: #78b7e5 +} + +.mat-progress-bar.mat-warn .mat-progress-bar-background { + fill: #ffcdd2 +} + +.mat-progress-bar.mat-warn .mat-progress-bar-buffer { + background-color: #ffcdd2 +} + +.mat-progress-bar.mat-warn .mat-progress-bar-fill::after { + background-color: #f44336 +} + +.mat-progress-spinner circle, +.mat-spinner circle { + stroke: #78b7e5 +} + +.mat-progress-spinner.mat-accent circle, +.mat-spinner.mat-accent circle { + stroke: #78b7e5 +} + +.mat-progress-spinner.mat-warn circle, +.mat-spinner.mat-warn circle { + stroke: #f44336 +} + +.mat-radio-outer-circle { + border-color: rgba(0, 0, 0, .54) +} + +.mat-radio-button.mat-primary.mat-radio-checked .mat-radio-outer-circle { + border-color: #78b7e5 +} + +.mat-radio-button.mat-primary .mat-radio-inner-circle, +.mat-radio-button.mat-primary .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), +.mat-radio-button.mat-primary.mat-radio-checked .mat-radio-persistent-ripple, +.mat-radio-button.mat-primary:active .mat-radio-persistent-ripple { + background-color: #78b7e5 +} + +.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle { + border-color: #78b7e5 +} + +.mat-radio-button.mat-accent .mat-radio-inner-circle, +.mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), +.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-persistent-ripple, +.mat-radio-button.mat-accent:active .mat-radio-persistent-ripple { + background-color: #78b7e5 +} + +.mat-radio-button.mat-warn.mat-radio-checked .mat-radio-outer-circle { + border-color: #f44336 +} + +.mat-radio-button.mat-warn .mat-radio-inner-circle, +.mat-radio-button.mat-warn .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), +.mat-radio-button.mat-warn.mat-radio-checked .mat-radio-persistent-ripple, +.mat-radio-button.mat-warn:active .mat-radio-persistent-ripple { + background-color: #f44336 +} + +.mat-radio-button.mat-radio-disabled .mat-radio-outer-circle, +.mat-radio-button.mat-radio-disabled.mat-radio-checked .mat-radio-outer-circle { + border-color: rgba(0, 0, 0, .38) +} + +.mat-radio-button.mat-radio-disabled .mat-radio-inner-circle, +.mat-radio-button.mat-radio-disabled .mat-radio-ripple .mat-ripple-element { + background-color: rgba(0, 0, 0, .38) +} + +.mat-radio-button.mat-radio-disabled .mat-radio-label-content { + color: rgba(0, 0, 0, .38) +} + +.mat-radio-button .mat-ripple-element { + background-color: #000 +} + +.mat-select-value { + color: rgba(0, 0, 0, .87) +} + +.mat-select-placeholder { + color: rgba(0, 0, 0, .42) +} + +.mat-select-disabled .mat-select-value { + color: rgba(0, 0, 0, .38) +} + +.mat-select-arrow { + color: rgba(0, 0, 0, .54) +} + +.mat-select-panel { + background: #fff +} + +.mat-select-panel:not([class*=mat-elevation-z]) { + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12) +} + +.mat-select-panel .mat-option.mat-selected:not(.mat-option-multiple) { + background: rgba(0, 0, 0, .12) +} + +.mat-form-field.mat-focused.mat-primary .mat-select-arrow { + color: #78b7e5 +} + +.mat-form-field.mat-focused.mat-accent .mat-select-arrow { + color: #78b7e5 +} + +.mat-form-field.mat-focused.mat-warn .mat-select-arrow { + color: #f44336 +} + +.mat-form-field .mat-select.mat-select-invalid .mat-select-arrow { + color: #f44336 +} + +.mat-form-field .mat-select.mat-select-disabled .mat-select-arrow { + color: rgba(0, 0, 0, .38) +} + +.mat-drawer-container { + background-color: #fafafa; + color: rgba(0, 0, 0, .87) +} + +.mat-drawer { + background-color: #fff; + color: rgba(0, 0, 0, .87) +} + +.mat-drawer.mat-drawer-push { + background-color: #fff +} + +.mat-drawer:not(.mat-drawer-side) { + box-shadow: 0 8px 10px -5px rgba(0, 0, 0, .2), 0 16px 24px 2px rgba(0, 0, 0, .14), 0 6px 30px 5px rgba(0, 0, 0, .12) +} + +.mat-drawer-side { + border-right: solid 1px rgba(0, 0, 0, .12) +} + +.mat-drawer-side.mat-drawer-end { + border-left: solid 1px rgba(0, 0, 0, .12); + border-right: none +} + +[dir=rtl] .mat-drawer-side { + border-left: solid 1px rgba(0, 0, 0, .12); + border-right: none +} + +[dir=rtl] .mat-drawer-side.mat-drawer-end { + border-left: none; + border-right: solid 1px rgba(0, 0, 0, .12) +} + +.mat-drawer-backdrop.mat-drawer-shown { + background-color: rgba(0, 0, 0, .6) +} + +.mat-slide-toggle.mat-checked .mat-slide-toggle-thumb { + background-color: #78b7e5 +} + +.mat-slide-toggle.mat-checked .mat-slide-toggle-bar { + background-color: rgba(255, 64, 129, .54) +} + +.mat-slide-toggle.mat-checked .mat-ripple-element { + background-color: #78b7e5 +} + +.mat-slide-toggle.mat-primary.mat-checked .mat-slide-toggle-thumb { + background-color: #78b7e5 +} + +.mat-slide-toggle.mat-primary.mat-checked .mat-slide-toggle-bar { + background-color: rgba(120, 183, 229, .54) +} + +.mat-slide-toggle.mat-primary.mat-checked .mat-ripple-element { + background-color: #78b7e5 +} + +.mat-slide-toggle.mat-warn.mat-checked .mat-slide-toggle-thumb { + background-color: #f44336 +} + +.mat-slide-toggle.mat-warn.mat-checked .mat-slide-toggle-bar { + background-color: rgba(244, 67, 54, .54) +} + +.mat-slide-toggle.mat-warn.mat-checked .mat-ripple-element { + background-color: #f44336 +} + +.mat-slide-toggle:not(.mat-checked) .mat-ripple-element { + background-color: #000 +} + +.mat-slide-toggle-thumb { + box-shadow: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12); + background-color: #fafafa +} + +.mat-slide-toggle-bar { + background-color: rgba(0, 0, 0, .38) +} + +.mat-slider-track-background { + background-color: rgba(0, 0, 0, .26) +} + +.mat-primary .mat-slider-thumb, +.mat-primary .mat-slider-thumb-label, +.mat-primary .mat-slider-track-fill { + background-color: #78b7e5 +} + +.mat-primary .mat-slider-thumb-label-text { + color: #fff +} + +.mat-accent .mat-slider-thumb, +.mat-accent .mat-slider-thumb-label, +.mat-accent .mat-slider-track-fill { + background-color: #78b7e5 +} + +.mat-accent .mat-slider-thumb-label-text { + color: #fff +} + +.mat-warn .mat-slider-thumb, +.mat-warn .mat-slider-thumb-label, +.mat-warn .mat-slider-track-fill { + background-color: #f44336 +} + +.mat-warn .mat-slider-thumb-label-text { + color: #fff +} + +.mat-slider-focus-ring { + background-color: rgba(255, 64, 129, .2) +} + +.cdk-focused .mat-slider-track-background, +.mat-slider:hover .mat-slider-track-background { + background-color: rgba(0, 0, 0, .38) +} + +.mat-slider-disabled .mat-slider-thumb, +.mat-slider-disabled .mat-slider-track-background, +.mat-slider-disabled .mat-slider-track-fill { + background-color: rgba(0, 0, 0, .26) +} + +.mat-slider-disabled:hover .mat-slider-track-background { + background-color: rgba(0, 0, 0, .26) +} + +.mat-slider-min-value .mat-slider-focus-ring { + background-color: rgba(0, 0, 0, .12) +} + +.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb, +.mat-slider-min-value.mat-slider-thumb-label-showing .mat-slider-thumb-label { + background-color: rgba(0, 0, 0, .87) +} + +.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb, +.mat-slider-min-value.mat-slider-thumb-label-showing.cdk-focused .mat-slider-thumb-label { + background-color: rgba(0, 0, 0, .26) +} + +.mat-slider-min-value:not(.mat-slider-thumb-label-showing) .mat-slider-thumb { + border-color: rgba(0, 0, 0, .26); + background-color: transparent +} + +.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused .mat-slider-thumb, +.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover .mat-slider-thumb { + border-color: rgba(0, 0, 0, .38) +} + +.mat-slider-min-value:not(.mat-slider-thumb-label-showing).cdk-focused.mat-slider-disabled .mat-slider-thumb, +.mat-slider-min-value:not(.mat-slider-thumb-label-showing):hover.mat-slider-disabled .mat-slider-thumb { + border-color: rgba(0, 0, 0, .26) +} + +.mat-slider-has-ticks .mat-slider-wrapper::after { + border-color: rgba(0, 0, 0, .7) +} + +.mat-slider-horizontal .mat-slider-ticks { + background-image: repeating-linear-gradient(to right, rgba(0, 0, 0, .7), rgba(0, 0, 0, .7) 2px, transparent 0, transparent); + background-image: -moz-repeating-linear-gradient(.0001deg, rgba(0, 0, 0, .7), rgba(0, 0, 0, .7) 2px, transparent 0, transparent) +} + +.mat-slider-vertical .mat-slider-ticks { + background-image: repeating-linear-gradient(to bottom, rgba(0, 0, 0, .7), rgba(0, 0, 0, .7) 2px, transparent 0, transparent) +} + +.mat-step-header.cdk-keyboard-focused, +.mat-step-header.cdk-program-focused, +.mat-step-header:hover { + background-color: rgba(0, 0, 0, .04) +} + +@media (hover:none) { + .mat-step-header:hover { + background: 0 0 + } +} + +.mat-step-header .mat-step-label, +.mat-step-header .mat-step-optional { + color: rgba(0, 0, 0, .54) +} + +.mat-step-header .mat-step-icon { + background-color: rgba(0, 0, 0, .54); + color: #fff +} + +.mat-step-header .mat-step-icon-selected, +.mat-step-header .mat-step-icon-state-done, +.mat-step-header .mat-step-icon-state-edit { + background-color: #78b7e5; + color: #fff +} + +.mat-step-header .mat-step-icon-state-error { + background-color: transparent; + color: #f44336 +} + +.mat-step-header .mat-step-label.mat-step-label-active { + color: rgba(0, 0, 0, .87) +} + +.mat-step-header .mat-step-label.mat-step-label-error { + color: #f44336 +} + +.mat-stepper-horizontal, +.mat-stepper-vertical { + background-color: #fff +} + +.mat-stepper-vertical-line::before { + border-left-color: rgba(0, 0, 0, .12) +} + +.mat-horizontal-stepper-header::after, +.mat-horizontal-stepper-header::before, +.mat-stepper-horizontal-line { + border-top-color: rgba(0, 0, 0, .12) +} + +.mat-sort-header-arrow { + color: #757575 +} + +.mat-tab-header, +.mat-tab-nav-bar { + border-bottom: 1px solid rgba(0, 0, 0, .12) +} + +.mat-tab-group-inverted-header .mat-tab-header, +.mat-tab-group-inverted-header .mat-tab-nav-bar { + border-top: 1px solid rgba(0, 0, 0, .12); + border-bottom: none +} + +.mat-tab-label, +.mat-tab-link { + color: rgba(0, 0, 0, .87) +} + +.mat-tab-label.mat-tab-disabled, +.mat-tab-link.mat-tab-disabled { + color: rgba(0, 0, 0, .38) +} + +.mat-tab-header-pagination-chevron { + border-color: rgba(0, 0, 0, .87) +} + +.mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: rgba(0, 0, 0, .38) +} + +.mat-tab-group[class*=mat-background-] .mat-tab-header, +.mat-tab-nav-bar[class*=mat-background-] { + border-bottom: none; + border-top: none +} + +.mat-tab-group.mat-primary .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-primary .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-primary .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-primary .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-primary .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-primary .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-primary .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-primary .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(197, 202, 233, .3) +} + +.mat-tab-group.mat-primary .mat-ink-bar, +.mat-tab-nav-bar.mat-primary .mat-ink-bar { + background-color: #78b7e5 +} + +.mat-tab-group.mat-primary.mat-background-primary .mat-ink-bar, +.mat-tab-nav-bar.mat-primary.mat-background-primary .mat-ink-bar { + background-color: #fff +} + +.mat-tab-group.mat-accent .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-accent .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-accent .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-accent .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-accent .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-accent .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-accent .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-accent .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(255, 128, 171, .3) +} + +.mat-tab-group.mat-accent .mat-ink-bar, +.mat-tab-nav-bar.mat-accent .mat-ink-bar { + background-color: #78b7e5 +} + +.mat-tab-group.mat-accent.mat-background-accent .mat-ink-bar, +.mat-tab-nav-bar.mat-accent.mat-background-accent .mat-ink-bar { + background-color: #fff +} + +.mat-tab-group.mat-warn .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-warn .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-warn .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-warn .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-warn .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-warn .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-warn .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-warn .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(255, 205, 210, .3) +} + +.mat-tab-group.mat-warn .mat-ink-bar, +.mat-tab-nav-bar.mat-warn .mat-ink-bar { + background-color: #f44336 +} + +.mat-tab-group.mat-warn.mat-background-warn .mat-ink-bar, +.mat-tab-nav-bar.mat-warn.mat-background-warn .mat-ink-bar { + background-color: #fff +} + +.mat-tab-group.mat-background-primary .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-primary .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-primary .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-primary .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-primary .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-primary .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-primary .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-primary .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(197, 202, 233, .3) +} + +.mat-tab-group.mat-background-primary .mat-tab-header, +.mat-tab-group.mat-background-primary .mat-tab-links, +.mat-tab-nav-bar.mat-background-primary .mat-tab-header, +.mat-tab-nav-bar.mat-background-primary .mat-tab-links { + background-color: #78b7e5 +} + +.mat-tab-group.mat-background-primary .mat-tab-label, +.mat-tab-group.mat-background-primary .mat-tab-link, +.mat-tab-nav-bar.mat-background-primary .mat-tab-label, +.mat-tab-nav-bar.mat-background-primary .mat-tab-link { + color: #fff +} + +.mat-tab-group.mat-background-primary .mat-tab-label.mat-tab-disabled, +.mat-tab-group.mat-background-primary .mat-tab-link.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-primary .mat-tab-label.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-primary .mat-tab-link.mat-tab-disabled { + color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-primary .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-primary .mat-tab-header-pagination-chevron { + border-color: #fff +} + +.mat-tab-group.mat-background-primary .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-primary .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-primary .mat-ripple-element, +.mat-tab-nav-bar.mat-background-primary .mat-ripple-element { + background-color: rgba(255, 255, 255, .12) +} + +.mat-tab-group.mat-background-accent .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-accent .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-accent .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-accent .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-accent .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-accent .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-accent .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-accent .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(255, 128, 171, .3) +} + +.mat-tab-group.mat-background-accent .mat-tab-header, +.mat-tab-group.mat-background-accent .mat-tab-links, +.mat-tab-nav-bar.mat-background-accent .mat-tab-header, +.mat-tab-nav-bar.mat-background-accent .mat-tab-links { + background-color: #78b7e5 +} + +.mat-tab-group.mat-background-accent .mat-tab-label, +.mat-tab-group.mat-background-accent .mat-tab-link, +.mat-tab-nav-bar.mat-background-accent .mat-tab-label, +.mat-tab-nav-bar.mat-background-accent .mat-tab-link { + color: #fff +} + +.mat-tab-group.mat-background-accent .mat-tab-label.mat-tab-disabled, +.mat-tab-group.mat-background-accent .mat-tab-link.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-accent .mat-tab-label.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-accent .mat-tab-link.mat-tab-disabled { + color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-accent .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-accent .mat-tab-header-pagination-chevron { + border-color: #fff +} + +.mat-tab-group.mat-background-accent .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-accent .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-accent .mat-ripple-element, +.mat-tab-nav-bar.mat-background-accent .mat-ripple-element { + background-color: rgba(255, 255, 255, .12) +} + +.mat-tab-group.mat-background-warn .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-warn .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-warn .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-group.mat-background-warn .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-warn .mat-tab-label.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-warn .mat-tab-label.cdk-program-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-warn .mat-tab-link.cdk-keyboard-focused:not(.mat-tab-disabled), +.mat-tab-nav-bar.mat-background-warn .mat-tab-link.cdk-program-focused:not(.mat-tab-disabled) { + background-color: rgba(255, 205, 210, .3) +} + +.mat-tab-group.mat-background-warn .mat-tab-header, +.mat-tab-group.mat-background-warn .mat-tab-links, +.mat-tab-nav-bar.mat-background-warn .mat-tab-header, +.mat-tab-nav-bar.mat-background-warn .mat-tab-links { + background-color: #f44336 +} + +.mat-tab-group.mat-background-warn .mat-tab-label, +.mat-tab-group.mat-background-warn .mat-tab-link, +.mat-tab-nav-bar.mat-background-warn .mat-tab-label, +.mat-tab-nav-bar.mat-background-warn .mat-tab-link { + color: #fff +} + +.mat-tab-group.mat-background-warn .mat-tab-label.mat-tab-disabled, +.mat-tab-group.mat-background-warn .mat-tab-link.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-warn .mat-tab-label.mat-tab-disabled, +.mat-tab-nav-bar.mat-background-warn .mat-tab-link.mat-tab-disabled { + color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-warn .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-warn .mat-tab-header-pagination-chevron { + border-color: #fff +} + +.mat-tab-group.mat-background-warn .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron, +.mat-tab-nav-bar.mat-background-warn .mat-tab-header-pagination-disabled .mat-tab-header-pagination-chevron { + border-color: rgba(255, 255, 255, .4) +} + +.mat-tab-group.mat-background-warn .mat-ripple-element, +.mat-tab-nav-bar.mat-background-warn .mat-ripple-element { + background-color: rgba(255, 255, 255, .12) +} + +.mat-toolbar { + background: #f5f5f5; + color: rgba(0, 0, 0, .87) +} + +.mat-toolbar.mat-primary { + background: #78b7e5; + color: #fff +} + +.mat-toolbar.mat-accent { + background: #78b7e5; + color: #fff +} + +.mat-toolbar.mat-warn { + background: #f44336; + color: #fff +} + +.mat-toolbar .mat-focused .mat-form-field-ripple, +.mat-toolbar .mat-form-field-ripple, +.mat-toolbar .mat-form-field-underline { + background-color: currentColor +} + +.mat-toolbar .mat-focused .mat-form-field-label, +.mat-toolbar .mat-form-field-label, +.mat-toolbar .mat-form-field.mat-focused .mat-select-arrow, +.mat-toolbar .mat-select-arrow, +.mat-toolbar .mat-select-value { + color: inherit +} + +.mat-toolbar .mat-input-element { + caret-color: currentColor +} + +.mat-tooltip { + background: rgba(97, 97, 97, .9) +} + +.mat-tree { + background: #fff +} + +.mat-nested-tree-node, +.mat-tree-node { + color: rgba(0, 0, 0, .87) +} + +.mat-snack-bar-container { + color: rgba(255, 255, 255, .7); + background: #323232; + box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 6px 10px 0 rgba(0, 0, 0, .14), 0 1px 18px 0 rgba(0, 0, 0, .12) +} + +.mat-simple-snackbar-action { + color: #78b7e5 +} + +.mat-select { + display: inline-block; + width: 100%; + outline: none +} + +.mat-select-trigger { + display: inline-table; + cursor: pointer; + position: relative; + box-sizing: border-box +} + +.mat-select-disabled .mat-select-trigger { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default +} + +.mat-select-value { + display: table-cell; + max-width: 0; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.mat-select-value-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis +} + +.mat-select-arrow-wrapper { + display: table-cell; + vertical-align: middle +} + +.mat-form-field-appearance-fill .mat-select-arrow-wrapper { + transform: translateY(-50%) +} + +.mat-form-field-appearance-outline .mat-select-arrow-wrapper { + transform: translateY(-25%) +} + +.mat-form-field-appearance-standard.mat-form-field-has-label .mat-select:not(.mat-select-empty) .mat-select-arrow-wrapper { + transform: translateY(-50%) +} + +.mat-form-field-appearance-standard .mat-select.mat-select-empty .mat-select-arrow-wrapper { + transition: transform 400ms cubic-bezier(0.25, 0.8, 0.25, 1) +} + +._mat-animation-noopable.mat-form-field-appearance-standard .mat-select.mat-select-empty .mat-select-arrow-wrapper { + transition: none +} + +.mat-select-arrow { + width: 0; + height: 0; + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid; + margin: 0 4px +} + +.mat-select-panel-wrap { + flex-basis: 100% +} + +.mat-select-panel { + min-width: 112px; + max-width: 280px; + overflow: auto; + -webkit-overflow-scrolling: touch; + padding-top: 0; + padding-bottom: 0; + max-height: 256px; + min-width: 100%; + border-radius: 4px +} + +.cdk-high-contrast-active .mat-select-panel { + outline: solid 1px +} + +.mat-select-panel .mat-optgroup-label, +.mat-select-panel .mat-option { + font-size: inherit; + line-height: 3em; + height: 3em +} + +.mat-form-field-type-mat-select:not(.mat-form-field-disabled) .mat-form-field-flex { + cursor: pointer +} + +.mat-form-field-type-mat-select .mat-form-field-label { + width: calc(100% - 18px) +} + +.mat-select-placeholder { + transition: color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1) +} + +._mat-animation-noopable .mat-select-placeholder { + transition: none +} + +.mat-form-field-hide-placeholder .mat-select-placeholder { + color: transparent; + -webkit-text-fill-color: transparent; + transition: none; + display: block +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/3_dx-dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/3_dx-dir.scss new file mode 100644 index 0000000..d9162ad --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/3_dx-dir.scss @@ -0,0 +1,10 @@ +/*==================================== + DX-DIRECTORY +======================================*/ + +@import 'dx-button.scss'; +@import 'dx-checkbox.scss'; +@import 'dx-grid.scss'; +@import 'dx-toolbar.scss'; +@import 'dx-typography.scss'; +@import 'dx-additional.scss'; \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-additional.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-additional.scss new file mode 100644 index 0000000..0c53c1a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-additional.scss @@ -0,0 +1,74 @@ +@import 'hr-core-consts.scss'; +/*===================================== + DX-ADDITIONAL +======================================*/ + +.dx-tooltip-wrapper .dx-overlay-content { + border: 1px solid #ddd; + background-color: #fff; + color: #333; + -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + border-radius: $hrBorder-radius-small; +} + +.dx-tooltip-wrapper.dx-popover-wrapper .dx-popover-arrow:after { + border: 1px solid #ddd; + background: #fff; +} + +.dx-slider .dx-tooltip-wrapper .dx-overlay-content { + -webkit-box-shadow: none; + box-shadow: none; +} + +.dx-tooltip-wrapper.dx-popover-wrapper .dx-popover-arrow { + display: block; +} + + +// DX Tabs styling +//---------------- Tabs +.dx-tab { + background: $hrColor-DarkBlue; + transition: all 0.3s ease; +} + +.dx-tab.dx-tab-selected, +.dx-tab.dx-tab-selected .mat-icon { + color: $hrColor-LightBlue; +} + +.dx-tab-content, +.dx-tab-text { + vertical-align: middle; + text-transform: uppercase; + line-height: 24px; + font-weight: 500; +} + + +.dx-tabs.dx-state-focused .dx-tab.dx-state-focused { + background-color: $hrColor-DarkBlue; //rgba(3,169,244,.12) +} + +.dx-tab.dx-tab-selected:before { + height: 2px !important; +} + +.dx-tab:hover:not([disabled]) { + background-color: $hrColor-LightBlue !important; + color: $hrColor-DarkBlue !important; +} + +.dx-tab:hover:not([disabled]) .mat-icon { + color: $hrColor-DarkBlue !important; +} + +.dx-tab:not(.dx-tab-selected):not(.dx-state-hover) { + background: 0 0; +} + +.dx-tabs { + text-align: center; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-button.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-button.scss new file mode 100644 index 0000000..b82d67a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-button.scss @@ -0,0 +1,84 @@ +/*===================================== + DX-BUTTON +======================================*/ +.buttonClose { + font-size: 16px; + cursor: pointer; + text-align: center; + margin-left: auto; + float: right; +} + +.btn-layout-ok { + cursor: pointer !important; + top: 5px; + right: 5px; + margin-left: 5px; + border-width: 0; +} + +.btn-layout-cancel { + cursor: pointer !important; + top: 5px; + right: 5px; + margin-left: 5px !important; + border-width: 0; +} + +.withexport .dx-button { + // margin-left: 0px !important; + left: -1px; + margin-top: 6%; + height: 21px; + width: 21px; + min-width: 21px !important; +} + +.withexport .dx-button .dx-button-content { + padding: 0px; + top: 1px; +} +//----------------------- setting for grid's export button: end + +/*===================================== + DX-DIAL-BUTTON +======================================*/ + +// corrections for css of dev-extreme 23.2.5 - dial button: start +.dx-fa-button.dx-fa-button-main .dx-overlay-content { + min-width: 56px; + max-height: 56px; + border-radius: 28px; +} + +.dx-fa-button.dx-fa-button-main .dx-overlay-content .dx-fa-button-icon, +.dx-fa-button.dx-fa-button-main .dx-overlay-content .dx-fa-button-icon-close { + padding: 19px; +} + +// corrections for css of dev-extreme 23.2.5 - dial button: end + +.dx-fa-button.dx-fa-button-main .dx-overlay-content { + background-color: rgba(255,255,255,0.4); + color: $hrColor-DarkBlue; +} + + +.dx-fa-button.dx-fa-button-main .dx-overlay-content .dx-fa-button-label-wrapper .dx-fa-button-label { + text-transform: none; + font-weight: bolder; + color: $hrColor-DarkBlue; + font-size: 14px; +} + + +.dx-fa-button .dx-fa-button-icon .dx-icon, +.dx-fa-button .dx-fa-button-icon-close .dx-icon { + font-size: 30px; + margin-top: -6px; + margin-left: -6px; +} + +.dx-fa-button .dx-overlay-content .dx-fa-button-label-wrapper .dx-fa-button-label { + font-size: 14px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-checkbox.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-checkbox.scss new file mode 100644 index 0000000..2b80303 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-checkbox.scss @@ -0,0 +1,12 @@ +/*===================================== + DX-CHECKBOX +======================================*/ +.cb-checked-first { + cursor: pointer !important; + margin-top: 12px; + right: 20px; + margin-left: auto !important; + border-width: 0; + font-size: smaller; + position: relative; +} \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-grid.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-grid.scss new file mode 100644 index 0000000..f6106fb --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-grid.scss @@ -0,0 +1,179 @@ +/*==================================== + DX-GRID +======================================*/ + +.hr-dx-datagrid-height-area .dx-datagrid-rowsview { + height: 1px !important; //trick to prevent dx-grid to overflow, if grid's heigh not fixed and aligned to the area above +} + +.hr-dx-datagrid-height-auto .dx-datagrid-rowsview { + height: inherit !important; //default behavior: the dx-grid heigh=auto if it is not fixed -> it aligns to the area above if its heigh td:not(.dx-focused), +.dx-datagrid-rowsview .dx-row-focused.dx-data-row > tr > td:not(.dx-focused), +.dx-datagrid-rowsview .dx-row-focused.dx-data-row .dx-command-edit .dx-link { + background-color: $hrColor-LightBlue !important; + color: #fff !important; +} + +.dx-datagrid .dx-datagrid-content .dx-datagrid-table .dx-row > td { + padding-left: 3px; // !important; + padding-right: 3px; // !important; + padding-bottom: 5px; // !important; + padding-top: 5px; // !important; +} + +.dx-datagrid-headers .dx-datagrid-content .dx-datagrid-table .dx-row.dx-header-row > td { + padding-top: 5px !important; + padding-bottom: 5px !important; +} + +.dx-datagrid .dx-datagrid-content .dx-datagrid-table .dx-row > td:first-child { + padding-left: 10px; +} + +.dx-datagrid .dx-datagrid-content .dx-datagrid-table .dx-row > td:last-child { + padding-right: 10px; +} + + +.dx-datagrid .dx-column-indicators.dx-visibility-hidden { + display: none; //don't show gap for the align=center grid headers if sort arrow is shown rights +} + +//----------------------- grid header settings +.headeralignment_left .dx-datagrid-headers .dx-datagrid-table .dx-row>td { + //align only grid header left + text-align: left !important; +} + +.headeralignment_right .dx-datagrid-headers .dx-datagrid-table .dx-row>td { + //align only grid header right + text-align: right !important; +} + +.headeralignment_center .dx-datagrid-headers .dx-datagrid-table .dx-row>td { + //align only grid header center + text-align: center !important; +} + +// .dx-datagrid-headers .dx-datagrid-table .dx-row>td { +// +// text-align: left !important; //set all dx-headers left aligned - must be used in style.css - apps depended, not in core! +// padding-top: 5px; //enger grid headers +// padding-bottom: 5px; //enger grid headers +// } + +//----------------------- grid row filter settings +.dx-datagrid .dx-editor-with-menu, +.dx-datagrid-container .dx-editor-with-menu { + height: 20px; +} + + +.dx-editor-cell .dx-texteditor .dx-texteditor-input { + height: 20px; + padding-top: 10px; +} + +.dx-datagrid .dx-editor-with-menu .dx-menu-item-content .dx-icon.dx-icon-filter-operation-default, +.dx-datagrid-container .dx-editor-with-menu .dx-menu-item-content .dx-icon.dx-icon-filter-operation-default, +.dx-datagrid .dx-item-content dx-menu-item-content { + // margin-top: -14px; + margin-top: 3px; +} + +// .dx-datagrid .dx-dropdowneditor-icon::before { +// margin-top: -12px; +// } + +.dx-datagrid .dx-texteditor-input-container .dx-placeholder { + margin-top: -5px; +} + +.dx-editor-cell.dx-editor-inline-block:not(.dx-command-select)::before { + padding-top: 0px; + padding-bottom: 0px; +} + +//------------------------ setting for grid's export button +.withexport .dx-datagrid-export-button .dx-icon-export-excel-button:before { + content: "\f05f"; +} + +.withexport .dx-datagrid-export-button .dx-icon-xlsxfile:before { + content: "\f05f"; +} + +.withexport .dx-header-row > td:last-of-type > .dx-datagrid-text-content { + width: calc(100% - 8px); +} + +.withexport .dx-header-row > td:last-of-type > .dx-sort-indicator { + width: calc(100% - 28px); +} + +.withexport .dx-datagrid-header-panel { + z-index: 2; +} +//----------------------- setting for grid's export button: end + +//---------customizing + +.dx-freespace-row { + height: 0px !important; +} + +.inline-edit-grid .dx-datagrid .dx-datagrid-content .dx-datagrid-table .dx-row>td { + padding-left: 7px; + padding-right: 7px; +} + +.inline-edit-grid .dx-datagrid .dx-datagrid-content .dx-datagrid-table .dx-row:not(.dx-header-row)>td { + padding-bottom: 0px; + padding-top: 0px; +} + + +.inline-editor { + // margin-top: -0.7em; + width: 100%; +} + +.inline-editor .mat-form-field-infix { + border-top-width: 0px; +} + + +.inline-editor-suffix { + // margin-top: -0.7em; + width: 100%; + padding-right: 10px; +} + +.inline-editor-checkbox { + padding-left: 5px; + margin-top: 0px; +} + + +td[role='gridcell']:has(.grid-vert-left-line) { + border-left: 1px solid #e0e0e0; +} + +td[role='gridcell']:has(.grid-vert-right-line) { + border-right: 1px solid #e0e0e0; +} + +td[role='gridcell']:has(.grid-botom-line) { + border-bottom: 1px solid #e0e0e0; +} + +td[role='gridcell']:has(.grid-top-line) { + border-top: 1px solid #e0e0e0; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-toolbar.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-toolbar.scss new file mode 100644 index 0000000..637b3f7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-toolbar.scss @@ -0,0 +1,17 @@ +/*===================================== + DX-TOOLBAR +======================================*/ + +.withexport .dx-toolbar { + height: 0px; +} + +.withexport .dx-toolbar .dx-toolbar-items-container { + height: 0px; + left: 10px; +} + +.withexport .dx-toolbar-after { + height: 0px; + padding-left: 0px !important; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-typography.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-typography.scss new file mode 100644 index 0000000..401ba8c --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-devextreme-styling/dx-typography.scss @@ -0,0 +1,11 @@ +/*==================================== + DX-TYPOGRAPHY +======================================*/ + +//for the same layout of material autocomplete, material calendar and material select components +// .dx-theme-material-typography input, +// .dx-theme-material-typography textarea { +// // font-family: inherit !important; //to use font from instead /css/dx.material.blue.light.compact.css of indigo-pink.scss +// //to use line-height from instead /css/dx.material.blue.light.compact.css of indigo-pink.scss +// line-height: 1 !important; +// } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/3_mat-dir.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/3_mat-dir.scss new file mode 100644 index 0000000..de84a82 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/3_mat-dir.scss @@ -0,0 +1,9 @@ +/*==================================== + MATERIAL-DIRECTORY +======================================*/ + +@import 'mat-button.scss'; +@import 'mat-checkbox.scss'; +@import 'mat-toolbar.scss'; +@import 'mat-typography.scss'; +@import 'mat-additional.scss'; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-additional.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-additional.scss new file mode 100644 index 0000000..82c4085 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-additional.scss @@ -0,0 +1,149 @@ +@import 'hr-core-consts.scss'; +/*===================================== + MAT-ADDITIONAL +======================================*/ + +// sidenav styling +mat-sidenav-container, +mat-sidenav-content, +mat-sidenav { + height: 100%; +} + +/*=========================================================================================================================*/ + +mat-sidenav { + width: 250px; +} + +// Tab Gruppen +mat-tab-group { + text-align: center; +} + +mat-tab-group p { + padding-top: 20px; +} + +/*=========================================================================================================================*/ +// spinner styling + +.mat-spinner circle { + stroke: $hrColor-DarkBlue !important; //#78b7e5; +} + +.hrd-mat-spinner { + transform: scale(0.3); + left: calc(50% - 46px); + top: -38px; + // display: inline-block !important; + position: absolute !important; +} + +.input.mat-input-element { + margin-top: inherit !important; +} + +// the next 2 settings do the mat form field enger +.mat-form-field-appearance-legacy .mat-form-field-underline { + bottom: 5px; +} + +.mat-form-field-wrapper { + padding-bottom: 5px !important; +} + +.mat-option { + height: 30px !important; + display: flex !important; +} + +/*=========================================================================================================================*/ +// dialog styling + +.mat-dialog-container { + border-radius: $hrBorder-radius-big !important; + height: auto !important; + overflow: hidden !important; +} + +//additional dead code +/* +// "-" symbol color in check box partially selected +::ng-deep .mat-checkbox-mixedmark { + background-color: rgba(0, 0, 0, .54); +} + +// check-symbol color in check box and width +::ng-deep .mat-checkbox-checkmark-path { + stroke: $hrColor-LightBlue !important; + stroke-width: 3 !important; +} +*/ + + +.mat-tab-label-active { + font-weight: bold !important; + opacity: 1 !important; +} + +.hr-alfa-disabled .mat-form-field-disabled, +.hr-alfa-disabled .mat-form-field-disabled .mat-select-value, +.hr-alfa-disabled .mat-input-element:disabled, +.hr-alfa-disabled .mat-checkbox-disabled .mat-checkbox-label, +.hr-alfa-disabled .mat-checkbox-disabled .mat-checkbox-input, +.hr-alfa-disabled .mat-radio-button.mat-radio-disabled .mat-radio-label-content { + color: rgba(0, 0, 0, $hrColor-Alpha_Disabled) !important; +} + +//--- menu + +.mat-menu-item { + line-height: 30px !important; + height: 30px !important; +} + + +//--- errors +.mat-error { + text-align: left; + width: fit-content; + background-color: rgb(255, 255, 255); +} + + +/*=========================================================================================================================*/ +// stepper + +.mat-vertical-stepper-header { + padding: 24px 10px 24px 24px; +} + +.mat-stepper-vertical-line::before { + top: -16px; + bottom: -16px; +} + + +/*=========================================================================================================================*/ +// drop down + +.mat-select-trigger { + height: 1.25em; + display: inline-table !important; +} + +.mat-input-element { + text-overflow: ellipsis; + // overflow: hidden; + // white-space: nowrap; +} + +.mat-select-arrow-wrapper { + display: table-cell !important; +} + +// .dx-dropdowneditor-button .dx-button-content { +// position: absolute; +// margin-top: 5px; +// } diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-button.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-button.scss new file mode 100644 index 0000000..8005406 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-button.scss @@ -0,0 +1,142 @@ +@import 'hr-core-consts.scss'; +/*===================================== + MAT-BUTTON +======================================*/ + +.mat-stroked-button, +.mat-raised-button { + min-width: auto !important; + padding-right: 5px !important; + padding-left: 5px !important; + transition: all 0.3s ease; +} + +//Stroke button accent styling +.mat-button.mat-accent, +.mat-icon-button.mat-accent, +.mat-stroked-button.mat-accent { + color: white; + background: $hrColor-DarkBlue; +} + +.mat-stroked-button:hover:not([disabled]), +.mat-raised-button:hover:not([disabled]) +{ + background-color: $hrColor-LightBlue !important; + color: $hrColor-DarkBlue !important; + border-color: $hrColor-DarkBlue; +} + +.mat-stroked-button:hover:not([disabled]) .mat-icon, +.mat-raised-button:hover:not([disabled]) .mat-icon +{ + color: $hrColor-DarkBlue !important; +} + +.mat-stroked-button:focus, +.mat-raised-button:focus + { + background: $hrColor-DarkBlue; + color: $hrColor-LightBlue; +} + +.mat-stroked-button:focus .mat-icon, +.mat-raised-button:focus .mat-icon, +.mat-stroked-toggle:focus .mat-icon { + color: $hrColor-LightBlue; +} + +.material-icons { + color: $hrColor-DarkBlue; + text-align: center; + } + +.mat-button .material-icons, +.mat-fab .material-icons, +.mat-mini-fab .material-icons { + color: unset; +} + +.mat-icon-button { + padding: 0 !important; + min-width: 0 !important; + width: 25px !important; + height: 25px !important; + flex-shrink: 0 !important; + line-height: 25px !important; + border-radius: 50% !important; +} + +.mat-stroked-button[disabled] .material-icons, +.mat-icon-button[disabled] .material-icons, +.mat-flat-button[disabled] .material-icons, +.mat-raised-button[disabled] .material-icons { + color: rgba(11, 58, 98, 0.4); +} + +.mat-raised-button { + margin-right: 2px !important; +} + +//---------- Mat Toggle Buttons --------- + +.mat-button-toggle:focus + { + background: $hrColor-LightBlue; + color: white; +} + +.mat-stroked-toggle:focus .mat-icon { + color: white; +} + +.hr-darkblue .mat-button-toggle +{ + background: $hrColor-DarkBlue; + color: white !important; +} + +.hr-darkblue .mat-button-toggle-checked +{ + background: $hrColor-LightBlue; + color: white !important; + // border-color: $hrColor-DarkBlue; +} + +.mat-button-toggle-checked +{ + background: $hrColor-DarkBlue; + color: $hrColor-LightBlue !important; +// border-color: $hrColor-DarkBlue; +} + +.mat-button-toggle:hover:not([disabled]) +{ + background-color: $hrColor-LightBlue !important; + color: $hrColor-DarkBlue !important; + border-color: $hrColor-DarkBlue; +} + +.mat-button-toggle:hover:not([disabled]) .material-icons { + color: $hrColor-DarkBlue !important; +} + +.mat-button-toggle[disabled] .material-icons { + color: rgba(11, 58, 98, 0.4); +} + + +.mat-button-wrapper:not(:has(.mat-icon)) { + padding-left: 5px; + padding-right: 5px; +} + +.mat-button-wrapper:has(.mat-icon) { + padding-right: 7px; +} + +.mat-button-withoutcaption .mat-button-wrapper:has(.mat-icon), +.mat-form-field .mat-button-wrapper +{ + padding-right: 0px; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-checkbox.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-checkbox.scss new file mode 100644 index 0000000..9960e27 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-checkbox.scss @@ -0,0 +1,37 @@ +/*===================================== + MAT-CHECKBOX +======================================*/ + +// check box frame color if is checked +::ng-deep .mat-checkbox-checked .mat-checkbox-frame { + border-color: $hrColor-LightBlue !important; +} + +//checkbox filling - transperant or light blue +::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background, +.mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { + background-color: $hrColor-LightBlue !important; //transparent; //#78b7e5; +} + +::ng-deep .mat-checkbox-checked.mat-accent .mat-checkbox-background { + background-color: $hrColor-LightBlueMain !important; +} + +::ng-deep .mat-step-header .mat-step-icon-selected { + background-color: $hrColor-DarkBlue !important; +} + +::ng-deep div.mat-step-icon.mat-step-icon-state-edit { + background-color: $hrColor-LightBlueMain !important; +} + +::ng-deep .mat-radio-button.mat-accent .mat-radio-inner-circle, +.mat-radio-button.mat-accent .mat-radio-ripple .mat-ripple-element:not(.mat-radio-persistent-ripple), +.mat-radio-button.mat-accent.mat-radio-checked .mat-radio-persistent-ripple, +.mat-radio-button.mat-accent:active .mat-radio-persistent-ripple { + background-color: $hrColor-DarkBlue; +} + +::ng-deep .mat-radio-button.mat-accent.mat-radio-checked .mat-radio-outer-circle { + border-color: $hrColor-DarkBlue; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-toolbar.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-toolbar.scss new file mode 100644 index 0000000..4aa1e8a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-toolbar.scss @@ -0,0 +1,21 @@ +@import 'hr-core-consts'; + +/*===================================== + MAT-TOOLBAR +======================================*/ + +.mat-toolbar.mat-primary { + background: $hrColor-DarkBlue !important; // #76a9cb; + color: #fff !important; +} + +.mat-toolbar-row, +.mat-toolbar-single-row { + height: 45px !important; +} + +mat-toolbar { + // border-bottom-left-radius: $hrBorder-radius-small; + // border-bottom-right-radius: $hrBorder-radius-small; + border-radius: $hrBorder-radius-small; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-typography.scss b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-typography.scss new file mode 100644 index 0000000..22cc1f5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/css/3-vendor/hr-material-styling/mat-typography.scss @@ -0,0 +1,3 @@ +/*==================================== + MAT-TYPOGRAPHY +======================================*/ diff --git a/ClientApp/staff-db-ui/src/app/shared/core/devextreme-license.ts b/ClientApp/staff-db-ui/src/app/shared/core/devextreme-license.ts new file mode 100644 index 0000000..b258d12 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/devextreme-license.ts @@ -0,0 +1 @@ +export const licenseKey = ''; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-decimal.directive.ts b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-decimal.directive.ts new file mode 100644 index 0000000..abd4e94 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-decimal.directive.ts @@ -0,0 +1,98 @@ +import { Directive, HostListener, ElementRef, OnInit, Optional, AfterViewInit, OnDestroy, Input, LOCALE_ID, Inject } from '@angular/core'; +import { formatNumber } from '@angular/common'; +import { NgControl } from '@angular/forms'; +import { Subscription } from 'rxjs'; +import * as keycode from '@angular/cdk/keycodes'; + + +@Directive({ + standalone: true, + selector: '[henselDecimal]' +}) +export class HenselMaskDecimalDirective implements OnInit, AfterViewInit, OnDestroy { + private el: HTMLInputElement; + private previousValue: any; + private subscription: Subscription; + private focused: boolean = false; + private noOfDecimals: number = 2; + private transformAnyway: boolean = false;S + @Input() + set henselDecimal(value: number) { + // if (value || value === 0) + this.noOfDecimals = value; + } + + @Input() henselDecimalAllowEmpty: boolean = false; + + constructor( + private elementRef: ElementRef, + @Inject(LOCALE_ID) private localeId: string, + @Optional() private control: NgControl) { + this.el = this.elementRef.nativeElement; + } + + useDirective(): boolean { + return (this.noOfDecimals !== undefined && this.noOfDecimals !== null); + } + + + @HostListener('focus', ['$event.target.value']) + onFocus() { + if (!this.useDirective()) return; + this.previousValue = this.control.value; //this.el.value; + this.transform(0, this.noOfDecimals); + this.focused = true; + this.el.select(); + } + + @HostListener('keydown', ['$event']) + onKeyDown(event: any) { + if (this.useDirective()) { + switch (event.which) { + case keycode.ESCAPE: // ESC + event.stopPropagation(); + // this.el.value = this.previousValue; + this.transformAnyway = true; + this.control.control.setValue(!this.previousValue && this.henselDecimalAllowEmpty ? this.previousValue : +(this.previousValue ?? 0)); + return false; + } + } + return true; + } + + + @HostListener('blur', ['$event.target.value']) + onBlur(value: any) { + if (!this.useDirective()) return; + this.focused = false; + this.transform(this.noOfDecimals, this.noOfDecimals); + if ((isNaN(this.control.value) || !this.control.value) && !this.henselDecimalAllowEmpty) this.control.control.setValue(0); + } + + ngAfterViewInit(): void { + } + + ngOnInit() { + if (!this.useDirective()) return; + this.subscription = this.control.valueChanges.subscribe(() => setTimeout(() => { + this.transform(this.noOfDecimals, this.noOfDecimals); + }, 0) + ); + } + + ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } + + + transform = (noOfDecimalsMin: number, noOfDecimalsMax: number) => { + const controlValueIsNull = (this.control.value === null) || (this.control.value === undefined); + if ((this.transformAnyway || !this.focused) && (!controlValueIsNull || this.el.value)) { + if ((controlValueIsNull || this.control.value === '') && this.henselDecimalAllowEmpty) { + this.el.value = null; + } else this.el.value = formatNumber(+this.control.value, this.localeId, `1.${noOfDecimalsMin}-${noOfDecimalsMax}`); + this.transformAnyway = false; + } + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-dnd.directive.ts b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-dnd.directive.ts new file mode 100644 index 0000000..f1fcb52 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-dnd.directive.ts @@ -0,0 +1,88 @@ +import { Directive, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, ViewChild } from '@angular/core'; + +@Directive({ + standalone: true, + selector: '[henselDnD]' +}) + + +export class HenselDnDDirective { + + private _disabled: boolean = false; + public get disabled(): boolean { + return this._disabled; + } + @Input() + public set disabled(value: boolean) { + this._disabled = value; + } + + // tslint:disable-next-line: no-output-on-prefix + @Output() onFileDropped = new EventEmitter(); + @HostBinding('style.background-color') private backgroundColor; + @HostBinding('style.opacity') private opacity; + // @ViewChild('dndicon') icon: ElementRef; + private icon: any; + private _dragover: boolean = false; + public get dragover(): boolean { + return this._dragover; + } + public set dragover(value: boolean) { + if (this._dragover === value) return; + if (value && this.disabled) return; + this._dragover = value; + if (value) { + if (!this.icon) { + this.icon = document.getElementById('dndicon'); + if (this.icon) { + this.lastIcon = this.icon.innerText; + if (this.icon) this.icon.innerText = 'vertical_align_top'; + } + } + this.backgroundColor = '#76a9cb'; + this.opacity = '1'; + } else { + setTimeout(() => { + if (!this.dragover) { + if (this.icon) this.icon.innerText = this.lastIcon; + this.icon = null; + delete this.opacity; + delete this.backgroundColor; + } + }, 100); + } + } + + private lastIcon: string; + + + //Dragover listener + @HostListener('dragover', ['$event']) onDragOver(evt) { + if (this.disabled) evt.dataTransfer.dropEffect = 'none'; + else evt.dataTransfer.dropEffect = 'copy'; + evt.preventDefault(); + evt.stopPropagation(); + this.dragover = true; + } + + //Dragleave listener + @HostListener('dragleave', ['$event']) public onDragLeave(evt) { + evt.preventDefault(); + evt.stopPropagation(); + this.dragover = false; + } + + //Drop listener + @HostListener('drop', ['$event']) public ondrop(evt) { + evt.preventDefault(); + evt.stopPropagation(); + if (!this._disabled) { + const files = evt.dataTransfer.files; + if (files.length > 0) this.onFileDropped.emit(files); + } + + this.dragover = false; + } + + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-mask.directive.ts b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-mask.directive.ts new file mode 100644 index 0000000..47904c5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-mask.directive.ts @@ -0,0 +1,35 @@ +import { Directive, HostListener, Input, Optional } from '@angular/core'; +import { NgControl } from '@angular/forms'; + +@Directive({ + standalone: true, + selector: '[henselMask]' +}) + +export class HenselMaskDirective { + @Input() + set henselMask(value) { + this.regExpr = new RegExp(value); + } + + private _oldvalue: string = ''; + private regExpr: any; + constructor(@Optional() private control: NgControl) { + } + @HostListener('input', ['$event']) + change($event) { + const item = $event.target; + const value = item.value; + let pos = item.selectionStart; + const matchvalue = value; + const noMatch: boolean = (value && !(this.regExpr.test(matchvalue))); + if (noMatch) { + item.selectionStart = item.selectionEnd = pos - 1; + if (item.value.length < this._oldvalue.length && pos === 0) pos = 2; + if (this.control) this.control.control.setValue(this._oldvalue, { emit: false }); + + item.value = this._oldvalue; + item.selectionStart = item.selectionEnd = pos - 1; + } else this._oldvalue = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-stepper-scroller.ts b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-stepper-scroller.ts new file mode 100644 index 0000000..ccb6d90 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/directives/hensel-stepper-scroller.ts @@ -0,0 +1,21 @@ +import { Directive, HostListener } from '@angular/core'; +import { MatStepper } from '@angular/material/stepper'; + +/* is used to: if a selected step is out of visibility, stepper screen is scrolled automatically to show it */ + +@Directive({ + standalone: true, + selector: '[mat-vertical-stepper-scroller]', +}) +export class MatVerticalStepperScrollerDirective { + constructor(private stepper: MatStepper) {} + + @HostListener('animationDone') + selectionChanged() { + const stepId = this.stepper._getStepLabelId(this.stepper.selectedIndex); + const stepElement = document.getElementById(stepId); + if (stepElement) { + stepElement.scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }); + } + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/images/DHR-2015-1004_DHR_Logo_Querformat_RGB.png b/ClientApp/staff-db-ui/src/app/shared/core/images/DHR-2015-1004_DHR_Logo_Querformat_RGB.png new file mode 100644 index 0000000000000000000000000000000000000000..89e15746902d8bff5df8a94351c5ba84ab4da606 GIT binary patch literal 29888 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 DUy(W~ literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_bright.ico b/ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_bright.ico new file mode 100644 index 0000000000000000000000000000000000000000..bc6c2d1fe45ce1642f6a2f9539bb66fa32fd687f GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_white.ico b/ClientApp/staff-db-ui/src/app/shared/core/images/hr-logo_white.ico new file mode 100644 index 0000000000000000000000000000000000000000..ff4f496b9c58968d7fe1f5c3d54bd47ec20366d2 GIT binary patch literal 3098 zcmbuB%}Z2K7>Cbw1})5H5txwVfGuhxAyg3I7%kjL2CZsiPz(`7tAeO-R{aGcMJ|f6 zZ)p)lWW*R$^r6dwG#bJ_KnkU_p~icA-r*j)oVmw)FI{=&J?DLY@9&(sb3atd;V-*Z z$)`%MQmR=gwGpz=0g{)a(5O^92_f#`y6y%z0e4{vetQ1F_y;_JO>zC=>R4hkz7N3F z>zR?#1!#)v8CQqrQTT1Hr{~lvjPr5*lIUdZz&gK}KZomZ&5trZiKYeWl6XgH@$Gamgv0D(+Yzi z-&?p1FJT7ce3W1uPQhWA3|n94sLOt1-4mjNUf2q9U0Dz6$K@O%a2W4}&o(hNxi|Zw z&N=+nC-RX1_Vd>yX(`ZVgPCT0N&W5A9~3 zIrn|6&l>SVGidh7oV@&Yq4$X2_b9B-%;E7$?>j6~pCO+%`(#dSG^|JGsCR|+1#@Wg zT5pT^90~U5G5S5W9?8=;thG9lTdBtqk=2uX8{s3@bb)HF&|_-*e7$uW)aBi98hEQ$_uXU@qj?AN z{uqMq=nm+$Y!O`_%-cM5Ui{!Z^E|Qo{A7GnnVU2qE)<8B0P8ScX+7>Di4tr4e&MjrTBogl|yu3?w%qx}@GwdOYRbGe!(OsC|Ni6rCuqq;-5dVG^p>191uD z`^$BH4tBF{eH>p;<-Cd-@XC(o&G7^*sWwP?1?6~Zh4Q*rtAS!h<%*d?uGCO$gY~6U av31TVI%Uz2`j7d7k&V=XpODciU8-nUR~3ii(Qa&_D+T+_V0x z^t8ZL4HWbfxPd}Y`betUVcu1sK@);Bw4?_LhTbC)Xfp&F*o9D0$q4^fK@nw|52&cP z4-9p*EhA<&^B-ayZC( zyxWQ)#ndM3Z{NU;8^4aG%aliwO~GHqFlcrf!wWPB^TsQ~;48yxQ(57I?>t^u?q}VI z`El}k*FcRS4vxdW@YTJP7fFG+ksmJ{!X-3&3w=^w@(P znH?d&m{p~+@ zl0y@dUGBvNflVc6xj=PBwF_#FQojltV7}4FCRjwqb#!v1MMz+p<SM?hl60S-L>L_EM1{3^ z7mFmNYQ->}Dh4_5!)-c;~^sZKG~3@s2LbkG$6fXbVz)Z$PYa`p z@X{6Lw2l{U!vTTU4*qhH#(I(e9x_=cXRfcRZ**nS8D;E@+r*TAdO~E{Up+Z^Um$suL5n zGRD+5);c2CTgU+Cj@6=~hf|3|>BXT)i8JXl4o_DmZ~_XX4K0du{Zd}Q?YB61B>J|y z*!HtPJubdyv5!l(xhRM)r!#3{!7QL`Dy

xZRhlB__E*^^Vsd@v(EELAy|D(+iq>$x% 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/app/shared/core/injection-tokens.ts b/ClientApp/staff-db-ui/src/app/shared/core/injection-tokens.ts new file mode 100644 index 0000000..3728d6a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/injection-tokens.ts @@ -0,0 +1,35 @@ +import { InjectionToken, NgModule } from '@angular/core'; + +export interface IENVIRONMENT { + production: boolean; + useLoginWithJWT?: boolean; + dontUseWindowsLogin?: boolean; + apiUrl: string; + APP_TITLE: string; + appVersion?: string; + appBuild?: string; + sentry_dsn?: string; + translationFolder: string; + headerData?: string; + culture?: string; + language?: string; + protocol?: string; +} + + +export const ENVIRONMENT_TOKEN = new InjectionToken('environment'); +export const SUPPORTED_LANGUAGES_TOKEN = new InjectionToken('Languages supported by App'); +export const SUPPORTED_CULTURES_TOKEN = new InjectionToken('Culturess supported by App'); + +export const APPICON4TEST_TOKEN = new InjectionToken('APPICON4TEST_TOKEN', { + providedIn: 'root', + factory: () => 'assets/icons/hr-logo_red.ico', +}); +export const APPICON4LIVE_TOKEN = new InjectionToken('APPICON4LIVE_TOKEN', { + providedIn: 'root', + factory: () => 'assets/icons/hr-logo_color.ico', +}); +export const APPICON4NAVBAR_TOKEN = new InjectionToken('APPICON4NAVBAR_TOKEN', { + providedIn: 'root', + factory: () => 'assets/icons/hr-logo_bright.ico', +}); diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/coreuser.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/coreuser.ts new file mode 100644 index 0000000..8d9d3b4 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/coreuser.ts @@ -0,0 +1,75 @@ +import { BaseEntity } from '../models/generics/baseentity'; +import { EN_CoreEntities } from '../services/globals'; + +export interface UserRole { + code: string; + caption: string; +} + + +export const enum EN_UserRoles { + User = 'user', + Master = 'master', + Admin = 'admin', + DepartmentMaster = 'departmentmaster', + DepartmentUser = 'departmentuser' +} + + +export class CoreUser extends BaseEntity { + typeName: string = EN_CoreEntities.User; + + webAppUserId: number; + name: string; + shortName: string; + loginName: string; + password: string; + roleList: string; + webAppRoleList: string; + token?: string; + jwtExpiredOn: Date; + lastLogin: string | Date | null; + clientVersion: string; + timeZoneOffsetInMin: number; + language: string; + culture: string; + showDisclaimer: boolean; + + get entityId(): number { return this.webAppUserId; } + set entityId(id: number) { this.webAppUserId = id; } + + get isAdmin(): boolean { + return this.isInRolle(EN_UserRoles.Admin); + } + + get isMaster(): boolean { + return this.isInRolle(EN_UserRoles.Master) || this.isInRolle(EN_UserRoles.DepartmentMaster) || this.isAdmin; + } + + showFooter: boolean; + + public isInRolle(role: string): boolean { + role = role?.toLowerCase(); + return (this.roleList && ((',' + this.roleList.replace(' ', '') + ',').toLowerCase().indexOf(',' + role + ',') > -1)) + || (this.webAppRoleList && ((',' + this.webAppRoleList.replace(' ', '') + ',').toLowerCase().indexOf(',' + role + ',') > -1)); + } + + + assign(source: Partial): CoreUser { + super.assign(source); + if (this.jwtExpiredOn && typeof this.jwtExpiredOn !== 'object') this.jwtExpiredOn = new Date(this.jwtExpiredOn); + return this; + } + + clear() { + super.clear(); + this.jwtExpiredOn = undefined; + this.token = undefined; + } +} + + +export interface UserRoles { + admin?: boolean; + master?: boolean; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.ts new file mode 100644 index 0000000..f7b701e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.ts @@ -0,0 +1,209 @@ + +import { cnst_ErrorCode4Unauthorized, EN_Error } from '../../consts'; +import { ResultSubject } from '../../models/resultsubject'; +import { RepositoryService } from '../../services/http/repository.service'; +import { Observable } from 'rxjs'; +import { now } from '../../utils'; + +export type BaseEntityCallBack = (entity?: BaseEntity) => void; +export type ErrorCallBack = (error: any) => void; + +export class BaseEntity { + public typeName: string = ''; //is used as Controller for URL queries + public get entitytitle(): string { return ''; } //is used for messages + public get useNull4Clear(): boolean { return false; } //is used for clear to set null instead of 0 or '' + public entityChanged: boolean = false; + get dateFields(): string { + return null; + } + protected technicalFields: string[] = ['dateFields', 'dontInsertFields', 'dontUpdateFields', 'typeName', 'entitytitle', 'technicalFields', 'lastLoaded', 'useNull4Clear']; + public dontUpdateFields: string[] = [...this.technicalFields, 'entityChanged']; + public dontInsertFields: string[] = [...this.technicalFields, 'entityChanged']; + public lastLoaded: number; + + resetCallBack: (obj: BaseEntity) => void; + + constructor(source?: Partial) { + // this.typeName = this.constructor.name; //is not working in productive environment !!! + if (source) this.assign(source); + else this.clear(); + } + + public deleteFields(): BaseEntity { + const retEntity: BaseEntity = Object.assign({}, this); + const whatfields: string[] = this.isNew() ? this.dontInsertFields : this.dontUpdateFields; + whatfields.forEach((field: string) => delete retEntity[field]); + return retEntity; + } + + get entityId(): number { return -1; } + set entityId(id: number) { } + + + public assign(source: Partial): BaseEntity { + this.clear(); + const res = Object.assign(this, source); + this.approveDateFields(this.dateFields); + return res; + } + + + public approveDateField(fieldname: string) { + if (this[fieldname] && !(this[fieldname] instanceof Date)) this[fieldname] = new Date(this[fieldname]); + } + + + public approveDateFields(fieldnames: string) { + if (!fieldnames) return; + const list = fieldnames.split(','); + list.forEach(fld => this.approveDateField(fld.trim())); + } + + + protected clearField(fldName: string, useNull: boolean = false) { + if (this[fldName] instanceof Array) this[fldName] = []; + else { + if (fldName.slice(-2) === 'Id') this[fldName] = null; + else { + switch (useNull || this.useNull4Clear ? null : typeof this[fldName]) { + case 'number': + this[fldName] = 0; + break; + case 'boolean': + this[fldName] = false; + break; + case 'string': + this[fldName] = ''; + break; + default: + this[fldName] = null; + break; + } + } + } + } + + + public clear(useNull: boolean = false) { + try { + for (const prop in this) { + if ((this.technicalFields.indexOf(prop) === -1) && this.propertyIsEnumerable(prop)) this.clearField(prop, useNull); + } + } catch (ex) { } + + if (this.isRealObject()) this.entityId = 0; + + this.entityChanged = false; + if (this.resetCallBack) { this.resetCallBack(this); } + } + + + public isEmpty() { + return Object.keys(this).length === 0 && (typeof this) === 'object'; + } + + //checks if this a realy Object with all methods but not only record with data fields after http call + public isRealObject() { + return 'entityId' in this; + } + + + public isValidInput() { return true; } + + public isNew() { return !this.entityId || this.entityId <= 0; } + + public insertWithIds() { return false; } + + load(repositoryService: RepositoryService, loadedcallback: BaseEntityCallBack, errorcallback?: ErrorCallBack, completecallback?: () => void): boolean { + const currentId = this.entityId; + if (!this.isNew() || currentId === -1) //-1 means load entity w/o id, f.e. Info + { + repositoryService.getDataById(this.typeName, currentId) + .subscribe((entity: BaseEntity) => { + if (this.entityId !== currentId) return false; //means, that meanwhile a load command for another Id was executed. it must win + console.log('loaded', entity); + this.lastLoaded = now(); + this.assign(entity); + if (loadedcallback) loadedcallback(this); + return true; + }, (error: any) => { + if (error.status !== cnst_ErrorCode4Unauthorized) this.clear(); + if (errorcallback) errorcallback(new ResultSubject(error, this, this.typeName + ': ')); + }, completecallback); + } else { + this.clear(); + // if (loadedcallback) loadedcallback(this); //for new only complete is triggered - otherwise an empty line is added to the grid, because of sync + if (completecallback) completecallback(); + } + return false; + } + + + public includeFieldForUpdate(fieldNames: string) { + const fieldList = fieldNames.split(','); + fieldList.forEach(fieldName => { + const index = this.dontUpdateFields.indexOf(fieldName); + if (index > -1) this.dontUpdateFields.splice(index, 1); + }); + } + + + public excludeFieldFromUpdate(fieldNames: string) { + const fieldList = fieldNames.split(','); + fieldList.forEach(fieldName => { + const index = this.dontUpdateFields.indexOf(fieldName); + if (index === -1) this.dontUpdateFields.push(fieldName); + }); + } + + + public async saveAsync(repositoryService: RepositoryService): Promise { + return new Promise((resolve, reject) => this.save(repositoryService, () => resolve(true), () => resolve(false))); + } + + + public save(repositoryService: RepositoryService, loadedcallback: BaseEntityCallBack, errorcallback?: ErrorCallBack, completecallback?: () => void, useSuffixInsteadEntityId?: string): void { + const lastId = this.entityId; + if (this.isNew()) this.entityId = this.insertWithIds() ? -this.entityId : 0; //the case when entityId<0 + const cloneEntity = this.deleteFields(); + this.entityId = lastId; //the case when entityId<0 + // if (this.isNew()) cloneEntity.entityId = 0; //the case when entityId<0 + + const loadedObj$: Observable = !this.isNew() && (useSuffixInsteadEntityId === null || useSuffixInsteadEntityId === undefined) ? + repositoryService.putDataById(this.typeName, this.entityId, cloneEntity) : + repositoryService.postDataById(this.typeName, useSuffixInsteadEntityId ?? this.entityId, cloneEntity); + + loadedObj$.subscribe( + (entity: BaseEntity) => { + console.log('loaded', entity); + this.assign(entity); + if (!this.isNew() /* means save successed*/) { + this.lastLoaded = now(); + if (loadedcallback) loadedcallback(this); + } else { + this.entityChanged = true; + if (errorcallback) errorcallback(({ errMsg: this.typeName + ': ' + EN_Error.Save, entity: this })); + } + } + , (error: any) => { if (errorcallback) errorcallback(new ResultSubject(error, this, this.typeName + ': ')); } + , completecallback); + } + + + //delete by Id + delete(repositoryService: RepositoryService, loadedcallback: BaseEntityCallBack, errorcallback?: ErrorCallBack, completecallback?: () => void): boolean { + //return this.load_update(EN_HTPPMethod.Delete, dataservice, loadedcallback, errorcallback, extrafilter); + if (!this.isNew()) { + repositoryService.deleteDataById(this.typeName, this.entityId) + .subscribe(() => { + console.log('deleted', this); + if (loadedcallback) loadedcallback(this); + return true; + } + , (error: any) => { if (errorcallback) errorcallback(new ResultSubject(error, this, this.typeName + ': ')); } + , completecallback); + } else this.clear(); + return true; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.wrapper.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.wrapper.ts new file mode 100644 index 0000000..11d3e5f --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentity.wrapper.ts @@ -0,0 +1,895 @@ +import * as keycode from '@angular/cdk/keycodes'; +import { inject } from '@angular/core'; +import { NgForm } from '@angular/forms'; +import { BehaviorSubject, forkJoin, Subject, Subscription } from 'rxjs'; +import { cnst_CANCEL_ERROR, EN_EntityBeforeSaveCallBackResults, EN_EntityEditingStates } from '../../consts'; +import { IMessageBoxData } from '../../services/globals'; +import { AppLogsService } from '../../services/applogs.service'; +import { RepositoryService } from '../../services/http/repository.service'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { getErrorMessageAsText, now } from '../../utils'; +import { ResultSubject } from '../resultsubject'; +import { BaseEntity, BaseEntityCallBack, ErrorCallBack } from './baseentity'; +import { BaseEntityDetail, BaseEntityDetailList, mdLOAD, mdSAVE } from './baseentitydetaillist'; +import { BaseEntityListWrapper } from './baseentitylist.wrapper'; +import { MatDialogRef } from '../../components/angular-material-index'; + + +export enum EN_SynchronizeListAfter { + Load = 0, + New = 1, + Save = 2 +} + + +export class BaseEntityWrapper { + public static EN_ViewMode = EN_EntityEditingStates.View; + public static EN_NewMode = EN_EntityEditingStates.New; + public static EN_EditMode = EN_EntityEditingStates.Edit; + public static EN_KeyEditMode = EN_EntityEditingStates.EditKey; + public static EN_Idle = EN_EntityEditingStates.Idle; + public entityList: BaseEntityListWrapper; + public delayEntityChange = 500; //delay to set changed flag + public delaySetEditModeCallback = 500; //delay to call callback after edit mode was changed + public delayToReloadedEntity = 2000; //reload entity only after delay since it was loaded last time + public loadedDataExpiresInMs: number = 0; //reload entity before edit if it was loaded longer as loadedDataExpiresInMs, if loadedDataExpiresInMs = 0 - no reload before edit + + public syncEntityListWhenSave: boolean = true; + public syncEntityListWhenLoad: boolean = true; + private _lastChangedTime = 0; //to avoid repeateadly changing of changed during loading/assigning + private _detailForm: NgForm; + protected _entity: T; + + + public errorCallBack: ErrorCallBack; + public loadedCallBack: BaseEntityCallBack; + public completeCallBack: () => void; + public beforeNewCallBack: BaseEntityCallBack; //callback to be called before insert + public beforeSaveCallBack: (entity: BaseEntity) => Promise; //callback to be called before save, returns 0-all ok, continue saving, 1-all ok, break further saving, 2 - error, ignore coninue + public beforeDeleteCallBack: (entity: BaseEntity) => Promise; //callback to be called before save, returns 0-all ok, continue saving, 1-all ok, break further saving, 2 - error, ignore coninue + public isEntityChangedCallBack: (entity: BaseEntity) => boolean; + public isEntityValidCallBack: (entity: BaseEntity) => boolean; + + public detailFormHTMLId: string; + public entityLoaded$: Subject = new Subject(); + + public entityIsLoading$: BehaviorSubject = new BehaviorSubject(false); + public onCheckFormValidInput: (form: NgForm) => boolean; + public get entityIsLoading(): boolean { + return this.entityIsLoading$.value; + } + public set entityIsLoading(value: boolean) { + const wasLoading = this.entityIsLoading; + if (!value && wasLoading || value && !wasLoading) this.entityIsLoading$.next(value); + this.appLogsService.dlog('--- Loading', this.entity.typeName + ': ' + this.entity.entityId + ' == ' + value); + if (!value && wasLoading) this.entityLoaded$.next(); + } + + public indexInList4New: number = -1; //last + + private _keyDownListenerStopped: boolean = false; + public get keyDownListenerStopped(): boolean { + return this._keyDownListenerStopped || + this.detailItems.items.some((item: BaseEntityDetail) => item.baseEntityList ? item.baseEntityList.focusedEntityShadowed?.keyDownListenerStopped : item.baseEntityWrapper.keyDownListenerStopped); + } + public set keyDownListenerStopped(value: boolean) { + this._keyDownListenerStopped = value; + } + + public hierarchyLevel: number = 0; + public confirmationsOn: boolean = true; + public dontShowErrors: boolean = false; + + private _editModeDefault: EN_EntityEditingStates = BaseEntityWrapper.EN_ViewMode; + public get editModeDefault(): EN_EntityEditingStates { + return this._editModeDefault; + } + public set editModeDefault(value: EN_EntityEditingStates) { + if (value !== null && value !== undefined) { + this._editModeDefault = value; + this.resetEditMode(); + } + } + + private _lastLoadedEntityId: number = 0; + private _editMode: EN_EntityEditingStates = this.editModeDefault; + public get editMode(): EN_EntityEditingStates { + return this._editMode; + } + public set editMode(newState: EN_EntityEditingStates) { + if (this.editMode === newState) return; + setTimeout(() => { + this.editModeDirectly = newState; + this.entityWasChanged = false; // to avoid changed state imedeately after going into edit mode (eable/disable buttons trigger form change event too) + if (this.inNotViewMode) this.setFocus4Form(!this.detailFormHTMLId ? 'form_' + this.entity.typeName : this.detailFormHTMLId); + }, 0); //timeout to avoid "change after checked" warning + } + + public set editModeDirectly(newState: EN_EntityEditingStates) { + this._editMode = newState; + this.appLogsService.dlog('--- Editmode', this.entity.typeName + ': ' + this.entityId + ' == ' + newState); + } + + get entitytitle(): string { + const title = this.entity?.entitytitle; + return this.translate.translateString(title); + } + + public canNew: boolean = true; + public canEdit: boolean = true; + public canCancel: boolean = true; + public canDelete: boolean = true; + public dontLoadEntity: boolean = false; + public dontCheckSaveButton: boolean = false; + public dontUpdateEntityDirectly: boolean = false; + public dontInsertEntityDirectly: boolean = false; + + public detailItems: BaseEntityDetailList = new BaseEntityDetailList(); + + private _wasChanged: boolean = false; + private delayedEditsubscription: Subscription; + protected translate: HenselTranslateService; + private loginSubscriptionSave: Subscription; + private loginSubscriptionLoad: Subscription; + + protected appLogsService: AppLogsService; + protected repositoryService: RepositoryService; + + constructor( + protected TEntity: new (source?: BaseEntity) => T, + defaultEditMode?: EN_EntityEditingStates, + appLogsService?: AppLogsService, + repositoryService?: RepositoryService, + ) // + { + this.appLogsService = appLogsService ?? inject(AppLogsService); + this.repositoryService = repositoryService ?? inject(RepositoryService); + this.translate = this.appLogsService.translate; + + if (defaultEditMode !== null && defaultEditMode !== undefined) { + this._editModeDefault = defaultEditMode; + this._editMode = defaultEditMode; + } + + setTimeout(() => { this.entityWasChanged = false; }, 0); //to avoid the changed was set during the initial binding + this._entity = new TEntity(); + } + + public get isNew(): boolean { + return !this.entity || ( + this.entity.entityId === 0 /* because of if this.dontInsertEntityDirectly it can be <0*/ + || this.entity.insertWithIds() && this.entity.entityId < 0 /* or if for insert Id is set explicitely */ + ); + } + + public get inViewMode(): boolean { return this.editModeDefault !== BaseEntityWrapper.EN_ViewMode && !this.inNewMode || this.editMode === BaseEntityWrapper.EN_ViewMode; } + public get inNotViewMode(): boolean { return this.editMode === BaseEntityWrapper.EN_EditMode || this.editMode === BaseEntityWrapper.EN_KeyEditMode || this.editMode === BaseEntityWrapper.EN_NewMode; } + public get inNewKeyEditMode(): boolean { return this.editMode === BaseEntityWrapper.EN_KeyEditMode || this.editMode === BaseEntityWrapper.EN_NewMode; } + public get inNewEditMode(): boolean { return this.editMode === BaseEntityWrapper.EN_EditMode || this.editMode === BaseEntityWrapper.EN_NewMode; } + public get inEditMode(): boolean { return this.editMode === BaseEntityWrapper.EN_EditMode; } + public get inNewMode(): boolean { return this.editMode === BaseEntityWrapper.EN_NewMode; } + public get inKeyEditMode(): boolean { return this.editMode === BaseEntityWrapper.EN_KeyEditMode; } + public onFormChange: (val: any) => boolean; + + public resetEditMode() { + if (this.hierarchyLevel === 0 && this.isNew && this.editModeDefault !== EN_EntityEditingStates.View) return; //this logic is used only for entity wrapper 1st level + this.editMode = this.editModeDefault; + } + + public set entityWasLoaded(finished: boolean) { + this.entityIsLoading = !finished; + if (finished) this.entityWasChanged = false; + } + + // we set false imedeatelely, but true only after entityChangeDelay=def 500 ms were gone, since the last call to set + public set entityWasChanged(changed: boolean) { + if (this.entity) { + this.appLogsService.dlog('--- ' + this.entity.typeName + ' CHANGED: ', changed, ' after ', now() - this._lastChangedTime); + if (!changed || (now() - this._lastChangedTime > this.delayEntityChange)) { + setTimeout(() => this.entity.entityChanged = changed); //to avoid change after check error, because is used in interface onSaveEnabled + this._wasChanged = changed; //to return properly value from this.changed() + } + this._lastChangedTime = now(); + } + } + + public get entityWasChanged() { + return this.entity?.entityChanged || this.detailItems.changed() + || (!!this.isEntityChangedCallBack && this.isEntityChangedCallBack(this.entity)); + } + + public get isValidInput() { + return this.entity?.isValidInput() && this.detailItems.isValidInput() + && (!this.isEntityValidCallBack || this.isEntityValidCallBack(this.entity)); + } + + + public get detailForm(): NgForm { + return this._detailForm; + } + + public set detailForm(value: NgForm) { + this._detailForm = value; + //connect input fields of the detail form with entity change method automatically + if (!this._detailForm) return; + this.detailForm.valueChanges.subscribe((val: any) => this.doFormChange(val)); + this.updateRequired(); + } + + + doFormChange = (val: any) => { + if (!this.onFormChange || !this.onFormChange(val)) { + this.changed(val); + } + } + + + public updateRequired() { + if (!this.detailForm) return; + // to show markup (read) for required fields imediately after a form was initialised, + // but not only after the field was focused + setTimeout(() => { if (this.detailForm?.control) this.detailForm.control.markAllAsTouched(); }); + } + + get entity() { return this._entity; } + + + //just connects UI wrapper with a given enity object + set entity(ent: T | null) { + this.entityWasLoaded = false; + this._entity = ent; + this.entityWasLoaded = true; + } + + //load an entity object on its Id and connects UI wrapper with it + set entityId(id: number) { + // tslint:disable-next-line: curly + if ((!this.entity) || (!this.entity.isRealObject())) { + this._entity = new this.TEntity(); + } + + this.load(id); + } + + get entityId() { return this.entity ? this.entity.entityId : null; } + + + private unsubscribe(subscr: Subscription) { + subscr?.unsubscribe(); + subscr = null; + } + + + public load(entityId: number, _loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) { + this.entity.entityId = entityId; + + if (!this.loginSubscriptionLoad && this.hierarchyLevel === 0) { + this.loginSubscriptionLoad = this.repositoryService.authService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { // try one time more + this.load(entityId, _loadedCallBack, _errorCallBack, _completeCallBack); + } else this.unsubscribe(this.loginSubscriptionLoad); + + }); + } else { + if (this.loginSubscriptionLoad) this.unsubscribe(this.loginSubscriptionLoad); // try only one time more + } + + const loadedDetails$: Subject[] = [new Subject()]; + // if (!_loadedCallBack) _loadedCallBack = this.loadedCallBack; + // if (!_errorCallBack) _errorCallBack = this.errorCallBack; + // if (!_completeCallBack) _completeCallBack = this.completeCallBack; + + this.detailItems.prepareObservables(loadedDetails$, mdLOAD); + + forkJoin(loadedDetails$).subscribe(() => { + + this.entityWasLoaded = true; + this.resetEditMode(); + if (this.hierarchyLevel === 0) { + this.appLogsService.dlog('------- master loaded <' + this.entity.typeName + ' ' + this.entity.entityId + '>'); + this.unsubscribe(this.loginSubscriptionLoad); + } + if (_loadedCallBack) _loadedCallBack(this.entity); + if (this.loadedCallBack) this.loadedCallBack(this.entity); + if (this.entityId) { // do check because for empty list focusedEntityShadowed.entityId is set to 0, to clear details + this.entityList?.updateListItem(this.entity); //to update entity if it was chaged in loadedCallBack + } + }, (error: ResultSubject) => { + this.cancelDelayedEditsubscription(); + this.entityIsLoading = false; + if (this.hierarchyLevel === 0) this.appLogsService.error('---!!! master error <' + this.entity.typeName + ' ' + this.entity.entityId + '>:', { error }); + const errorMsg = getErrorMessageAsText(error); + if (errorMsg !== cnst_CANCEL_ERROR) { + if (!this.dontShowErrors) this.errorMessageBox(this.translate.instant('core.error.loading', { value: this.entitytitle }), errorMsg); + if (_errorCallBack) _errorCallBack(error); + if (this.errorCallBack) this.errorCallBack(error); + this.unsubscribe(this.loginSubscriptionLoad); //relogin is not executed - don't need subscription + } + if (_completeCallBack) _completeCallBack(); + if (this.completeCallBack) this.completeCallBack(); + }, () => { + this.entityWasLoaded = true; //important for new mode, because callback loaded in this case is not called + + if (this.hierarchyLevel === 0) this.appLogsService.dlog('------- master loaded completed <' + this.entity.typeName + ' ' + this.entity.entityId + '>'); + if (_completeCallBack) _completeCallBack(); + if (this.completeCallBack) this.completeCallBack(); + }); + + //load entity itself + this.entityWasLoaded = false; + if (this.dontLoadEntity && this.entityList) { + if (this.entityList.items.length > 0 && this.entityId) {//do check because for empty list focusedEntityShadowed.entityId is set to 0, to clear details + this.entity.assign(this.entityList.getItemById(this.entity.entityId)); + + loadedDetails$[0].next(); + //load detail lists + this.detailItems.load(this, loadedDetails$, 1); + loadedDetails$[0].complete(); + } else { + this.clear(); + loadedDetails$[0].complete(); + } + } else { + this.entity.load(this.repositoryService, (entity) => { + this.synchroniseEntityList(EN_SynchronizeListAfter.Load); + loadedDetails$[0].next(); + + //load detail lists, must be in call back + //this.detailItems.load(this, loadedDetails$, 1); + }, (error: any) => { + if (this.hierarchyLevel > 0) { + loadedDetails$[0].next(); + loadedDetails$[0].complete(); //w/o complete is passed no next + //error in details does not mean error in main + } else loadedDetails$[0].error(error); + // this.entityWasLoaded = false; + }, () => { + //load detail lists, must be in call back + this.detailItems.load(this, loadedDetails$, 1); + loadedDetails$[0].complete(); + } + ); + } + } + + + public changed(event?: any): boolean { + this.entityWasChanged = true; + return this._wasChanged; //can be the case that set it to true has no affect, because of delay after it was set to false + } + + isFormValidInput() { + return ((this.onCheckFormValidInput && this.onCheckFormValidInput(this.detailForm)) || (!this.detailForm || (this.detailForm && !this.detailForm.invalid + /* valid was changed against !invalid, because valid = status==VALID, but status for disabled is DISABLED, i.e. disabled -> !valid*/ + ))) && this.isValidInput; + } + + public enabledSaveButton() { + return this.isFormValidInput() && this.inNotViewMode && (this.entityWasChanged || this.dontCheckSaveButton); + } + public enabledDeleteButton() { return this.canDelete && (!this.isNew || this.dontUpdateEntityDirectly) && !this.entityIsLoading && this.inViewMode; } + public enabledNewButton() { return this.canNew && !this.entityIsLoading && this.inViewMode /*&& !this.isNew && !this.entityWasChanged */; } + public enabledEditButton() { return this.canEdit && (!this.isNew || this.dontInsertEntityDirectly) && !this.entityIsLoading && this.inViewMode; } + public enabledCancelButton() { + return this.canCancel + && ( + this.editModeDefault === BaseEntityWrapper.EN_ViewMode && this.inNotViewMode || + this.editModeDefault !== BaseEntityWrapper.EN_ViewMode && ( + this.inEditMode && this.entityWasChanged || + this.inNewMode && (!this.entityList || this.entityList.focusedItem || //if there is a binded list with the selected item, then load it with cancel + this.entityWasChanged) //or clear if there was changed something + ) + ) + ///*(this.isNew || this.entityWasChanged || this.editModeDefault === BaseEntityWrapper.EN_ViewMode) && */ this.inNotViewMode + && !this.entityIsLoading; + } + public enabledCopyButton() { return this.canNew && (!this.isNew || this.dontInsertEntityDirectly) && !this.entityIsLoading && this.inViewMode; } + + + public async saveExcludingFields(excludeFields: string, _loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void, useSuffixInsteadEntityId?: string) { + this.entity.excludeFieldFromUpdate(excludeFields); + this.save(_loadedCallBack, _errorCallBack + , () => { + this.entity.includeFieldForUpdate(excludeFields); + if (_completeCallBack) _completeCallBack(); + } + , useSuffixInsteadEntityId + ); + } + + + public async saveAsync(): Promise { + return new Promise((resolve, reject) => this.save(null, () => resolve(false), () => resolve(true))); + } + + + public async saveAnywayAsync(): Promise { + return new Promise((resolve, reject) => this.saveAnyway(null, () => resolve(false), () => resolve(true))); + } + + + public saveAnyway(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void, useSuffixInsteadEntityId?: string) { + if (!this.entity) return; + this.save(_loadedCallBack, _errorCallBack, _completeCallBack, useSuffixInsteadEntityId, true); + } + + + public async save(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void, useSuffixInsteadEntityId?: string, dontCheckSaveButton: boolean = false) { + + if (this.entity && (dontCheckSaveButton || this.enabledSaveButton())) { + const savedDetails$: Subject[] = [new Subject()]; + const _isNew = this.isNew; + + let resBeforeSaveCallBack: EN_EntityBeforeSaveCallBackResults = EN_EntityBeforeSaveCallBackResults.Ok_Continue; + // tslint:disable-next-line: no-bitwise + const doBreak: boolean = this.beforeSaveCallBack && ((resBeforeSaveCallBack = await this.beforeSaveCallBack(this.entity)) & EN_EntityBeforeSaveCallBackResults.Ok_Break) !== 0; + if (!doBreak) { //saves main base entity only after all details entities/entity lists are successfuly saved + this.detailItems.prepareObservables4SaveAutonome(savedDetails$, mdSAVE, () => this.saveEntity(savedDetails$[0], useSuffixInsteadEntityId)); + } + + + forkJoin(savedDetails$).subscribe( + () => { + this.unsubscribe(this.loginSubscriptionSave); + this.resetEditMode(); + if (!this.synchroniseEntityList(_isNew ? EN_SynchronizeListAfter.New : EN_SynchronizeListAfter.Save)) this._cancel(); //don't change order here!!! + if (_loadedCallBack) _loadedCallBack(this.entity); + this.appLogsService.dlog('------- master saved <' + this.entity.typeName + ' ' + this.entity.entityId + '>'); + this.entityList?.updateListItem(this.entity); //to update entity if it was chaged in loadedCallBack + this.entityWasChanged = false; + }, (error: ResultSubject) => { + this.entityWasChanged = true; + this.appLogsService.error('---!!! master error <' + this.entity.typeName + '>:', { error }); + const errorMsg = getErrorMessageAsText(error); + if (errorMsg !== cnst_CANCEL_ERROR) { + if (!this.dontShowErrors) this.errorMessageBox(this.translate.instant('core.error.saving', { value: this.entitytitle }), errorMsg); + if (_errorCallBack) _errorCallBack(error); + this.unsubscribe(this.loginSubscriptionSave); //relogin is not executed - don't need subscription + } + if (_completeCallBack) _completeCallBack(); + }, () => { + this.appLogsService.dlog('------- master saved completed <' + this.entity.typeName + ' ' + this.entity.entityId + '>'); + if (_completeCallBack) _completeCallBack(); + } + ); + + if (doBreak) { + // tslint:disable-next-line: no-bitwise + const resOk = (resBeforeSaveCallBack & EN_EntityBeforeSaveCallBackResults.Error_Continue) === 0; + if (resOk) { + savedDetails$[0].next(); + savedDetails$[0].complete(); + } else savedDetails$[0].error({ errMsg: cnst_CANCEL_ERROR } as ResultSubject); //raise error callback, but without message box + return; + } + + if (!this.loginSubscriptionSave && this.hierarchyLevel === 0) { + this.loginSubscriptionSave = this.repositoryService.authService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { // try one time more + this.save(_loadedCallBack, _errorCallBack, _completeCallBack, useSuffixInsteadEntityId); + } else this.unsubscribe(this.loginSubscriptionSave); + }); + } else { + if (this.loginSubscriptionSave) this.unsubscribe(this.loginSubscriptionSave); // try only one time more + } + + //if we have details and a new main entity, we should insert it at first, get id, then save all details, and then update main entity + const mainObservable$ = savedDetails$[0]; + if (!this.detailItems.isEmpty4Save && this.isNew) { + const mainInserted$ = new Subject(); + this.saveEntity(mainInserted$, useSuffixInsteadEntityId); + mainInserted$.subscribe({ + next: () => { + //save detail Items + this.detailItems.batchSave(this); + }, error: (error: any) => { + mainObservable$.error(error); + } + }); + } else { + //save detail Items + this.detailItems.batchSave(this); + + //save entity itself - no details objects + if (this.detailItems.isEmpty4Save) this.saveEntity(mainObservable$, useSuffixInsteadEntityId); + } + + } else { //to process sub details, when main detail entity is saved, it must call _completeCallBack() anyway + if ((this.hierarchyLevel > 0) && _loadedCallBack) _loadedCallBack(this.entity); + this.appLogsService.dlog('!! completed saving main' + this.entity.typeName); + if (_completeCallBack) _completeCallBack(); + this.resetEditMode(); + } + } + + + private saveEntity(savedDetails$: Subject, useSuffixInsteadEntityId: string) { + if (!useSuffixInsteadEntityId && this.entityList && (this.isNew && this.dontInsertEntityDirectly || !this.isNew && this.dontUpdateEntityDirectly)) { + // -- we don't save details data directly, but save the connected list and data should be saved with this.entityList.save, entityId will be the minimal negative + if (this.entity.entityId === 0) { + this.entity.entityId = this.entityList.items.reduce((min: number, entity: BaseEntity) => min < entity.entityId ? min : entity.entityId, 0) - 1; + } + this.entityWasChanged = true; + this.appLogsService.dlog('!! next saving main: ' + this.entity.typeName); + savedDetails$.next(); + this.appLogsService.dlog('!! completed saving main: ' + this.entity.typeName); + savedDetails$.complete(); + } else { + this.entity.save(this.repositoryService, + (entity) => { + // this.synchroniseEntityList(); //!!! check + // this.entityWasChanged = false; + // if (loadedcallback) loadedcallback(entity); + this.appLogsService.dlog('!! next saving main: ' + this.entity.typeName); + savedDetails$.next(); + }, + (error: any) => savedDetails$.error(error), + () => { + this.appLogsService.dlog('!! completed saving main: ' + this.entity.typeName); + savedDetails$.complete(); + }, + useSuffixInsteadEntityId + ); + } + } + + + public synchroniseEntityList(calledAfterSave: EN_SynchronizeListAfter, entityList?: BaseEntityListWrapper): boolean { + if (!entityList) entityList = this.entityList; + if (!entityList + || (calledAfterSave === EN_SynchronizeListAfter.New || calledAfterSave === EN_SynchronizeListAfter.Save) && !this.syncEntityListWhenSave + || calledAfterSave === EN_SynchronizeListAfter.Load && !this.syncEntityListWhenLoad) { + return false; + } + if (calledAfterSave !== EN_SynchronizeListAfter.Load && entityList.reloadAfterItemUpdate) { + entityList.load(); + entityList.focusedItemId = this.entity.entityId; + } else entityList.updateListItem(this.entity, this.indexInList4New, calledAfterSave === EN_SynchronizeListAfter.New); + return true; + } + + + public clear(useNull: boolean = false) { + this.entity.clear(useNull); + this.detailItems.clear(useNull); + } + + + public cancelWithSave(_saveCallBack: () => void, _loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack) { + this.cancel(_loadedCallBack, _errorCallBack, null, null, _saveCallBack); + } + + + public cancel(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void, useSuffixInsteadEntityId?: string, _saveCallBack?: () => void) { + if (!this.confirmationsOn || !this.enabledSaveButton() || !this.entityWasChanged) { //only if something was changed and form is valid + setTimeout(() => this._cancel(_loadedCallBack, _errorCallBack)); + } else { + this.confirmMessageBoxYesNoCancel( + // 'Bearbeitungsabbruch von ' + this.entitytitle, + this.translate.instant('core.msgbox.header.cancel', { value: this.entitytitle }), + // `${this.entitytitle} wurde geändert. Sollen Änderungen gespeichert werden?`, + this.translate.instant('core.msgbox.body.cancel', { value: this.entitytitle }), + + () => { + if (_saveCallBack) _saveCallBack(); + else this.save(_loadedCallBack, _errorCallBack, _completeCallBack, useSuffixInsteadEntityId); + }, + () => { + if (_loadedCallBack) _loadedCallBack(this.entity); //to call close for popupdialogs before canceling starts + this._cancel(null, _errorCallBack); + } + ); + } + } + + + public _cancel(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack): boolean { + // if (!this.enabledCancelButton()) return false; //cancel must work anyway, even if viemode + if (this.entityWasChanged || this.isNew) { + + + //this.detailItems.cancel(); + if (this.isNew) { + /*if (this.entityList && this.entityList.focusedItemId) { + this.entityId = this.entityList.focusedItemId; + } else*/ + if (this._lastLoadedEntityId) this.entityId = this._lastLoadedEntityId; + else { + this.detailItems.cancel(); + this.entity.clear(); + if (this.hierarchyLevel === 0 && this.editModeDefault !== EN_EntityEditingStates.View) this.new(); //if always in edit mode and there is no items in the list the mode stays in new mode + } + } else if (this.entity) { + this.reloadAnyway((entity: BaseEntity) => { + this.resetEditMode(); + if (_loadedCallBack) _loadedCallBack(this.entity); + }, _errorCallBack); + return true; + } + } + this.resetEditMode(); + if (_loadedCallBack) _loadedCallBack(this.entity); + return true; + } + + + public async deleteAsync(): Promise { + return new Promise((resolve, reject) => this.save(() => resolve(true), () => resolve(false) /* complete is called anyway */)); + } + + + public async delete(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack) { + if (!this.confirmationsOn) return this._delete(_loadedCallBack, _errorCallBack); + this.confirmMessageBoxYesNo( + // 'Löschen von ' + this.entitytitle, + this.translate.instant('core.msgbox.header.delete', { value: this.entitytitle }), + // `Soll ${this.entitytitle} gelöscht werden?`, + this.translate.instant('core.msgbox.body.delete', { value: this.entitytitle }), + () => this._delete(_loadedCallBack, _errorCallBack), 1); + } + + private async _delete(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack) { + if (this.entity && this.enabledDeleteButton()) { + let resbeforeDeleteCallBack: EN_EntityBeforeSaveCallBackResults = EN_EntityBeforeSaveCallBackResults.Ok_Continue; + // tslint:disable-next-line: no-bitwise + if (this.beforeDeleteCallBack && ((resbeforeDeleteCallBack = await this.beforeDeleteCallBack(this.entity)) & EN_EntityBeforeSaveCallBackResults.Ok_Break) !== 0) { + // tslint:disable-next-line: no-bitwise + if ((resbeforeDeleteCallBack & EN_EntityBeforeSaveCallBackResults.Error_Continue) === 0) { + if (_loadedCallBack) _loadedCallBack(this.entity); + } else { + if (_errorCallBack) _errorCallBack({ errMsg: cnst_CANCEL_ERROR } as ResultSubject); + } + return; + } + + let loginSubscription: Subscription; + if (this.hierarchyLevel === 0) { + loginSubscription = this.repositoryService.authService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { // try one time more + loginSubscription?.unsubscribe(); + this._delete(_loadedCallBack, _errorCallBack); + } + }); + } + + + if (this.dontUpdateEntityDirectly) { + this.resetEditMode(); + if (this.entityList) this.entityList.deleteListItem(this.entity, true); + } else { + return this.entity.delete(this.repositoryService, + (entity) => { + this.resetEditMode(); + if (this.entityList) this.entityList.deleteListItem(this.entity, false); + if (_loadedCallBack) _loadedCallBack(entity); + } + , (error: ResultSubject) => { + this.appLogsService.error('---!!! delete error <' + this.entity.typeName + '>:', { error }); + const errorMsg = getErrorMessageAsText(error); + if (!this.dontShowErrors && errorMsg !== cnst_CANCEL_ERROR) { + this.errorMessageBox(this.translate.instant('core.error.deleting', { value: this.entitytitle }), errorMsg); + } + if (errorMsg !== cnst_CANCEL_ERROR && _errorCallBack) _errorCallBack(error); + }); + } + } else { + if (_loadedCallBack) _loadedCallBack(this.entity); + } + } + + + public editKey(setEditModedirectly: boolean = false, callBack?: BaseEntityCallBack): T { + return this._edit(BaseEntityWrapper.EN_KeyEditMode, setEditModedirectly, callBack); + } + + + + public edit(setEditModedirectly: boolean = false, callBack?: BaseEntityCallBack): T { + return this._edit(BaseEntityWrapper.EN_EditMode, setEditModedirectly, callBack); + } + + + public _edit(editMode: EN_EntityEditingStates, setEditModedirectly: boolean = false, callBack?: BaseEntityCallBack): T { + if (this.enabledEditButton()) { + this.appLogsService.dlog('--- Edit, since last loading expired ms', now() - (this.entity.lastLoaded || 0)); + if (this.loadedDataExpiresInMs && ((now() - (this.entity.lastLoaded || 0)) > this.loadedDataExpiresInMs)) { + this.reload(() => this._setEditMode(setEditModedirectly, editMode, callBack)); + } else this._setEditMode(setEditModedirectly, editMode, callBack); + return this.entity; + } else return null; + } + + + private _setEditMode(setEditModedirectly: boolean, editMode: EN_EntityEditingStates, callBack: BaseEntityCallBack) { + if (setEditModedirectly) { + this.editModeDirectly = editMode; + if (callBack) callBack(this.entity); + } else { + this.editMode = editMode; + setTimeout(() => { + if (callBack) callBack(this.entity); + }, this.delaySetEditModeCallback); + } + } + + + public delayedEdit(entityId2Edit: number, editFn?: () => any) { + if (entityId2Edit === this.entityId) { + if (editFn) editFn(); + else this.edit(); + } else { + if (!this.delayedEditsubscription) { + this.delayedEditsubscription = this.entityLoaded$.subscribe(() => { + this.cancelDelayedEditsubscription(); + if (editFn) editFn(); + else this.edit(); + }); + } + } + } + + + private cancelDelayedEditsubscription() { + this.delayedEditsubscription?.unsubscribe(); + this.delayedEditsubscription = null; + } + + + private setfocus4ElementsOf(qualifiedName: keyof HTMLElementTagNameMap, frm: HTMLElement): boolean { + const elements = frm?.getElementsByTagName(qualifiedName); + let focusElement = null; + if (elements) { + for (let inx = 0; inx < elements.length; inx++) { + const el = elements[inx]; + if (!(el).disabled && !el.hidden && el.autofocus /*attributes.getNamedItem('autofocus')*/) { + if (!focusElement) focusElement = el; + if ((el).required && !(el).value) { + focusElement = el; + break; + } + } + } + setTimeout(() => { + focusElement?.focus(); + }, 300); + } + return !!focusElement; + } + + + public setFocus4Form(formId: string) { + setTimeout(() => { + const frm = document.getElementById(formId); + if (!this.setfocus4ElementsOf('input', frm)) this.setfocus4ElementsOf('button', frm); + }); + } + + + private _NewCopy(copy: boolean): T { + if (this.editMode === this.editModeDefault || this.editMode === BaseEntityWrapper.EN_NewMode) //we use new() to call everytime before new + { + this._lastLoadedEntityId = this.entityId; + + this.editMode = BaseEntityWrapper.EN_NewMode; + if (!copy) this.entityId = 0; + if (this.beforeNewCallBack) this.beforeNewCallBack(this.entity); + if (copy) this.entity.entityId = 0; + + if (copy) setTimeout(() => this.entity.entityChanged = true, 0); + + this.detailItems.new(); + this.updateRequired(); + return this.entity; + } else return null; + } + + + public new(): T { return this._NewCopy(false); } + public copy(): T { return this._NewCopy(true); } + + public loadDetails(onlyDetailItem: BaseEntityListWrapper | BaseEntityWrapper) { + if (this.detailItems) this.detailItems.load(this, null, 0, onlyDetailItem); + } + + + public reloadAnyway(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) { + this.entity.lastLoaded = 0; //to reload independend from was loaded the last time + this.reload(_loadedCallBack, _errorCallBack, _completeCallBack); + } + + + public reload(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) { + const ignoreInterval = this.delayToReloadedEntity; + if ((now() - (this.entity.lastLoaded || 0)) > ignoreInterval) { + this.appLogsService.dlog(`--- Reload for ${this.entity.entitytitle} is executed: since last loading expired ${now() - (this.entity.lastLoaded || 0)} > ${ignoreInterval}`); + this.load(this.entityId, _loadedCallBack, _errorCallBack, _completeCallBack); //load new + } else { + this.appLogsService.dlog(`--- Reload is ignored: since last loading expired ${now() - (this.entity.lastLoaded || 0)} <= ${ignoreInterval}`); + this.entityWasLoaded = true; + if (_loadedCallBack) _loadedCallBack(this.entity); + if (_completeCallBack) _completeCallBack(); + } + } + + + public hardReload(_loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) { + const prevDontLoadEntity = this.dontLoadEntity; + this.dontLoadEntity = false; + this.load(this.entityId, (entity?: BaseEntity) => { + this.dontLoadEntity = prevDontLoadEntity; + if (_loadedCallBack) _loadedCallBack(entity); + }, _errorCallBack, _completeCallBack); //load new + } + + + public shortcutsHandler(event: KeyboardEvent, + saveCallBack: () => void = null, _cancelCallBack: () => void = null, _newCallBack: () => void = null, _editCallBack: () => void = null) { + if (!this.keyDownListenerStopped) { + if (event.ctrlKey && !event.shiftKey && !event.altKey) { + // tslint:disable-next-line: deprecation + switch (event.which) { + case keycode.E: // Ctrl + e + event.stopPropagation(); + if (_editCallBack) _editCallBack(); + else this.edit(); + return false; //processed + case keycode.S: // Ctrl + s + event.stopPropagation(); + if (saveCallBack) saveCallBack(); + else this.save(); + return false; //processed + case keycode.N: // Ctrl + n + event.stopPropagation(); + if (_newCallBack) _newCallBack(); + else this.new(); + return false; //processed + } + } else { + if (!event.ctrlKey && !event.shiftKey && !event.altKey) { + // tslint:disable-next-line: deprecation + switch (event.which) { + case keycode.ESCAPE: // ESC + event.stopPropagation(); + if (_cancelCallBack) _cancelCallBack(); + else this.cancel(); + return false; //processed event.preventDefault()-the same, event.stopPropagation(); -> globally + } + } + } + } + return true; //default processing + } + + + showMessageBox(messageBoxData: IMessageBoxData): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.showMessageBox(messageBoxData, () => this.keyDownListenerStopped = false); + } + + informationMessageBox(caption: string, message: string, callBack?: () => void): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.informationMessageBox(caption, message, () => { this.keyDownListenerStopped = false; if (callBack) callBack(); }); + } + + errorMessageBox(caption: string, message: string, okCallBack?: () => void): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.errorMessageBox(caption, message, () => { this.keyDownListenerStopped = false; if (okCallBack) okCallBack(); }); + } + + warningMessageBox(caption: string, message: string, okCallBack?: () => void): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.warningMessageBox(caption, message, () => { this.keyDownListenerStopped = false; if (okCallBack) okCallBack(); }); + } + + confirmMessageBoxYesNo(caption: string, message: string, yesCallBack: () => void, defaultButtonInx: number = 0): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.confirmMessageBoxYesNo(caption, message, yesCallBack, () => this.keyDownListenerStopped = false, defaultButtonInx); + } + + confirmMessageBoxYesNoCancel(caption: string, message: string, yesCallBack: () => void, noCallBack: () => void, defaultButtonInx: number = 0): MatDialogRef { + this.keyDownListenerStopped = true; + return this.appLogsService.confirmMessageBoxYesNoCancel(caption, message, yesCallBack, noCallBack, () => this.keyDownListenerStopped = false, defaultButtonInx); + } + + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitydetaillist.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitydetaillist.ts new file mode 100644 index 0000000..01eb5e7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitydetaillist.ts @@ -0,0 +1,265 @@ +import { BaseEntity, ErrorCallBack } from '../generics/baseentity'; +import { BaseEntityListWrapper } from './baseentitylist.wrapper'; +import { BaseEntityWrapper } from './baseentity.wrapper'; +import { forkJoin, Subject } from 'rxjs'; +import { EN_EntityEditingStates } from '../../consts'; + +export const mdLOAD: number = 1; +export const mdSAVE: number = 2; + +export interface BaseEntityDetail { + baseEntityList?: BaseEntityListWrapper; + baseEntityWrapper?: BaseEntityWrapper; + callBack?: (entity: BaseEntity[] | BaseEntity) => void; + errorCallBack?: ErrorCallBack; + completeCallBack?: () => void; + filterKeyField: string; + masterField4Filter: string; + mode: number; +} + + +export class BaseEntityDetailList { + public items: BaseEntityDetail[] = []; + + public observList$: Subject[] = []; + + public get isEmpty(): boolean { + return this.items.length === 0; + } + + + public get isEmpty4Save(): boolean { + return this.observList$.length === 0; + + } + + + private _register(_mode: number, _baseEntityList: BaseEntityListWrapper, _baseEntityWrapper: BaseEntityWrapper, _filterKeyField: string | string[], + _callBack?: (entity: BaseEntity[] | BaseEntity) => void, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void): BaseEntityDetail { + + let filterKeyField: string = null; + let masterField4Filter: string = null; + if (Array.isArray(_filterKeyField)) { + filterKeyField = _filterKeyField[0]; + if (_filterKeyField.length > 1) masterField4Filter = _filterKeyField[1]; + } else filterKeyField = _filterKeyField; + const item: BaseEntityDetail = { + baseEntityList: _baseEntityList, + baseEntityWrapper: _baseEntityWrapper, + filterKeyField: filterKeyField, + masterField4Filter: masterField4Filter, + callBack: _callBack, + errorCallBack: _errorCallBack, + completeCallBack: _completeCallBack, + mode: _mode + }; + this.items.push(item); + if (_baseEntityWrapper) { + _baseEntityWrapper.hierarchyLevel++; + _baseEntityWrapper.editModeDefault = EN_EntityEditingStates.Edit; //to saving with main automatically + } + if (_baseEntityList) _baseEntityList.hierarchyLevel++; + return item; + } + + + public register(_baseEntityList: BaseEntityListWrapper, _baseEntityWrapper: BaseEntityWrapper, _filterKeyField: string | string[], + _callBack?: (entity: BaseEntity[] | BaseEntity) => void, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void): BaseEntityDetail { + return this._register(mdLOAD + mdSAVE, _baseEntityList, _baseEntityWrapper, _filterKeyField, _callBack, _errorCallBack, _completeCallBack); + } + + + public register4Load(_baseEntityList: BaseEntityListWrapper, _baseEntityWrapper: BaseEntityWrapper, _filterKeyField: string | string[], + _callBack?: (entity: BaseEntity[] | BaseEntity) => void, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void): BaseEntityDetail { + return this._register(mdLOAD, _baseEntityList, _baseEntityWrapper, _filterKeyField, _callBack, _errorCallBack, _completeCallBack); + } + + + public register4Save(_baseEntityList: BaseEntityListWrapper, _baseEntityWrapper: BaseEntityWrapper, _filterKeyField: string | string[], + _callBack?: (entity: BaseEntity[] | BaseEntity) => void, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void): BaseEntityDetail { + return this._register(mdSAVE, _baseEntityList, _baseEntityWrapper, _filterKeyField, _callBack, _errorCallBack, _completeCallBack); + } + + + public prepareObservables(observList$: Subject[], mode: number) { + this.items.forEach((item: BaseEntityDetail) => { + // tslint:disable-next-line: no-bitwise + if (item.mode & mode) observList$.push(new Subject()); + }); + } + + + public prepareObservables4SaveAutonome(_observList$: Subject[], mode: number, callBack: () => void) { + this.observList$ = []; + this.prepareObservables(this.observList$, mode); + if (this.observList$.length === 0) return; + const observListAutonome$: Subject = new Subject(); + _observList$.push(observListAutonome$); + forkJoin(this.observList$).subscribe( + () => { + // console.log('******Details next'); + if (callBack) callBack(); + observListAutonome$.next(); + }, (error: any) => observListAutonome$.error(error) + , () => { + // console.log('******Details complete'); + observListAutonome$.complete(); + } + ); + } + + + public new() { + this.items.forEach((list: BaseEntityDetail) => list.baseEntityList ? list.baseEntityList.clear() : list.baseEntityWrapper.new()); + } + + + public clear(useNull: boolean = false) { + this.items.forEach((list: BaseEntityDetail) => { + if (list.baseEntityList) list.baseEntityList.clear(); + else if (list.baseEntityWrapper.entity) list.baseEntityWrapper.entity.clear(useNull); + }); + } + + + public cancel() { + this.items.forEach((list: BaseEntityDetail) => { + if (list.baseEntityList) list.baseEntityList.clear(); + else { + list.baseEntityWrapper.resetEditMode(); + if (list.baseEntityWrapper.entity) list.baseEntityWrapper.entity.clear(); + // list.baseEntityWrapper.cancel(); + } + }); + } + + + public changed(): boolean { + return this.items.some((list: BaseEntityDetail) => list.baseEntityList ? list.baseEntityList.changed : list.baseEntityWrapper.entityWasChanged); + } + + + public isValidInput(): boolean { + return this.items.every((list: BaseEntityDetail) => list.baseEntityList ? list.baseEntityList.isValidInput : list.baseEntityWrapper.isValidInput); + } + + + public load(masterEntityWrapper: BaseEntityWrapper, observList$?: Subject[], baseIndex: number = 0, onlyDetailItem: BaseEntityListWrapper | BaseEntityWrapper = null) { + // tslint:disable-next-line: no-bitwise + this.items.filter(x => (x.mode & mdLOAD)).forEach((item: BaseEntityDetail, index: number) => { + const indexObservable = index + baseIndex; + // observList$.push(new Subject()); + if (masterEntityWrapper.entityId) { + if (item.baseEntityList && (!onlyDetailItem || onlyDetailItem === item.baseEntityList)) { + if (item.filterKeyField && item.baseEntityList.filter) item.baseEntityList.filter[item.filterKeyField] = masterEntityWrapper.entity[item.masterField4Filter ?? 'entityId']; + item.baseEntityList.load( + (entityList: BaseEntity[]) => { + console.log('!! next load detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + if (item.callBack) item.callBack(entityList); + if (observList$) observList$[indexObservable].next(); + }, (error: any) => { + if (item.errorCallBack) item.errorCallBack(error); + if (observList$) observList$[indexObservable].error(error); + }, () => { + console.log('!! complete load detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + if (item.completeCallBack) item.completeCallBack(); + if (observList$) observList$[indexObservable].complete(); + } + ); + } else if (item.baseEntityWrapper && (!onlyDetailItem || onlyDetailItem === item.baseEntityWrapper)) { + item.baseEntityWrapper.load(masterEntityWrapper.entity[item.filterKeyField ?? 'entityId'], + (entity: BaseEntity) => { + console.log('!! next load detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + if (item.callBack) item.callBack(entity); + if (observList$) observList$[indexObservable].next(); + }, (error: any) => { + if (item.errorCallBack) item.errorCallBack(error); + if (observList$) observList$[indexObservable].error(error); + }, () => { + console.log('!! complete load detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + if (item.completeCallBack) item.completeCallBack(); + if (observList$) observList$[indexObservable].complete(); + } + ); + } + } else { + if (item.baseEntityList) item.baseEntityList.clear(); + else item.baseEntityWrapper.new(); + if (observList$) observList$[indexObservable].next(); + if (observList$) observList$[indexObservable].complete(); + } + }); + } + + + private itemSave(masterEntityWrapper: BaseEntityWrapper, item: BaseEntityDetail, callback: () => void, errorcallback: (error: any) => void, completecallback: () => void) { + if (item.baseEntityList) { + item.baseEntityList.items.forEach(it => { + if (it.isNew()) it[item.filterKeyField] = masterEntityWrapper.entity[item.masterField4Filter ?? 'entityId']; + }); + item.baseEntityList.save( + () => { + if (item.callBack) item.callBack(item.baseEntityList.items); + if (callback) callback(); + }, + (error: any) => { + if (item.errorCallBack) item.errorCallBack(item.baseEntityList.items); + if (errorcallback) errorcallback(error); + }, + () => { + if (item.completeCallBack) item.completeCallBack(); + if (completecallback) completecallback(); + } + ); + } else { + if (item.baseEntityWrapper.isNew) item.baseEntityWrapper.entity[item.filterKeyField] = masterEntityWrapper.entity[item.masterField4Filter ?? 'entityId']; + item.baseEntityWrapper.save( + () => { + if (item.callBack) item.callBack(item.baseEntityWrapper.entity); + if (callback) callback(); + }, + (error: any) => { + if (item.errorCallBack) item.errorCallBack(item.baseEntityWrapper.entity); + if (errorcallback) errorcallback(error); + }, + () => { + if (item.completeCallBack) item.completeCallBack(); + if (completecallback) completecallback(); + } + ); + } + } + + + public batchSave(masterEntityWrapper: BaseEntityWrapper) { + this.save(masterEntityWrapper, this.observList$, 0); + } + + + public save(masterEntityWrapper: BaseEntityWrapper, observList$: Subject[], baseIndex: number) { + // tslint:disable-next-line: no-bitwise + this.items.filter(x => x.mode & mdSAVE).forEach((item: BaseEntityDetail, index: number) => { + const indexObservable = index + baseIndex; + if (masterEntityWrapper.entityId) { //details list can be saved only if id>0 + this.itemSave(masterEntityWrapper, item, + () => { + console.log('!! next save detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + observList$[indexObservable].next(); + }, + (error: any) => observList$[indexObservable].error(error), + () => { + console.log('!! complete save detail No.' + indexObservable + ': ' + (item.baseEntityList ? item.baseEntityList.translate.instant(item.baseEntityList._listName) : item.baseEntityWrapper.entity.typeName)); + observList$[indexObservable].complete(); + } + ); + } else { + if (item.baseEntityList) item.baseEntityList.clear(); + else item.baseEntityWrapper.new(); + observList$[indexObservable].next(); + observList$[indexObservable].complete(); + } + }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentityfilter.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentityfilter.ts new file mode 100644 index 0000000..354bc26 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentityfilter.ts @@ -0,0 +1,129 @@ +import * as Utils from '../../utils'; +import { EN_DropDownConst4Filter } from '../../consts'; +//Date format for dates in Web API + +export class BaseFilter { + filterPrefix: string = ''; + alwaysUsefilterPrefix: boolean = false; + useObjectFilter: boolean = true; + + + public onPrepare: (retFilter: BaseFilter) => void; + protected dontConsiderFields = ',filterPrefix,alwaysUsefilterPrefix,dontConsiderFields,useObjectFilter,onPrepare,dontResetFields,'; + + public dontResetFields = ''; + + public constructor(filterPrefix: string = '', init?: Partial) { + this.filterReset(); + if (init) { Object.assign(this, init); } + this.filterPrefix = filterPrefix; + } + + + public isFieldEmpty(fldName: string): boolean { + let isEmpty: boolean; + const obj: any = this[fldName]; + isEmpty = !obj && !(typeof obj === 'boolean' && obj === false); + if (!isEmpty) { + if (obj instanceof Array) isEmpty = obj.length === 0; + else { + switch (typeof obj) { + case 'number': + isEmpty = (obj === EN_DropDownConst4Filter.AllValueInt); + break; + case 'string': + isEmpty = (obj === EN_DropDownConst4Filter.AllValueString); + break; + } + } + } + return isEmpty; + } + + + public initField(fldName: string) { + if (!this.isFieldEmpty(fldName)) { + if (this[fldName] instanceof Array) this[fldName] = []; + else { + switch (typeof this[fldName]) { + // case 'number': + // Object.assign(this, { [fldName]: 0 }); + // break; + case 'string': + Object.assign(this, { [fldName]: '' }); + break; + default: + this[fldName] = null; + break; + } + } + } + } + + + protected isServiceField(fldName: string): boolean { + return (',' + this.dontConsiderFields + ',').indexOf(',' + fldName + ',') > -1; + } + + + protected isFixedField(fldName: string): boolean { + return (',' + this.dontResetFields + ',').indexOf(',' + fldName + ',') > -1; + } + + + public getFilterURL(): any { + const retFilter: BaseFilter = Object.assign({}, this); + if (this.doPrepare) this.doPrepare(retFilter); + let retVal = ''; + // tslint:disable-next-line: forin + for (const prop in retFilter) { + if (!retFilter.isServiceField(prop) && retFilter.propertyIsEnumerable(prop) && !retFilter.isFieldEmpty(prop)) { + let curval: string = ''; + const obj = retFilter[prop]; + + if (obj instanceof Array) { + if (obj.length > 0) curval = obj.join(); + } else curval = Utils.toStringConsiderDateFormat(obj); + if (curval) retVal += `&${prop}=${curval}`; + } + } + if (retVal.length) retVal = retVal.substring(1); + if (retVal.length) retVal = retFilter.filterPrefix + '?' + retVal; + else if (retFilter.alwaysUsefilterPrefix) retVal = retFilter.filterPrefix; + + return retVal; + } + + + getFilter(): any { + const retFilter: BaseFilter = Object.assign({}, this); + if (this.doPrepare) this.doPrepare(retFilter); + delete retFilter.alwaysUsefilterPrefix; + delete retFilter.filterPrefix; + delete retFilter.useObjectFilter; + delete retFilter.dontConsiderFields; + delete retFilter.dontResetFields; + return retFilter; + } + + protected doPrepare(retFilter: BaseFilter) { + for (const prop in this) { + if (!this.isServiceField(prop) && this.propertyIsEnumerable(prop) && !this.isFieldEmpty(prop)) { + const obj = retFilter[prop as string]; + switch (typeof obj) { + case 'string': + retFilter[prop as string] = obj.trim(); + break; + } + } + } + if (this.onPrepare) this.onPrepare(retFilter); + } + + + public filterReset() { + for (const prop in this) { + if (!this.isServiceField(prop) && !this.isFixedField(prop) && this.propertyIsEnumerable(prop)) this.initField(prop); + } + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitylist.wrapper.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitylist.wrapper.ts new file mode 100644 index 0000000..c8d9a2e --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/generics/baseentitylist.wrapper.ts @@ -0,0 +1,683 @@ +import { BaseEntity, ErrorCallBack, BaseEntityCallBack } from './baseentity'; +import { BaseEntityWrapper } from './baseentity.wrapper'; +import { Subscription, interval, Observable, Subject, forkJoin, of } from 'rxjs'; +import { BaseFilter } from './baseentityfilter'; +import { RepositoryService } from '../../services/http/repository.service'; +import { UINotifierService } from '../../services/notification/uinotifier.service'; +import { cnst_CANCEL_ERROR, EN_EntityBeforeSaveCallBackResults, EN_EntityEditingStates } from '../../consts'; +import { getErrorMessageAsText, isEqual, now } from '../../utils'; +import { AppLogsService } from '../../services/applogs.service'; +import { ResultSubject } from '../resultsubject'; +import * as keycode from '@angular/cdk/keycodes'; +import { HenselTranslateService } from '../../services/localization/hensel-translate.service'; +import { inject } from '@angular/core'; + +export class BaseEntityListWrapper { + public static delayDoItemSelect: number = 500; //item is selected if the last ..ms doSelect was not called + public static delayDoItemFocus: number = 500; //item is focused if the last ..ms doFocus was not called + public static dalayFocusLastItem: number = 500; //delay after last item of the list is selected in the grid component + public static dalayFocusFirstItem: number = 1250; //delay after last item of the list is selected in the grid component, use it to wait the finish of grid sorting + public focusedEntityShadowed: BaseEntityWrapper; + public reloadAfterItemUpdate: boolean = false; + public alwaysFocused: boolean = true; // approves that if the list is not empty it has always focused row (after delete rows or reloading), after loading the focused is not changed + public afterLoadFocusFirstItem: boolean = false; // approves that after reloading the first row always has focus + public batchInsert: boolean = true; + public focusedItemGridIndex: number = -1; + public useFocusedGridIndex: boolean = true; + public focusedCallBack: BaseEntityCallBack; + public focusedRoutingCallBack: BaseEntityCallBack; + public savedCallBack: VoidFunction; + public confirmationsOn: boolean = false; + public dontShowErrors: boolean = true; + public beforeSaveCallBack: (entity: BaseEntity[]) => Promise; //callback to be called before save, returns 0-all ok, continue saving, 1-all ok, break further saving, 2 - error, ignore coninue + public afterInsertCallBack: (entity: BaseEntity, callback?: BaseEntityCallBack) => void; + public isConnectedWithSortedGrid: boolean = true; + public connectedGrid: any; + public deletedItems: T[] = []; + public shouldBeNotEmpty: boolean = false; + public entityListLoaded$: Subject = new Subject(); + public translate: HenselTranslateService; + + private _isLoading: boolean = false; + public updateItemIfWasNotFoundInList: boolean = false; + + public get isLoading(): boolean { + return this._isLoading; + } + public set isLoading(value: boolean) { + const wasLoading = this._isLoading; + this._isLoading = value; + if (wasLoading && !value) this.entityListLoaded$.next(); + } + + + private _hierarchyLevel: number = 0; + public get hierarchyLevel(): number { + return this._hierarchyLevel; + } + public set hierarchyLevel(value: number) { + this._hierarchyLevel = value; + if (this.focusedEntityShadowed) this.focusedEntityShadowed.hierarchyLevel = value; + } + + protected _focusedTimer: Subscription = null; + protected _selectedTimer: Subscription = null; + protected _selectedItemIds: number[] = []; + protected _focusedItemId: number = 0; + protected _items: T[] = []; + + private _reloadAnyway: boolean = false; + private readonly lastElement = -1; + private loginSubscriptionSave: Subscription; + private loginSubscriptionLoad: Subscription; + + protected appLogsService: AppLogsService; + protected repositoryService: RepositoryService; + protected uiNotificationsService: UINotifierService; + + constructor( + protected TEntity: new (src?: Partial) => T, + public _listName: string, + public routing: string, //controller route + public filter?: BaseFilter, + appLogsService?: AppLogsService, + repositoryService?: RepositoryService, + uiNotificationsService?: UINotifierService, + ) { + this.appLogsService = appLogsService ?? inject(AppLogsService); + this.repositoryService = repositoryService ?? inject(RepositoryService); + this.uiNotificationsService = uiNotificationsService ?? inject(UINotifierService); + this.translate = this.appLogsService.translate; + } + + public get items(): T[] { return this._items; } + + + public set items(newItems: T[]) { + this._items = newItems; + this.deletedItems = []; + // this.clearSelected(); //is done indirectly in approveFocusedSelectedItems + this.approveFocusedSelectedItems(); + } + + get selectedItemIds(): number[] { + return this._selectedItemIds; + } + + + set selectedItemIds(list: number[]) { + // if (!(this._selectedItemsLast.length === list.length && list.every(_ => this._selectedItemsLast.find(vl => vl === _) !== undefined))) { + // this._selectedItemsLast = Object.assign([], list); + + this._selectedItemIds = list; + //Hack to avoid multicall of selected event + + if (this._selectedTimer) this._selectedTimer.unsubscribe(); + this._selectedTimer = interval(BaseEntityListWrapper.delayDoItemSelect).subscribe(() => { + this._selectedTimer?.unsubscribe(); + this.doSelect(list); + }); + } + + get focusedItemId(): number { return this._focusedItemId; } + set focusedItemId(focusedId: number) { + if (Array.isArray(focusedId)) focusedId = focusedId.length > 0 ? focusedId[0] : 0; + if (!focusedId || (typeof focusedId !== 'number')) focusedId = 0; //avoid to fire if focusedId is undefined or null or NaN, which we can get from the grid component + if (this._focusedItemId === focusedId && !this._reloadAnyway && focusedId /* important for details.enablededit() at the start*/) return; + this._focusedItemId = focusedId; + + if (this._focusedTimer) this._focusedTimer.unsubscribe(); + this._focusedTimer = interval(BaseEntityListWrapper.delayDoItemFocus).subscribe(() => { + this._focusedTimer?.unsubscribe(); + this.doFocus(focusedId); + }); + } + + public get focusedItem(): T { return this.focusedItemId ? this.getItemById(this.focusedItemId) : null; } + + + public get changed(): boolean { + return (this.deletedItems.length > 0) || this.items.some((it: BaseEntity) => it.entityChanged); + } + + + public get isValidInput(): boolean { + return (!this.shouldBeNotEmpty || this.items.length > 0) && this.items.every((it: BaseEntity) => it.isValidInput); + } + + + protected approveFocusedSelectedItems(newId: number = 0) { + const _focusedItem: T = this.focusedItem; + // setTimeout(() => { + this._reloadAnyway = true; //to call focused event for details anyway (even focusedItemId was the same) + if (!_focusedItem) { + if (newId !== 0) this.focusedItemId = newId; + else if (this.alwaysFocused) this.focusFirstItem(); + else this.focusedItemId = 0; + } else { + // this._reloadAnyway = true; + this.focusedItemId = this.focusedItemId; //reload focused entity anyway + } + if (this.items.length === 0) this.clearSelected(); + else this.selectedItemIds = this.selectedItemIds.filter(id => this.getItemById(id) !== null); + // }, 0/*cnstChangedWaitInterval*/); + } + + + public focusFirstItem(_loadedCallback?: (entity: T[]) => void, _interval: number = BaseEntityListWrapper.dalayFocusFirstItem) { + const lastFocusItemIdIndex = this.useFocusedGridIndex ? this.focusedItemGridIndex : this.focusedItemId; + if (this.useFocusedGridIndex) _interval = 0; //if the gridindex is using is used - does not matter the grid sorting + setTimeout(() => { //to set after grid's sorting + // to fix - during setting of focusedItemGridIndex, focusedItemId is changed and causes "check after change error" + const curFocusItemIdIndex = this.useFocusedGridIndex ? this.focusedItemGridIndex : this.focusedItemId; + // this.appLogsService.dlog('--- Last Focused Index/Id', this._listName, lastFocusItemIdIndex, curFocusItemIdIndex); + if (this.items && this.items.length > 0) { + if (lastFocusItemIdIndex === curFocusItemIdIndex) { //grid focus was not explicetely changed + if (this.useFocusedGridIndex) this.focusedItemGridIndex = 0; // to be aware of grid sorting + else this.focusedItemId = this.items[0].entityId; + } + } else this.focusedItemId = 0; + if (_loadedCallback) _loadedCallback(this.items); + }, _interval); + } + + + public focusLastItem(_loadedCallback?: (entity: T[]) => void, _interval: number = BaseEntityListWrapper.dalayFocusLastItem) { + const lastFocusItemIdIndex = this.useFocusedGridIndex ? this.focusedItemGridIndex : this.focusedItemId; + if (this.useFocusedGridIndex) _interval = 0; //if the gridindex is using is used - does not matter the grid sorting + setTimeout(() => { //to set after grid's sorting + const curFocusItemIdIndex = this.useFocusedGridIndex ? this.focusedItemGridIndex : this.focusedItemId; + // this.appLogsService.dlog('--- Last Focused Index/Id', this._listName, lastFocusItemIdIndex, curFocusItemIdIndex); + if (this.items && this.items.length > 0) { + if (lastFocusItemIdIndex === curFocusItemIdIndex) { //grid focus was not explicetely changed + if (this.useFocusedGridIndex) this.focusedItemGridIndex = this.items.length - 1; // to be aware of grid sorting + else this.focusedItemId = this.items[this.items.length - 1].entityId; + } + } else this.focusedItemId = 0; + if (_loadedCallback) _loadedCallback(this.items); + }, _interval); + } + + + public gridUpDownProcessing(e: any) { + switch (e.event.keyCode) { + case keycode.HOME: + this.focusFirstItem(null, 100); + e.event.stopPropagation(); + break; + case keycode.END: + this.focusLastItem(null, 100); + e.event.stopPropagation(); + break; + } + } + + public getItemById(id: number): T { return this.items ? this.items.find(it => it.entityId === id) : null; } + + + public getItemIndex(entity: T | number): number { + if ((typeof entity) === 'number') { + return this.items.findIndex((it) => (it.entityId === entity)); + } else if (entity instanceof BaseEntity) { + return this.items.findIndex((it) => it === entity || ( + entity?.entityId && ( + it?.entityId === entity?.entityId + || entity.insertWithIds() && -it?.entityId === entity?.entityId //in the case of insertWithIds entityId = -entityId after saving + ) + )); + } else return this.items.findIndex((it: any) => it === entity); + } + + + public get focusedItemIndex(): number { + return this.getItemIndex(this.focusedItem); + } + + + public isDeleted(entity: T, respawn: boolean = false): boolean { + const indexInDeleted: number = this.deletedItems.indexOf(entity); + if (respawn && indexInDeleted > -1) this.deletedItems.splice(indexInDeleted, 1); + return indexInDeleted > -1; + } + + + setTriggerItem(entity: T, itemOn: boolean) { + if (!itemOn) { + if (!entity.isNew()) this.deletedItems.push(entity); //mark for deleting if already saved, bot leave in the main list + entity.entityChanged = false; //set to be not saved from main list + } else { + entity.entityChanged = true; //mark to be saved + this.isDeleted(entity, true); //remove from list of items to delete if was there + } + } + + + public clearSelected() { this.selectedItemIds = []; } + + + public clearFocused() { this.focusedItemId = 0; } + + + public clear() { + this.items = []; + // this._items = []; + // this.clearSelected(); + // this.clearFocused(); + // if (this.focusedEntityShadowed) this.focusedEntityShadowed.clear(); + } + + + public createFocusedShadowEntity(defaultEditMode?: EN_EntityEditingStates): BaseEntityWrapper { + this.focusedEntityShadowed = new BaseEntityWrapper(this.TEntity, defaultEditMode); + this.focusedEntityShadowed.entityList = this; + this.focusedEntityShadowed.hierarchyLevel = this.hierarchyLevel; + return this.focusedEntityShadowed; + } + + + public load(_loadedCallback?: (entity: T[]) => void, _errorCallback?: ErrorCallBack, _completeCallback?: () => void): boolean // + { + if (this.filter && this.filter.useObjectFilter) { + return this.loadWithObjFilter(_loadedCallback, _errorCallback, _completeCallback); + } else this.loadWithURLFilter(_loadedCallback, _errorCallback, _completeCallback); + + } + + + public loadWithObjFilter(_loadedCallback?: (entity: T[]) => void, _errorCallback?: ErrorCallBack, _completeCallback?: () => void): boolean // + { + return this._load(this.repositoryService.getDataByObjFilter(this.routing + (this.filter.filterPrefix ? '/' + this.filter.filterPrefix : ''), this.filter.getFilter()), _loadedCallback, _errorCallback, _completeCallback); + } + + + public loadWithURLFilter(_loadedCallback?: (entity: T[]) => void, _errorCallback?: ErrorCallBack, _completeCallback?: () => void): boolean // + { + return this._load(this.repositoryService.getDataByURLFilter(this.routing, this.filter ? this.filter.getFilterURL() : ''), _loadedCallback, _errorCallback, _completeCallback); + } + + + + protected _load(loadList$: Observable, _loadedCallback?: (entity: T[]) => void, _errorCallback?: ErrorCallBack, _completeCallback?: () => void): boolean { + let msgID: number; + + if (!this.loginSubscriptionLoad && this.hierarchyLevel === 0) { + this.loginSubscriptionLoad = this.repositoryService.authService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { //try one time more + this._load(loadList$, _loadedCallback, _errorCallback, _completeCallback); + } else this.unsubscribe(this.loginSubscriptionLoad); + }); + } else { + if (this.loginSubscriptionLoad) this.unsubscribe(this.loginSubscriptionLoad); // try only one time more + } + + this.isLoading = true; + if (this.uiNotificationsService) msgID = this.uiNotificationsService.showMessage(this.translate.instant('core.msg.loading', { value: this.translate.instant(this._listName) })); + const filter4Call: BaseFilter = this.filter ? Object.assign({}, this.filter) : null; + let afterLoadFocusFirstItem = this.afterLoadFocusFirstItem; + loadList$.subscribe( + (entities: T[]) => { + try { + this.unsubscribe(this.loginSubscriptionLoad); //relogin is not executed - don't need subscription + if (!isEqual(filter4Call, this.filter)) return false; //means, that meanwhile a load command for another Id was executed. it must win + const _items: T[] = []; + if (entities) entities.map(entity => _items.push(new this.TEntity(entity))); + if (this.focusedEntityShadowed /*&& _items.length === 0*/ /*&& this.focusedRoutingCallBack*/) // to accellerate call back for empty list, otherwise it takes up to 2s, + // and to have isLoading=true for shadowEntity to disable new/edit button after list is loaded but before callback from the grid to load shadowEntity, + // otherwise can happens, the edit dialog for shadowEntity is opened and shadowEntity is loaded afterwords and get editmode=view -> error + { + this.focusedEntityShadowed.entityWasLoaded = false; //is set to fire loaded$ event for empty too, is called when wasloaded=true in pageservice.focusedRoutingCallBack + // functionality is called in approveFocusedSelectedItems called by this.items = _items; + // if (_items.length === 0) { + // this._reloadAnyway = true; //set it to 0 to call load for id=0, that sets entityWasLoaded=false, if not focusedRoutingCallBack + // this.focusedItemId = 0; //set it to 0 to call dofocused immediately. don't wait on pageservice.focusedRoutingCallBack + // } + } + this.items = _items; //here doFocused and do doSelected are triggered + if (this.uiNotificationsService) this.uiNotificationsService.showMessage(this.translate.instant('core.msg.loaded', { value: this.translate.instant(this._listName), count: this.items.length }), msgID); + if (this.afterLoadFocusFirstItem) { + this.focusFirstItem(() => { + if (_loadedCallback) _loadedCallback(this.items); + if (_completeCallback) _completeCallback(); + }); + } else if (_loadedCallback) _loadedCallback(this.items); + } catch (error) { + afterLoadFocusFirstItem = false; //to call completecallback anyway + const fehlerName: string = this.translate.instant('core.error.loading', { value: this.translate.instant(this._listName) }); + const errorMsg = getErrorMessageAsText(error); + if (errorMsg !== cnst_CANCEL_ERROR) { + if (this.uiNotificationsService) this.uiNotificationsService.showMessage(`${fehlerName}: ${errorMsg}`, msgID); + if (!this.dontShowErrors) this.appLogsService.errorMessageBox(fehlerName, errorMsg); + this.unsubscribe(this.loginSubscriptionLoad); //relogin is not executed - don't need subscription + } else this.uiNotificationsService.stopMessage(msgID); + if (_errorCallback) _errorCallback(({ errMsg: errorMsg === cnst_CANCEL_ERROR ? cnst_CANCEL_ERROR : `${fehlerName}: ${errorMsg}`, entity: this })); + } + finally { + if (_completeCallback && !afterLoadFocusFirstItem) {//_completeCallback is already called as callback for this.focusFirstItem(), don't need one time more + _completeCallback(); + } + this.isLoading = false; + } + }, + (error: any) => { + if (this.uiNotificationsService) this.uiNotificationsService.showMessage(this.translate.instant('core.error.loading', { value: this.translate.instant(this._listName) }), msgID, 6000); + if (_errorCallback) _errorCallback(error); + if (_completeCallback) _completeCallback(); + this.isLoading = false; + }, + ); + return true; + } + + + updateListItem(entity: T, insertIndex: number = this.lastElement /* at the end */, wasInserted: boolean = false): number { + if (!entity?.isEmpty() && entity.entityId !== 0) { + if (!wasInserted) { + let foundEntityIndex: number; + foundEntityIndex = this.getItemIndex(entity); + if (foundEntityIndex < 0 && this.updateItemIfWasNotFoundInList) foundEntityIndex = this.focusedItemIndex; //dont overwrite focused row in the grid, but add at the end + if (foundEntityIndex < this.items.length && foundEntityIndex > -1) { + if (this.items[foundEntityIndex] !== entity) { + this.items[foundEntityIndex].assign(entity); + // this.items[foundEntityIdx] = new this.TEntity(entity); //if is running we get spinner for the grid + } + if (this.focusedItemId !== entity.entityId) this.focusedItemId = entity.entityId; + return entity.entityId; + } + } + //inserts a new entity + const newEntity: T = new this.TEntity(entity); + if (newEntity) { + if (insertIndex < 0 || this.items.length <= insertIndex) this.items.push(newEntity); + else this.items.splice(insertIndex, 0, newEntity); + this.focusedItemId = newEntity.entityId; + return newEntity.entityId; //Id of a new Inserted entity + } + } + return -1; //no entities were updated/inserted + } + + + deleteListItem(entity: T, save2deleted: boolean = true, addAsDeletedAnyway: boolean = false): boolean { + if (!entity) return false; + const foundEntityIdx: number = this.getItemIndex(entity); + if (foundEntityIdx > -1) { + if (save2deleted && (entity instanceof BaseEntity) && !entity.isNew()) this.deletedItems.push(this.items[foundEntityIdx]); + this.items.splice(foundEntityIdx, 1); //to do delete must be called approve + //if is deleted in the sorted grid the logic cannot be used + if (!this.isConnectedWithSortedGrid) { + //timeout to avoid "Check after change error" + setTimeout(() => this.approveFocusedSelectedItems(this.items.length === 0 ? 0 : this.items[foundEntityIdx - (foundEntityIdx >= this.items.length ? 1 : 0)].entityId)); + } else if (this.items?.length === 0) this.approveFocusedSelectedItems(); + return true; + } else if (addAsDeletedAnyway && !((entity instanceof BaseEntity) && entity.isNew())) this.deletedItems.push(entity); + return false; + } + + + deleteAll(save2deleted: boolean = true) { + for (let i = this.items.length - 1; i >= 0; i--) { + const entity = this.items[i]; + if (save2deleted && !entity.isNew()) this.deletedItems.push(entity); + // this.items.splice(i, 1); //to do delete must be called approve + } + this.items.splice(0); + } + + + protected doSelect(list: number[]) { + //console.log('Selected', this.selectedItemIds); + } + + + protected doFocus(focusedId: number) { + const focusedItemId = this.focusedEntityShadowed?.entityId ?? 0; + const reloadAnyway = this._reloadAnyway; + this._reloadAnyway = false; + + if (this.focusedEntityShadowed && !this.focusedRoutingCallBack) { //use direct connection or routing + if (this.focusedEntityShadowed.entityId !== focusedId || reloadAnyway) { + this.focusedEntityShadowed.entityId = focusedId; + } + } + if (this.focusedRoutingCallBack) setTimeout(() => { this.focusedRoutingCallBack(this.focusedItem); }); + + if (this.focusedCallBack && (focusedItemId !== focusedId || reloadAnyway)) { + setTimeout(() => { this.focusedCallBack(this.focusedItem); }); + } + } + + + public async saveAsync(): Promise { + return new Promise((resolve, reject) => this.save(null, () => resolve(false), () => resolve(true))); + } + + + private unsubscribe(subscr: Subscription) { + subscr?.unsubscribe(); + subscr = null; + } + + public async save(_loadedCallback?: () => void, _errorCallback?: ErrorCallBack, _completeCallback?: () => void) { + let resBeforeSaveCallBack: EN_EntityBeforeSaveCallBackResults = EN_EntityBeforeSaveCallBackResults.Ok_Continue; + // tslint:disable-next-line: no-bitwise + const doBreak: boolean = this.beforeSaveCallBack && ((resBeforeSaveCallBack = await this.beforeSaveCallBack(this.items)) & EN_EntityBeforeSaveCallBackResults.Ok_Break) !== 0; + if (resBeforeSaveCallBack === EN_EntityBeforeSaveCallBackResults.Ok_Break) { + if (_loadedCallback) _loadedCallback(); + if (_completeCallback) _completeCallback(); + if (this.savedCallBack) this.savedCallBack(); + return; + } else if (resBeforeSaveCallBack === EN_EntityBeforeSaveCallBackResults.Error_Break) { + if (_errorCallback) _errorCallback({ errMsg: cnst_CANCEL_ERROR } as ResultSubject); + return; + } + + const updateDetails$: Subject[] = []; + const newItemList: BaseEntity[] = []; + const changedItemList: BaseEntity[] = []; + let newEntityIndex: number = 0; + + // prepare observable array for forkjoin + this.deletedItems.forEach(() => updateDetails$.push(new Subject())); + this.items.forEach((entity: T) => { + if (entity.entityChanged) { + if (entity.isNew()) { + if (this.batchInsert) { + const newEntity: BaseEntity = new this.TEntity(entity); + newEntity.entityId = 0; + newItemList.push(newEntity.deleteFields()); + } else updateDetails$.push(new Subject()); + } else changedItemList.push(entity.deleteFields()); + } + }); + if (newItemList.length > 0) updateDetails$.push(new Subject()); + if (changedItemList.length > 0) updateDetails$.push(new Subject()); + + //if nothing was deleted/added/changed + if (updateDetails$.length === 0) { + if (_loadedCallback) _loadedCallback(); + if (this.savedCallBack) this.savedCallBack(); + if (_completeCallback) _completeCallback(); + return; + } + + if (!this.loginSubscriptionSave && this.hierarchyLevel === 0 && this.repositoryService.authService.user.isAdmin) { + this.loginSubscriptionSave = this.repositoryService.authService.loginAction$.subscribe((resultObject) => { //try one time more + if (resultObject.result) { + this.appLogsService.dlog('!!! - relogin - resave list', resultObject); + this.save(_loadedCallback, _errorCallback, _completeCallback); + } else this.unsubscribe(this.loginSubscriptionSave); + }); + } else { + if (this.loginSubscriptionSave) this.unsubscribe(this.loginSubscriptionSave); // try only one time more + } + + + let msgID: number; + if (this.uiNotificationsService) msgID = this.uiNotificationsService.showMessage(this.translate.instant('core.msg.saving', { value: this.translate.instant(this._listName) })); + //wait on the result + forkJoin(updateDetails$).subscribe( + () => { + this.unsubscribe(this.loginSubscriptionSave); //relogin is not executed - don't need subscription + this.appLogsService.dlog('++ next save list <' + this.translate.instant(this._listName) + '>'); + this.items = this.items.slice(); //otherwise for new entities in the bind to grid lists id in the grid will not be updated and stay <0 + // this.approveFocusedSelectedItems(); + if (this.uiNotificationsService) this.uiNotificationsService.showMessage(this.translate.instant('core.msg.saved', { value: this.translate.instant(this._listName) }), msgID); + if (_loadedCallback) _loadedCallback(); + if (this.savedCallBack) this.savedCallBack(); + } + , (error: any) => { + this.deletedItems = this.deletedItems.filter(_ => _); //let be in array only not null elements + + this.appLogsService.error('!! error save list <' + this.translate.instant(this._listName) + '>: ', { error }); + + const fehlerName: string = this.translate.instant('core.error.saving', { value: this.translate.instant(this._listName) }); + const errorMsg = getErrorMessageAsText(error); + if (errorMsg !== cnst_CANCEL_ERROR) { + if (this.uiNotificationsService) this.uiNotificationsService.showMessage(`${fehlerName}: ${errorMsg}`, msgID); + if (!this.dontShowErrors) this.appLogsService.errorMessageBox(fehlerName, errorMsg); + this.unsubscribe(this.loginSubscriptionSave); //relogin is not executed - don't need subscription + } else this.uiNotificationsService.stopMessage(msgID); + if (_errorCallback) _errorCallback(({ errMsg: errorMsg === cnst_CANCEL_ERROR ? cnst_CANCEL_ERROR : `${fehlerName}: ${errorMsg}`, entity: this })); + } + , () => { + this.appLogsService.dlog('++ complete save list <' + this.translate.instant(this._listName) + '>'); + this.deletedItems = this.deletedItems.filter(_ => _); //let be in array only not null elements + if (_completeCallback) _completeCallback(); + } + ); + + //delete deleted entities + for (let index = 0; index < this.deletedItems.length; index++) { + const inx: number = index; //must be created every time for every observable call, otherwise we get the same value for all callbacks + if (this.deletedItems[inx]) { + this.deletedItems[inx].delete(this.repositoryService + , () => { + this.deletedItems[inx] = null; //element was sucessfully deleted - eliminate from the list of to be deleted + updateDetails$[inx].next(); + } + , (error) => updateDetails$[inx].error(error) + , () => updateDetails$[inx].complete()); + } + } + + newEntityIndex = this.deletedItems.length; + let batchRouting = this.routing.toLowerCase(); + if (batchRouting.slice(-4) === '/all') batchRouting = batchRouting.slice(0, batchRouting.length - 4); + batchRouting += '/list'; + + if (this.batchInsert) { + // insert new entities in batch + if (newItemList.length > 0) { + const inx: number = newEntityIndex; //must be created every time for every obserfable call, otherwise we get the same value for all callbacks + this.repositoryService.postData(batchRouting, newItemList) + .subscribe( + (entities: T[]) => { + // let index: number = 0; + // this.items.forEach((it: T) => { + // if (it.isNew() && it.entityChanged) it.assign(new this.TEntity(entities[index++])); + // }); + this._items.splice(0, this._items.length, ...this.items.filter( //splice - technique to save array pointer and change only array content + (it: T) => !(it.isNew() && it.entityChanged)).concat(entities.map((it: T) => new this.TEntity(it))) + ); + this.appLogsService.dlog('--- next insert list <' + this.translate.instant(this._listName) + '>', inx, this.items); + updateDetails$[inx].next(); + } + , (error) => updateDetails$[inx].error(error) + , () => { + this.appLogsService.dlog('--- complete insert list <' + this.translate.instant(this._listName) + '>', inx); + updateDetails$[inx].complete(); + } + ); + newEntityIndex++; + } + } else { + //insert new entities separately + this.items.forEach((entity: T, index: number) => { + if (entity.isNew() && entity.entityChanged) { + const inx: number = newEntityIndex; //must be created every time for every observable call, otherwise we get the same value for all callbacks + entity.save(this.repositoryService + , (loadedEntity: BaseEntity) => { + const updNext$ = updateDetails$[inx]; + const entity_ = loadedEntity; //because of collisions in callback if it is called sequentially + if (this.afterInsertCallBack) { + this.afterInsertCallBack(entity_, () => { + // loadedEntity.load(this.repositoryService, null); + updNext$.next(); + updNext$.complete(); + }); + } else updNext$.next(); + } + , (error) => updateDetails$[inx].error(error) + , () => { if (!this.afterInsertCallBack) updateDetails$[inx].complete(); } + ); + newEntityIndex++; + } + }); + } + + //save changed entities in batch + if (changedItemList.length > 0) { + const inx: number = newEntityIndex; //must be created every time for every obserfable call, otherwise we get the same value for all callbacks + this.repositoryService.putData(batchRouting, changedItemList) + .subscribe( + () => { + this.items.forEach((entity: T) => { if (entity.entityChanged) entity.entityChanged = false; }); + this.appLogsService.dlog('--- next update list <' + this.translate.instant(this._listName) + '>', inx); + updateDetails$[inx].next(); + } + , (error: any) => updateDetails$[inx].error(error) + , () => { + this.appLogsService.dlog('--- complete update list <' + this.translate.instant(this._listName) + '>', inx); + updateDetails$[inx].complete(); + } + ); + } + } + + + getId4NewItem() { + return this.items.reduce((min: number, _item: T) => (min < _item.entityId ? min : _item.entityId), 0) - 1; + } + + + newItem(src?: Partial, changed?: boolean): T { + const item: T = new this.TEntity(src); + if (changed !== null && changed !== undefined) item.entityChanged = changed; + item.entityId = this.getId4NewItem(); + this.items.push(item); + return item; + } + + public match2KeysArray(entity: BaseEntity, fieldName4EntityKey: string, keyArray: number[], fieldName4Key: string): boolean { + let wasChanged: boolean = false; + for (let index = this.items.length - 1; index >= 0; index--) { + const currItem = this.items[index]; + if (keyArray.indexOf(currItem[fieldName4Key]) === -1) { + this.deleteListItem(currItem); + wasChanged = true; + } + } + keyArray.forEach((key) => { + if (!this.items.find((item: T) => item[fieldName4Key] === key)) { + const item = new this.TEntity(); + item[fieldName4EntityKey] = entity[fieldName4EntityKey]; + item[fieldName4Key] = key; + item.entityChanged = true; + this.items.push(item); + wasChanged = true; + } + }); + return wasChanged; + } + + + public match2array(entity: BaseEntity, fieldName4EntityKey: string, fieldName4ArrayKey: string, fieldName4Key: string): boolean { + return this.match2KeysArray(entity, fieldName4EntityKey, entity[fieldName4ArrayKey], fieldName4Key); + } + + + public onFocusedRowChanging($event) { + if (this.focusedEntityShadowed && this.focusedEntityShadowed.entityIsLoading) $event.cancel = true; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/resultsubject.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/resultsubject.ts new file mode 100644 index 0000000..d972fe0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/resultsubject.ts @@ -0,0 +1,14 @@ +import { cnst_CANCEL_ERROR } from '../consts'; +import { getErrorMessageAsText } from '../utils'; + +export class ResultSubject { + result = false; + errMsg?; + entity?: any; + constructor(error: any, entity: any, prefix: string = '') { + this.errMsg = getErrorMessageAsText(error); + if ( this.errMsg !== cnst_CANCEL_ERROR && this.errMsg.indexOf(prefix) === -1) this.errMsg = prefix + this.errMsg; + this.entity = entity; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/models/serverinfo.ts b/ClientApp/staff-db-ui/src/app/shared/core/models/serverinfo.ts new file mode 100644 index 0000000..1181db9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/models/serverinfo.ts @@ -0,0 +1,31 @@ +import { EN_CoreEntities } from '../services/globals'; +import { BaseEntity } from './generics/baseentity'; + + +export class ServerInfo extends BaseEntity { + public typeName: string = EN_CoreEntities.ServerInfo; //is used as Controller for URL queries + version: string; + server: string; + status: number; + message: string; + databaseServer: string; + databaseName: string; + databaseStatus: string; + + userName: string; + serviceLoginName: string; + isLive: boolean; + fileServer: string; + lastDataLoaded: Date; + clientVersion: string; + firstOnlineTime: Date; + lastOfflineTime: Date; + attributes: any; + officeFileServer: string; + officeFileServerURL: string; + officeFileServerVersion: string; + officeFileServerDBServer: string; + officeFileServerDBName: string; + + isNew() { return false; } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/pipes/hensel-html-sanitizer.pipe.ts b/ClientApp/staff-db-ui/src/app/shared/core/pipes/hensel-html-sanitizer.pipe.ts new file mode 100644 index 0000000..f811688 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/pipes/hensel-html-sanitizer.pipe.ts @@ -0,0 +1,15 @@ +import { Pipe } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; + + +@Pipe({ + name: 'htmlSanitize', + standalone: true +}) + +export class HenselHTMLSanitizer { + constructor(private sanitized: DomSanitizer) { } + transform(value) { + return this.sanitized.bypassSecurityTrustHtml(value); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/applogs.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/applogs.service.ts new file mode 100644 index 0000000..29533eb --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/applogs.service.ts @@ -0,0 +1,164 @@ +import { Inject, Injectable } from '@angular/core'; +import * as Utils from '../utils'; +import { MatDialogService } from './mat-dialog.service'; +import { MessageBoxComponent } from '../components/message-box/message-box.component'; +import { EN_LogType } from '../consts'; +import { Globals, IMessageBoxButton, IMessageBoxData } from './globals'; +import * as Sentry from '@sentry/angular'; +import { ENVIRONMENT_TOKEN, IENVIRONMENT } from '../injection-tokens'; +import { HenselTranslateService } from './localization/hensel-translate.service'; +import { MatDialogRef } from '../components/angular-material-index'; + +const DoubledEventIntrval = 500; + +@Injectable({ + providedIn: 'root' +}) + +export class AppLogsService { + startingTimes: Map = new Map(); + constructor( + private dialog: MatDialogService, + private globals: Globals, + public translate: HenselTranslateService, + @Inject(ENVIRONMENT_TOKEN) private environment: IENVIRONMENT, + ) { } + + checkDoubledEvent(key: string) { + const nowticks = Utils.now(); + const isDoubled = (this.startingTimes.has(key) && (nowticks - this.startingTimes.get(key)) < DoubledEventIntrval); + this.startingTimes.set(key, nowticks); + return isDoubled; + } + + log(message?: any, ...optionalParams: any[]) { + this._log(EN_LogType.message, message, ...optionalParams); + } + + warn(message?: any, ...optionalParams: any[]) { + this._log(EN_LogType.warning, message, ...optionalParams); + } + + error(message?: any, ...optionalParams: any[]) { + this._log(EN_LogType.error, message, ...optionalParams); + const err = optionalParams.find(obj => typeof obj === 'object'); + if (this.environment.sentry_dsn) Sentry.captureException(err ?? message); + } + + + exception(exception: any, ...optionalParams: any[]) { + this._log(EN_LogType.error, Utils.getErrorMessageAsText(exception), ...optionalParams); + if (this.environment.sentry_dsn) Sentry.captureException(Utils.extractError(exception)); + } + + + dlog(message?: any, ...optionalParams: any[]) { + this._log(EN_LogType.debug_message, message, ...optionalParams); + } + + + private _log(logType: EN_LogType, message?: any, ...optionalParams: any[]) { + let timestr: string = ''; + let guid: string = null; + const isDebug = logType === EN_LogType.debug_message; + const guiindex = optionalParams.findIndex( + obj => { if (typeof obj === 'object' && 'guid' in obj) { guid = obj.guid; return true; } else return false; } + ); + + + if (guid) { + optionalParams.splice(guiindex, 1); + if (this.startingTimes.has(guid)) { + timestr = Utils.ms2ToTimeString(Utils.now() - this.startingTimes.get(guid), 'm:s.SSS'); + this.startingTimes.delete(guid); + logType = EN_LogType.guid_message; + } else this.startingTimes.set(guid, Utils.now()); + } + switch (logType) { + case EN_LogType.message: + console.log(message, ...optionalParams); + break; + case EN_LogType.warning: + console.warn(message, ...optionalParams); + break; + case EN_LogType.error: + console.error(message, ...optionalParams); + break; + case EN_LogType.debug_message: + if (!this.environment.production) console.log(message, ...optionalParams); + break; + case EN_LogType.guid_message: + if (!isDebug || !this.environment.production) { + console.log('Finished: ' + ((message).indexOf('%c') > -1 ? '' : '%c') + message + (timestr ? ': ' + timestr + 's' : ''), ...optionalParams); + } + break; + } + } + + showMessageBox(messageBoxData: IMessageBoxData, callBack?: () => void): MatDialogRef { + messageBoxData.overHeader = this.globals.appTitleWithVersion; + // messageBoxData.header = Utils.translateString(messageBoxData.header, this.translate); + // messageBoxData.message = Utils.translateString(messageBoxData.message, this.translate); + return this.dialog.openDialog(MessageBoxComponent, messageBoxData, true, (result: number) => { + if (callBack) callBack(); + messageBoxData.buttons.forEach((btn: IMessageBoxButton) => { + if (btn.code === result && btn.callback) btn.callback(); + }); + }, false); + } + + + errorMessageBox(caption: string, message: string, commonCallBack?: () => void): MatDialogRef { + return this.showMessageBox({ + type: EN_LogType.error, + header: caption, + message: message, + buttons: [{ title: this.translate.instant('core.btn.ok') }] + }, commonCallBack); + } + + + warningMessageBox(caption: string, message: string, commonCallBack?: () => void): MatDialogRef { + return this.showMessageBox({ + type: EN_LogType.warning, + header: caption, + message: message, + buttons: [{ title: this.translate.instant('core.btn.ok') }] + }, commonCallBack); + } + + + informationMessageBox(caption: string, message: string, commonCallBack?: () => void): MatDialogRef { + return this.showMessageBox({ + type: EN_LogType.message, + header: caption, + message: message, + buttons: [{ title: this.translate.instant('core.btn.ok') }] + }, commonCallBack); + } + + + confirmMessageBoxYesNo(caption: string, message: string, yesCallBack: () => void, commonCallBack?: () => void, defaultButtonInx: number = 0): MatDialogRef { + return this.showMessageBox({ + type: EN_LogType.confirmation, + header: caption, + message: message, + buttons: [{ title: this.translate.instant('core.btn.yes'), code: 1, default: defaultButtonInx === 0, callback: yesCallBack }, + { title: this.translate.instant('core.btn.no'), default: defaultButtonInx === 1, cancel: true, code: 0 }, + ] + }, commonCallBack); + } + + + confirmMessageBoxYesNoCancel(caption: string, message: string, yesCallBack: () => void, noCallBack: () => void, commonCallBack?: () => void, defaultButtonInx: number = 0): MatDialogRef { + return this.showMessageBox({ + type: EN_LogType.confirmation, + header: caption, + message: message, + buttons: [{ title: this.translate.instant('core.btn.yes'), code: 1, callback: yesCallBack, default: defaultButtonInx === 0 }, + { title: this.translate.instant('core.btn.no'), code: 0, callback: noCallBack, default: defaultButtonInx === 1 }, + { title: this.translate.instant('core.btn.cancel'), cancel: true, code: -1, default: defaultButtonInx === 2 }, + ] + }, commonCallBack); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/authguard.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/authguard.ts new file mode 100644 index 0000000..a4427c5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/authguard.ts @@ -0,0 +1,63 @@ +import { Injectable, Inject } from '@angular/core'; +import { Router, ActivatedRouteSnapshot, RouterStateSnapshot, Route, UrlSegment } from '@angular/router'; +import { AuthorizeService } from './authorize.service'; +import { Globals, LOGIN_PAGE } from './globals'; +import { PageLoadingService } from './pageloading.service'; +import { AppLogsService } from './applogs.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthGuard { + constructor( + private router: Router, + private authService: AuthorizeService, + private globals: Globals, + private pageLoadingService: PageLoadingService, + private appLogsService: AppLogsService + ) { } + + canLoad(route: Route, segments: UrlSegment[]): boolean { + return true; + } + + + async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise { + let ret: boolean = true; + const urlParsed: string[] = state.url.slice(1).split('/'); + if (!(this.authService.useJWT && !this.authService.checkJWT(0) && this.authService.isLoggedIn())) { + const currentPageURL = urlParsed[0].split('?')[0]; + const currentPage = this.globals.getPage(currentPageURL); + if (this.globals.isTheLoginPage(state.url/*'/' + currentpage*/) || this.authService.isLoggedIn()) { + if (currentPage && currentPage.hidden && !currentPage.allowRedirect) return false; //security to acces hidden pages for unathorized + let param: string = null; + if (urlParsed.length > 1) param = urlParsed[urlParsed.length - 1]; + // if (currentPage?.allowRedirect && this.globals.currentPage === currentpage && !param) return false; + if (this.globals.currentPage === currentPageURL) { + if (currentPage.dontAllowEmptyURL && !param && !!this.globals.urlParam) { + param = this.globals.urlParam; + state.url += '/' + param; + ret = false; + } + } + this.globals.currentPage = currentPageURL; + this.globals.urlParam = param; + this.pageLoadingService.pageActive$.next(this.globals.urlParam); + this.appLogsService.dlog('!! Goto', state.url); + return ret; + } + } else { + this.authService.expiredJWTLogout = true; //the flag is used to show jwt expired message + if (await this.authService.tryRenewJWTAsync(false)) return true; + } + + //not logged in and not in the logon page + if (!this.globals.isTheLoginPage(state.url)) { + const queryParams = { queryParams: { returnUrl: state.url } }; + this.globals.currentPage = LOGIN_PAGE.path; + this.appLogsService.dlog('!! Goto ' + LOGIN_PAGE.path, state.url); + this.router.navigate(['/' + LOGIN_PAGE.path], queryParams); + } + return false; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/authorize.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/authorize.service.ts new file mode 100644 index 0000000..569c76b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/authorize.service.ts @@ -0,0 +1,318 @@ +import { inject, Inject, Injectable, Optional, SkipSelf } from '@angular/core'; +import { Router } from '@angular/router'; +import * as Sentry from '@sentry/angular'; +import { DeviceDetectorService } from 'ngx-device-detector'; +import { NgxSpinnerService } from 'ngx-spinner'; +import { BehaviorSubject, Observable, Subject } from 'rxjs'; +import { LoginPopupComponent } from '../components/login/login-popup/login-popup.component'; +import * as Cnst from '../consts'; +import { LOGIN_PAGE } from './globals'; +import { ENVIRONMENT_TOKEN } from '../injection-tokens'; +import { CoreUser, EN_UserRoles } from '../models/coreuser'; +import { ResultSubject } from '../models/resultsubject'; +import { AppLogsService } from '../services/applogs.service'; +import { RepositoryService } from '../services/http/repository.service'; +import * as Utils from '../utils'; +import { HenselTranslateService } from './localization/hensel-translate.service'; +import { LocaleService } from './localization/locale.service'; +import { MatDialogService } from './mat-dialog.service'; +import { UINotifierService } from './notification/uinotifier.service'; + +// tslint:disable-next-line: class-name +export class HR_JWToken { + idToken: string; + expiresInSec?: number; + expiresAt?: Date; + + constructor(idToken: string, expiresAt: Date, expiresInSec?: number) { + this.idToken = idToken; + this.expiresAt = expiresAt; + this.expiresInSec = expiresInSec; + } +} + + + +@Injectable({ providedIn: 'root' }) +export class AuthorizeService { + private environment = inject(ENVIRONMENT_TOKEN); + + public EN_LoginStatus_Unknown = Cnst.EN_LoginStatus.unknown; + public EN_LoginStatus_JWT = Cnst.EN_LoginStatus.jwt; + public EN_LoginStatus_Password = Cnst.EN_LoginStatus.loginWithNameAndPassword; + public EN_LoginStatus_Windows = Cnst.EN_LoginStatus.windowsAuthorizatoin; + + public versionObsolete$ = new Subject(); + public loginAction$ = new Subject(); + public loginLogout$ = new BehaviorSubject(null); + public loginStatus: Cnst.EN_LoginStatus = Cnst.EN_LoginStatus.unknown; + public useWindowsLogin: boolean = true; + public isMobileDevice: boolean = false; + public expiredJWTLogout: boolean = false; + public useJWT: boolean = false; + public HR_JWT: HR_JWToken; + public processDisclaimer: (coreUser: CoreUser) => Promise; + private _user: CoreUser = new CoreUser(); + private lastLoggedUserId: number; + private _versionObsolete: boolean = false; + public get versionObsolete(): boolean { + return this._versionObsolete; + } + public set versionObsolete(value: boolean) { + if (this._versionObsolete === value) return; + this._versionObsolete = value; + if (value) this.versionObsolete$.next(); + } + + private isRunningRenewJWT: boolean = false; + + + + constructor( + private dialog: MatDialogService, + private router: Router, + private repositoryService: RepositoryService, + private appLogsService: AppLogsService, + private uiNotifier: UINotifierService, + private deviceService: DeviceDetectorService, + private spinnerService: NgxSpinnerService, + private translate: HenselTranslateService, + public localeService: LocaleService, + + @Optional() @SkipSelf() parentService: AuthorizeService, + // @Inject(LOCALE_ID) private localeId: string, + ) { + + repositoryService.authService = this; //to give possibility to use authservice in base entity wrappers + this.isMobileDevice = !this.deviceService.isDesktop(); + this.useWindowsLogin = !this.isMobileDevice; + if ('useLoginWithJWT' in this.environment) this.useJWT = this.environment.useLoginWithJWT; + if ('dontUseWindowsLogin' in this.environment) this.useWindowsLogin = !this.environment.dontUseWindowsLogin; + + // if (this.useJWT) { + // if (!this.checkJWT(this.environment.production ? 60 * 24 /* relogin one day before expiration*/ : 0)) this.loginStatus = this.EN_LoginStatus_Password; + // } else if (!this.useWindowsLogin) this.loginStatus = this.EN_LoginStatus_Password; + + if (parentService) throw new Error('Authorization service is already loaded. Import it in the AppModule only'); + + this.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { + // ACCOUNT_PAGE.hidden = false; + if (!(this.user.isAdmin) && this.environment.production && window) { + window.console.log = function () { }; + this.uiNotifier.isActive = false; + } + this.appLogsService.log(resultObject.errMsg, this.user); + this.uiNotifier.showMessage(this.translate.instant('core.msg.loggedon', { value: this.user.loginName })); + } else { + this.appLogsService.error(resultObject.errMsg); + this.uiNotifier.showMessage(`${resultObject.errMsg}`); + } + }); + + if (!!this.environment.sentry_dsn) { + this.loginLogout$.subscribe((user: CoreUser) => { + const scope = Sentry.getCurrentScope(); + scope.setUser({ + 'id': user?.webAppUserId.toString(), + 'shortname': user?.shortName, + 'username': user?.name, + 'login': user?.loginName, + }); + }); + } + + this.appLogsService.dlog('AuthorizeService is initialized'); + } + + + get user(): CoreUser { + return this._user; + } + + + set user(user: CoreUser) { + this._user = user; + } + + isLoggedIn(): boolean { + return this.isValidUser(); + } + + private isValidUser(): boolean { + return !this.isEmptyUser() && this.user.entityId !== 0; + } + + private isEmptyUser(): boolean { + return (!this._user) || this._user.isEmpty(); + } + + get loginname() { + return this.user?.loginName; + } + + get userName() { + return this.user?.name; + } + + logout(gotoLoginPage: boolean = true) { + this.loginStatus = this.EN_LoginStatus_Password; + this._user.clear(); + localStorage.removeItem('HR-JWToken'); + this.HR_JWT = undefined; + if (gotoLoginPage) { + if (this.isLoggedUserChanged()) this.loginLogout$.next(null); + this.lastLoggedUserId = null; + this.router.navigate(['/' + LOGIN_PAGE.path]); + } + } + + + login(loginname?: string, passw?: string) { + const loginWithPassword: boolean = !!loginname; + if (!loginWithPassword && !this.useJWT && !this.useWindowsLogin) return; + + const logController = loginWithPassword ? Cnst.cnst_LoginPassw_URL : (this.useJWT ? Cnst.cnst_LoginJWT_URL : Cnst.cnst_LoginAuth_URL); + const errorText = loginWithPassword ? this.translate.instant('core.error.logon') : this.translate.instant('core.error.logonnotpossible', { value: this.translate.instant(this.useJWT ? 'JWT-' : 'Windows-') }); + + this.user.loginName = loginname; + this.user.password = passw; + this.user.clientVersion = this.environment.appVersion; + + try { + this.user.timeZoneOffsetInMin = new Date().getTimezoneOffset(); + const loginObj$: Observable = this.repositoryService.postData(this.user.typeName + '/' + logController, this.user); + + if (loginWithPassword) { + this.HR_JWT = undefined; + this.user.culture = this.localeService.currentCulture; + this.user.language = this.localeService.currentLanguage; + } + + loginObj$.subscribe( + async (coreUser) => { + this.user.assign(coreUser); + + if (this.user.entityId) { + if (this.user.roleList && (this.user.isMaster || this.user.isInRolle(EN_UserRoles.DepartmentUser) || this.user.isInRolle(EN_UserRoles.User))) { + + if (loginWithPassword) { + this.jwtAuthentication(); + this.loginStatus = this.EN_LoginStatus_Password; + } else { + this.loginStatus = this.jwtAuthentication() ? this.EN_LoginStatus_JWT : this.EN_LoginStatus_Windows; + } + + if (!!coreUser.language) this.localeService.currentLanguage = coreUser.language; + if (!!coreUser.culture) this.localeService.currentCulture = coreUser.culture; + + if (coreUser.showDisclaimer && this.processDisclaimer) { + LoginPopupComponent.LOGIN_IS_SHOWN = true; //do not show Login poup + if (!await this.processDisclaimer(coreUser)) { + LoginPopupComponent.LOGIN_IS_SHOWN = false; + this.loginAction$.next({ result: false, errMsg: this.translate.instant('core.error.disclaimernotconfirmed') }); + // this.loginStatus = this.EN_LoginStatus_Password; //the order is important + return; + } + } + + if (this.isLoggedUserChanged()) this.loginLogout$.next(coreUser); + this.appLogsService.dlog('!! - eingelogged', new Date().toTimeString(), coreUser); + this.loginAction$.next({ result: true, entity: coreUser }); + this.lastLoggedUserId = coreUser.webAppUserId; + } else { + this.loginAction$.next({ result: false, errMsg: this.translate.instant('core.error.nouserrole'), entity: coreUser }); //roleList must be checked in backend + this.loginStatus = this.EN_LoginStatus_Password; //the order is important + } + } else { + this.loginAction$.next({ result: false, errMsg: coreUser['Message'] }); + this.loginStatus = this.EN_LoginStatus_Password; //the order is important + } + }, + error => { + this.loginAction$.next({ + result: false, errMsg: errorText + + (typeof error.error === 'string' && (error.error as string).indexOf('Exception') === -1 ? ' ' + error.error : '') + }); + this.loginStatus = this.EN_LoginStatus_Password; //the order is important + } + ); + } catch (error) { + this.loginStatus = this.EN_LoginStatus_Password; + this.appLogsService.dlog(logController + ' Unexpected Error', error); + } finally { + } + } + + + isLoggedUserChanged() { + return (this.lastLoggedUserId ?? 0) !== (this.user?.webAppUserId ?? 0); + } + + public checkJWT(correctionInMin?: number): boolean { + if (!this.HR_JWT) { + this.HR_JWT = JSON.parse(localStorage.getItem('HR-JWToken')) as HR_JWToken; + if (!this.HR_JWT?.idToken) return false; + if (this.HR_JWT) this.HR_JWT.expiresAt = new Date(this.HR_JWT?.expiresAt); + } + const expiresAt = this.HR_JWT.expiresAt; + if (correctionInMin === null || correctionInMin === undefined) return !!this.HR_JWT?.idToken; //correctionInMin === null - just load and check JWT + expiresAt.setMinutes(expiresAt.getMinutes() - correctionInMin); + return (!!this.HR_JWT?.idToken && Utils.isBefore(this.HR_JWT?.expiresAt)); + } + + + public jwtAuthentication(): boolean { + if (this.useJWT && this.user.token) { + this.user.jwtExpiredOn.setMinutes(this.user.jwtExpiredOn.getMinutes() + 1); + this.HR_JWT = new HR_JWToken(this.user.token, this.user.jwtExpiredOn); + localStorage.setItem('HR-JWToken', JSON.stringify(this.HR_JWT)); + return true; + } else return false; + } + + + loginPopup(errorMsg?: string, gotoLoginPage: boolean = false) { + if (LoginPopupComponent.LOGIN_IS_SHOWN) return; + LoginPopupComponent.LOGIN_IS_SHOWN = true; + this.logout(gotoLoginPage); + if ((errorMsg === null || errorMsg === undefined) && this.expiredJWTLogout) errorMsg = Cnst.cnst_JWT_Expired; + this.expiredJWTLogout = false; + this.dialog.openDialog(LoginPopupComponent, { errorMsg: errorMsg, authorizationService: this }, true, () => { }); + } + + + public async tryRenewJWTAsync(openLogin: boolean = true): Promise { + if (!this.useJWT) return false; + + if (LoginPopupComponent.LOGIN_IS_SHOWN || this.isRunningRenewJWT) return; + this.isRunningRenewJWT = true; + this.appLogsService.warn('Try to renew JWT'); + this.uiNotifier.showMessage(this.translate.instant('core.msg.renewJWT')); + this.spinnerService.show(); + try { + if (!this.HR_JWT || !await this.loginAsync()) { + if (openLogin) this.loginPopup(Cnst.cnst_JWT_Expired); + return false; + } + } + finally { + this.spinnerService.hide(); + this.isRunningRenewJWT = false; + } + return true; + } + + + public async loginAsync(): Promise { + return new Promise((resolve, reject) => { + const logisSubscription = + this.loginAction$.subscribe((resultObject) => { + logisSubscription.unsubscribe(); + resolve(resultObject.result); + }); + this.login(); + }); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/globals.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/globals.ts new file mode 100644 index 0000000..dda6594 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/globals.ts @@ -0,0 +1,249 @@ +import { Inject, Injectable, LOCALE_ID } from '@angular/core'; +import { Route } from '@angular/router'; +import { EN_LogType } from '../consts'; +import * as utils from '../utils'; +import { exportPivotGrid as exportPivotGridToExcel, exportDataGrid as exportDataGridToExcel } from 'devextreme/excel_exporter'; +import { exportDataGrid as exportDataGridToPDF } from 'devextreme/pdf_exporter'; +import { jsPDF, jsPDFOptions } from 'jspdf'; +import { Workbook } from 'exceljs'; +import { saveAs } from 'file-saver'; +import config from 'devextreme/core/config'; +import { licenseKey } from '../devextreme-license'; + + +export interface HRExportDataFromDxGrid { + gridComponent: any; + fileName: string; + title?: { + text?: string; + tabName?: string; + align?: 'left' | 'center' | 'right' | 'justify'; + x?: number; + y?: number; + divX?: number + }; + margin?: { top: number; right: number; bottom: number; left: number }; + pdfOptions?: jsPDFOptions; + repeatHeaders?: boolean; + customizeCallback?: (any) => void; + finalizeCallback?: () => void; +} + +export interface IMessageBoxButton { + title: string; + hint?: string; + code?: number; + default?: boolean; + cancel?: boolean; + callback?: () => void; +} + +export interface IMessageBoxData { + type: EN_LogType; + overHeader?: string; + header: string; + message: string; + buttons: IMessageBoxButton[]; +} + +export interface IAppPage extends Route { + caption: string; + icon?: string; + messageCaption?: string; + hidden?: boolean; + allowRedirect?: boolean; + disabled?: boolean; + showIconInNavbar?: boolean; + dontAllowEmptyURL?: boolean; +} + +export const LOGIN_PAGE: IAppPage = { + caption: 'core.caption.login', + path: 'login', + loadChildren: () => import('../components/login/login.module').then(m => m.LoginModule), + icon: 'logout', + allowRedirect: true, + hidden: true, + messageCaption: 'stammdaten', +}; + +export const ACCOUNT_PAGE: IAppPage = { + caption: 'core.caption.account', + path: 'account', + loadChildren: () => import('../components/account/account.module').then(m => m.AccountModule), + icon: 'account_circle', + hidden: false, + messageCaption: 'My Account', + showIconInNavbar: true +}; + +export enum EN_CoreEntities { + User = 'WebAppUser', + ServerInfo = 'Info' +} + +config({ licenseKey }); + + +@Injectable({ providedIn: 'root' }) + +export class Globals { + public hrColorDarkBlue: string = '#0b3a62'; + public hrColorLightBlue: string = '#78b7e5'; + public hrColorLightGrey: string = '#878787'; + public hrColorDarkGrey: string = '#3c3c3b'; + public hrColorGreen: string = '#76b82a'; + + public appTitle: string; + public appTitleWithVersion: string; + public currentPage: string; //path of the urrent page + public urlParam: string; //parameter in url + public mainPage: IAppPage; + public ipAddress: string; + public showIds: boolean = false; + + public appPages: IAppPage[] = [ + LOGIN_PAGE, + ]; + + constructor( + @Inject(LOCALE_ID) private locale: string + ) { } + + + isTheMainPage(page: string = null): boolean { + return this.isThePage(this.mainPage.path, page); + } + + isTheLoginPage(page: string = null): boolean { + return this.isThePage(LOGIN_PAGE.path, page); + } + + isTheCurrentPage(pageInx: number): boolean { + return this.isThePage(this.appPages[pageInx].path); + } + + isVisiblePage(page: string = null): boolean { + const pg = this.appPages.find((_pg: IAppPage) => this.isThePage(_pg.path, page)); + return (pg && !pg.hidden); + } + + isThePage(pagePath: string, page: string = null): boolean { + return page ? ((!page.startsWith('/') ? '/' : '') + page + '/').startsWith('/' + pagePath + '/') : (this.currentPage + '/').startsWith(pagePath + '/'); + } + + getPageIndex(page: string): number { + return this.appPages.findIndex((pg) => pg.path === page); + } + + + getPage(page: string): IAppPage { + const indx = this.getPageIndex(page); + return indx > -1 ? this.appPages[indx] : null; + } + + //------------------------------------------ + + public formatNumber(data: any, frac: number): string { + if (data === null || data === undefined) return ''; + if (typeof data === 'object') return utils.formatNumbers(this.locale, +data.value, frac); + else return utils.formatNumbers(this.locale, +data, frac); + } + + + formatNumber_0(data: any): string { + return this.formatNumber(data, 0); + } + + formatNumber_1(data: any): string { + return this.formatNumber(data, 1); + } + + formatNumber_2(data: any): string { + return this.formatNumber(data, 2); + } + + formatNumber_3(data: any): string { + return this.formatNumber(data, 3); + } + + formatNumber_4(data: any): string { + return this.formatNumber(data, 4); + } + + get localeDecimalSeparator(): string { + return utils.getDecimalSeparator(this.locale); + } + + get localeThousandSeparator(): string { + return utils.getThousandSeparator(this.locale); + } + + get localeDateFormat(): string { + return utils.getDateFormat(this.locale); + } + + get localeDateTimeFormat(): string { + return utils.getDateTimeFormat(this.locale); + } + + + exportToPDF(option: HRExportDataFromDxGrid) { + const doc = new jsPDF(option.pdfOptions); + doc.text(option.title.text, option.title.x ?? doc.internal.pageSize.width / option.title.divX, option.title.y ?? 15, { align: option.title.align ?? 'center' }); + exportDataGridToPDF({ + jsPDFDocument: doc, + component: option.gridComponent, + repeatHeaders: option.repeatHeaders ?? true, + margin: option.margin, + customizeCell: (options) => { if (option.customizeCallback) option.customizeCallback(options); } + }).then(() => { + doc.save(option.fileName); + if (option.finalizeCallback) option.finalizeCallback(); + }); + } + + + + public exportToExcel(option: HRExportDataFromDxGrid) { + const workbook = new Workbook(); + const worksheet = workbook.addWorksheet(option.title?.tabName ?? utils.removeSpecialChars(option.fileName)); + const self = this; + + const exportToExcel = 'dxPivotGrid' === option.gridComponent.NAME ? exportPivotGridToExcel : exportDataGridToExcel; + exportToExcel({ + component: option.gridComponent, + worksheet: worksheet, + topLeftCell: option.margin ? { row: option.margin.top, column: option.margin.left } : null, + customizeCell: (options) => { if (option.customizeCallback) option.customizeCallback(options); } + }).then(function () { + workbook.xlsx.writeBuffer() + .then((buffer: BlobPart) => { + saveAs(new Blob([buffer], { type: 'application/octet-stream' }), option.fileName + '.xlsx'); + }); + if (option.finalizeCallback) option.finalizeCallback(); + }); + } + + + public doExcelExportSimple(e: any, filename, dontExportFieldnameTemplatenameList?: string) { + this.exportToExcel({ + fileName: filename + , gridComponent: e.component + , customizeCallback: 'dxPivotGrid' === e.component.NAME && !!dontExportFieldnameTemplatenameList ? this.dontExportFieldnameTemplatename.bind(this, dontExportFieldnameTemplatenameList) : null + }); + } + + + private dontExportFieldnameTemplatename(dontExportFieldnameTemplatenameList: string, options: any) { + const { gridCell, excelCell } = options; + dontExportFieldnameTemplatenameList = ',' + dontExportFieldnameTemplatenameList.replace(' ', '').toLocaleLowerCase() + ','; + + if (!!gridCell.column?.cellTemplate && dontExportFieldnameTemplatenameList.indexOf(',#' + gridCell.column?.cellTemplate.toLocaleLowerCase() + ',') > -1 + || !!gridCell.column?.dataField && dontExportFieldnameTemplatenameList.indexOf(',' + gridCell.column?.dataField.toLocaleLowerCase() + ',') > -1 + ) { + excelCell.value = null; + excelCell._column.hidden = true; + } + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/http/http-interceptor.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/http/http-interceptor.service.ts new file mode 100644 index 0000000..16a48aa --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/http/http-interceptor.service.ts @@ -0,0 +1,157 @@ +import { Injectable, Inject } from '@angular/core'; +import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpHeaders, HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError, tap, finalize } from 'rxjs/operators'; +import { AppLogsService } from '../applogs.service'; +import { AuthorizeService } from '../authorize.service'; +import * as Utils from '../../utils'; +import * as Const from '../../consts'; +import { InMemoryDataService } from '../in-memory-data.service'; +import { ENVIRONMENT_TOKEN, IENVIRONMENT } from '../../injection-tokens'; + +@Injectable({ + providedIn: 'root' +}) + +export class HttpInterceptorService implements HttpInterceptor { + constructor( + private appLogsservice: AppLogsService, + private authorizeService: AuthorizeService, + private mockDataService: InMemoryDataService, + @Inject(ENVIRONMENT_TOKEN) private environment: IENVIRONMENT, + ) { } + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + const clone = request.clone(this.prepareOptions(request.headers)); + + const guid = Utils.guid(); + const operation = `${request.method}: ${request.url}`; + this.appLogsservice.dlog('%c# HTTP Request ' + operation, { guid: guid }, 'color:' + Const.EN_AppColors.startRequestColor); + let ok: string; + + const splittedURL = request.url.split(/\//g); + let querySufix: string = ''; + const base: number = splittedURL[4] ? 4 : 3; + if (request.method === 'GET') { + querySufix = splittedURL[base] + (splittedURL.length < base + 2 ? ': list' : ''); + } else { + for (let i = base; i < splittedURL.length; i++) { + querySufix += (i === base ? '' : '/') + splittedURL[i]; + } + } + + const mockDataResponse: Observable> = this.mockDataService.parseMockData(request, guid); + if (mockDataResponse) return mockDataResponse; + + return next.handle(clone) + .pipe( + tap({ + next: (event: HttpEvent) => ok = event instanceof HttpResponse ? 'SUCCEDED' : '', + error: (error: HttpErrorResponse) => ok = 'FAILED', + complete: () => { this.appLogsservice.dlog(querySufix, { guid: guid }, 'color:' + Const.EN_AppColors.returnRequestColor); } + } + ), + + //retry(2), + catchError((error: HttpErrorResponse) => { + + // this.appLogsservice.error(Utils.getErrorMessageAsText(error), { error }); + this.appLogsservice.exception(error); + + if (error.status === Const.cnst_ErrorCode4Unauthorized) { // 401 handled in auth.interceptor + // this.authorizeService.loginPopup(Const.cnst_JWT_Expired); + this.authorizeService.tryRenewJWTAsync(); + } + return throwError(() => error); + }), + // Log when response observable either completes or errors + // finalize( + // () => { this.appLogsservice.log(querySufix, { guid: guid }, 'color:' + Const.EN_AppColors.returnRequestColor); } + // ), + ) + ; + } + + + prepareOptions(sentHeader?: HttpHeaders, withBearer: boolean = true): any { + let headerAdditionalKeys: HttpHeaders = null; + if (!!this.environment.headerData) headerAdditionalKeys = new HttpHeaders(this.environment.headerData); + + let header: HttpHeaders = null; + if (sentHeader) header = sentHeader; + else { + header = new HttpHeaders(); + header = header + .append('Content-Type', 'application/json') + .append('Accept', 'application/json'); + } + //if (headerAdditionalKeys) header = header.append(headerAdditionalKeys.getAll); + + if (withBearer && this.authorizeService.useJWT && this.authorizeService.HR_JWT) header = header.append('Authorization', 'Bearer ' + this.authorizeService.HR_JWT.idToken); + const withCredent: boolean = this.authorizeService.loginStatus === this.authorizeService.EN_LoginStatus_Windows || + this.authorizeService.loginStatus === this.authorizeService.EN_LoginStatus_Unknown && !this.authorizeService.useJWT && !headerAdditionalKeys; + return { + headers: header, + withCredentials: withCredent + }; + } + /* intercept(request: HttpRequest, next: HttpHandler): Observable> { + + const users: User[] = [ + { id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' } + ]; + + const authHeader = request.headers.get('Authorization'); + const isLoggedIn = authHeader && authHeader.startsWith('Bearer fake-jwt-token'); + + // wrap in delayed observable to simulate server api call + return of(null).pipe(mergeMap(() => { + + // authenticate - public + if (request.url.endsWith('/users/authenticate') && request.method === 'POST') { + const user = users.find(x => x.username === request.body.username && x.password === request.body.password); + if (!user) return error('Username or password is incorrect'); + return ok({ + id: user.id, + username: user.username, + firstName: user.firstName, + lastName: user.lastName, + token: `fake-jwt-token` + }); + } + + // get all users + if (request.url.endsWith('/users') && request.method === 'GET') { + if (!isLoggedIn) return unauthorised(); + return ok(users); + } + + // pass through any requests not handled above + return next.handle(request); + })) + // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648) + .pipe(materialize()) + .pipe(delay(500)) + .pipe(dematerialize()); + + // private helper functions + + function ok(body) { + return of(new HttpResponse({ status: 200, body })); + } + + function unauthorised() { + return throwError({ status: 401, error: { message: 'Unauthorised' } }); + } + + function error(message) { + return throwError({ status: 400, error: { message } }); + } + }*/ +} +// export let fakeBackendProvider = { +// // use fake backend in place of Http service for backend-less development +// provide: HTTP_INTERCEPTORS, +// useClass: FakeBackendInterceptor, +// multi: true +// }; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/http/repository.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/http/repository.service.ts new file mode 100644 index 0000000..828f866 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/http/repository.service.ts @@ -0,0 +1,93 @@ +import { Inject, Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { AppLogsService } from '../applogs.service'; +import { cnst_IP_ADDRESS_SOURCE_URL } from '../../consts'; +import { AuthorizeService } from '../authorize.service'; +import { ENVIRONMENT_TOKEN, IENVIRONMENT } from '../../injection-tokens'; + +@Injectable({ + providedIn: 'root' +}) +export class RepositoryService { + public authService: AuthorizeService; + private apiUrl: string; + + constructor( + private httpClient: HttpClient, + private appLogService: AppLogsService, + @Inject(ENVIRONMENT_TOKEN) environment: IENVIRONMENT, + ) { + this.apiUrl = environment.apiUrl; + } + + // tslint:disable-next-line: no-shadowed-variable + deleteDataById(routing: string, id: string | number): Observable { + // tslint:disable-next-line: triple-equals + const filterstr = (id && id != '0' ? '/' + id.toString() : ''); + return this.httpClient.delete(this.apiUrl + '/' + routing + filterstr).pipe(map(response => response as T)); + } + + getDataById(routing: string, id: string | number): Observable { + // tslint:disable-next-line: triple-equals + const filterstr = (id && id != '0' && id != -1 ? '/' + id.toString() : ''); + return this.getDataByURLFilter(routing, filterstr); + } + + + putDataById(routing: string, id: string | number, obj: any): Observable { + // tslint:disable-next-line: triple-equals + // if (id && !Number.isNaN(Number(id)) && id != '0') + return this.putData(routing + '/' + id.toString(), obj); + } + + + postDataById(routing: string, id: string | number, obj: any): Observable { + // tslint:disable-next-line: triple-equals + let suffix: string = ''; + if (typeof id === 'number' || !Number.isNaN(Number(id))) { + if (Number(id) > 0) suffix = id.toString(); + } else suffix = id; + const filterstr = (suffix ? '/' + suffix : ''); + return this.postData(routing + filterstr, obj); + } + + + getDataByObjFilter(routing: string, filter: any): Observable { + this.appLogService.dlog('filter=', filter); + return this.postData(routing + (filter.filterPrefix ? '/' + filter.filterPrefix : ''), filter); + } + + + getDataByURLFilter(routing: string, filter: string): Observable { + return this.getData(routing + (filter && filter !== '' ? ((filter).slice(0, 1) !== '/' ? '/' : '') + filter : '')/*, getMethodName()*/); + } + + public putData(routing: string, obj: any, headers?: HttpHeaders): Observable { + return this.httpClient.put(this.apiUrl + '/' + routing, obj, { headers: headers }).pipe(map(response => response as T)); + } + + + public postData(routing: string, obj: any, headers?: HttpHeaders): Observable { + return this.httpClient.post(this.apiUrl + '/' + routing, obj, { headers: headers }).pipe(map(response => response as T)); + } + + public getData(routing: string, headers?: HttpHeaders): Observable { + return this.httpClient.get(this.apiUrl + '/' + routing, { headers: headers }).pipe(map(response => response as T)); + } + + public getIPAddress(): Observable { + return this.httpClient.get(cnst_IP_ADDRESS_SOURCE_URL); + } + + // public async getData(routing: string, headers?: HttpHeaders): Promise> { + // return this.httpClient.get(this.apiUrl + '/' + routing, { headers: headers }) + // .pipe( + // map(response => of(response as T)) + // , catchError(async (error: any) => { + // return of(null); + // })).toPromise(); + // } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/in-memory-data.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/in-memory-data.service.ts new file mode 100644 index 0000000..53cc190 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/in-memory-data.service.ts @@ -0,0 +1,63 @@ +import { InMemoryDbService } from 'angular-in-memory-web-api'; +import { Observable, of } from 'rxjs'; +import { HttpEvent, HttpResponse, HttpRequest } from '@angular/common/http'; +import * as Const from '../consts'; +import { AppLogsService } from './applogs.service'; +import { Injectable } from '@angular/core'; +import { delay } from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) + +export class InMemoryDataService implements InMemoryDbService { + + constructor(private appLogsService: AppLogsService) { } + createDb() { + return {}; + } + + parseMockData(request: HttpRequest, guid: string): Observable> { + return undefined; + } + + + mockingInterception(request: HttpRequest, splittedURL: string[], filterStr: string, guid: string) { + let resp: Observable> = null; + switch (request.method) { + case 'PUT': + case 'POST': + resp = this.postMockData(request.body); + break; + case 'GET': + resp = this.getMockData(splittedURL[4], filterStr); + break; + case 'DELETE': + resp = this.deleteMockData(+splittedURL[5]); + break; + } + if (resp) { + this.appLogsService.dlog(splittedURL[4] + (splittedURL.length < 6 ? ': list' : ''), { guid: guid }, 'color:' + Const.EN_AppColors.returnRequestColor); + return resp.pipe(delay(500)); + } + } + + + getMockData(entityBase: string, entityFilterstring: string): Observable> { + return of(new HttpResponse( + { status: 200, body: this.getFilteredDataList(entityFilterstring) } + )); + } + + postMockData(entity: any): Observable> { + return of(new HttpResponse({ status: 200, body: Object.assign({}, entity) })); + } + + deleteMockData(id: number): Observable> { + return of(new HttpResponse({ status: 200 })); + } + + getFilteredDataList(entityFilterstring: string): any { + return null; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/localization/hensel-translate.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/hensel-translate.service.ts new file mode 100644 index 0000000..b5253b0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/hensel-translate.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; + +@Injectable({ + providedIn: 'root', +}) + +export class HenselTranslateService extends TranslateService { + + public instant(key: string | Array, interpolateParams?: Object): string | any { + if (!key) return ''; + return super.instant(key, interpolateParams); + } + + public translateString(stringToTranslate: string) { + let res = stringToTranslate?.replace(/\${(.*?)}/g, (found: string, translationKey: string) => this.instant(translationKey)); + if (res === stringToTranslate) res = this.instant(res); // source string does not contain placeholder "${}" - try to translate directly + return res; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.provider.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.provider.ts new file mode 100644 index 0000000..af6f5d1 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.provider.ts @@ -0,0 +1,23 @@ +import { LOCALE_ID, Provider } from '@angular/core'; +import { LocaleService } from './locale.service'; + +export class LocaleId extends String { + constructor(private localeService: LocaleService) { + super(); + } + + toString(): string { + return this.localeService.currentCulture; + } + + valueOf(): string { + return this.toString(); + } +} + + +export const LocaleProvider: Provider = { + provide: LOCALE_ID, + useClass: LocaleId, + deps: [LocaleService], +}; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.service.ts new file mode 100644 index 0000000..8665b63 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/locale.service.ts @@ -0,0 +1,119 @@ +import { Injectable, Optional, SkipSelf } from '@angular/core'; +import { ActivatedRouteSnapshot, Router } from '@angular/router'; +import { noop } from 'rxjs'; +import * as localization from 'devextreme/localization'; +import * as deMessages from 'devextreme/localization/messages/de.json'; +import * as enMessages from 'devextreme/localization/messages/en.json'; +import * as frMessages from 'devextreme/localization/messages/fr.json'; +import { getCurrencySymbol, getDateFormat, getDateTimeFormat, getDecimalSeparator, getLocaleCurrencyCode, getThousandSeparator } from '../../utils'; +import { HenselTranslateService } from './hensel-translate.service'; + +const langMessages: { [key: string]: any } = { en: enMessages, de: deMessages, fr: frMessages }; + +type ShouldReuseRoute = (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) => boolean; + +@Injectable({ + providedIn: 'root', +}) + + +export class LocaleService { + + + public dateFormat: string; + public dateTimeFormat: string; + public thousandSeparator: string; + public decimalSeparator: string; + public currencyCode: string; + public currencySymbol: string; + + private initialized = false; + + private _currentCulture: string; + get currentCulture(): string { + return this._currentCulture; + } + set currentCulture(culture: string) { + const oldCulture = this._currentCulture; + this.setCultureWOReload(culture); + if (oldCulture !== culture) setTimeout(() => this.reloadPages()); + } + + set currentLocale(culture: string) { + this.setCultureWOReload(culture); + this.currentLanguage = culture; + } + + private _currentLanguage: string; + get currentLanguage(): string { + return this._currentLanguage; + } + set currentLanguage(lang: string) { + this._currentLanguage = lang.split('-')[0]; //it can take culture as argument too + // locale(this.currentLanguage); + this.translate.use(lang); + } + + constructor( + private router: Router, + public translate: HenselTranslateService, + @Optional() + @SkipSelf() + otherInstance: LocaleService, + ) { + if (otherInstance) throw new Error('LocaleService should have only one instance.'); + } + + + private setCultureWOReload(culture: string) { + this._currentCulture = culture; + this.dateFormat = getDateFormat(culture); + this.dateTimeFormat = getDateTimeFormat(culture); + this.thousandSeparator = getThousandSeparator(culture); + this.decimalSeparator = getDecimalSeparator(culture); + this.currencyCode = getLocaleCurrencyCode(culture); + this.currencySymbol = getCurrencySymbol(culture); + + // const lang = culture.split('-')[0]; + // const messages = {}; + // messages[lang] = langMessages[this.currentLanguage]; + // localization.loadMessages(messages); + localization.locale(culture); + } + + private setRouteReuse(reuse: ShouldReuseRoute) { + this.router.routeReuseStrategy.shouldReuseRoute = reuse; + } + + private subscribeToLangChange() { + this.translate.onLangChange.subscribe(() => { + this.reloadPages(); + }); + } + + + reloadPages = async () => { + const { shouldReuseRoute } = this.router.routeReuseStrategy; + + this.setRouteReuse(() => false); + this.router.navigated = false; + + await this.router.navigateByUrl(this.router.url).catch(noop); + this.setRouteReuse(shouldReuseRoute); + } + + + initLocaleLanguage(culture: string, lang?: string) { + if (this.initialized) return; + + this.setCultureWOReload(culture); + this.currentLanguage = lang ?? culture; + this.translate.setDefaultLang(this.currentLanguage); + setTimeout(() => this.subscribeToLangChange(), 1000); //delay avoid to fire onLangChange at the init - app start, otherwise start url will be overwritten + + this.initialized = true; + console.log('Locale is initialized !!'); + } + + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/localization/translation-loader.provider.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/translation-loader.provider.ts new file mode 100644 index 0000000..d37e20d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/localization/translation-loader.provider.ts @@ -0,0 +1,22 @@ +import { Provider } from '@angular/core'; +import { TranslateLoader } from '@ngx-translate/core'; +import { HttpBackend } from '@angular/common/http'; +import { MultiTranslateHttpLoader } from 'ngx-translate-multi-http-loader'; +import { ENVIRONMENT_TOKEN, IENVIRONMENT } from '../../injection-tokens'; + + + +export function HttpLoaderFactory(_httpBackend: HttpBackend, environment: IENVIRONMENT): TranslateLoader { + return new MultiTranslateHttpLoader(_httpBackend, [ + { prefix: './assets/translate-core/', suffix: '.json' }, + { prefix: environment.translationFolder, suffix: '.json' }, + ] + ); +} + + +export const TranslateLoaderProvider: Provider = { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpBackend, ENVIRONMENT_TOKEN], +}; diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/mat-dialog.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/mat-dialog.service.ts new file mode 100644 index 0000000..a90f7f8 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/mat-dialog.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { PopupBaseComponent } from '../components/popup-base/popup-base.component'; +import { MatDialog, MatDialogConfig, MatDialogRef } from '../components/angular-material-index'; + +@Injectable({ + providedIn: 'root' +}) +export class MatDialogService { + + constructor(private dialog: MatDialog) { } + + public openDialog(dialogComponent: any, dataObject: Object, isModal: boolean = false, onCloseDialog?: (_) => void, autofocus: boolean = true): + MatDialogRef { + const dialogConfig = new MatDialogConfig(); + if (dialogComponent instanceof PopupBaseComponent) isModal = true; // we open derived from PopupBaseComponent popup dialogs + // only as modal to shure executing of cancel function, thats reset BaseEntityWrapper + dialogConfig.disableClose = isModal; + dialogConfig.autoFocus = autofocus; + dialogConfig.data = dataObject; + const dialog = this.dialog.open(dialogComponent, dialogConfig); + dialog.afterClosed().subscribe(result => { + if (onCloseDialog) onCloseDialog(result); + }); + return dialog; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotification.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotification.ts new file mode 100644 index 0000000..50f036d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotification.ts @@ -0,0 +1,46 @@ +export enum EN_UINotificationType { + info = 1, + warn = 2 +} +export class UINotification { + + message: string; + type: EN_UINotificationType; + isActive: boolean; + createdTimestamp: Date; + displayedTimestamp: Date; + finishedTimestamp: Date; + duration: number; + id: number; + + constructor(message: string, type: EN_UINotificationType, duration: number, id: number) { + this.message = message; + this.isActive = true; + this.type = type; + this.createdTimestamp = new Date(); + this.duration = duration; + this.id = id; + } + + public stopMessage(): void { + this.finishedTimestamp = new Date(); + this.isActive = false; + } + + public durationExpired(timeInSeconds: number) { + if (this.displayedTimestamp && this.duration > 0) { + if (timeInSeconds >= this.displayedTimestamp.getTime() + this.duration) { + return true; + } + } + return false; + } + + public getStyleColor(): string { + if (this.type === EN_UINotificationType.info) { + return 'secondary'; + } else { + return 'primary'; + } + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotifier.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotifier.service.ts new file mode 100644 index 0000000..aa39734 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/notification/uinotifier.service.ts @@ -0,0 +1,187 @@ +import { Injectable } from '@angular/core'; +import { interval, Subject, Subscription } from 'rxjs'; +import { AppLogsService } from '../applogs.service'; +import { EN_UINotificationType, UINotification } from './uinotification'; +import { MatSnackBar, MatSnackBarConfig, MatSnackBarHorizontalPosition, MatSnackBarRef, MatSnackBarVerticalPosition, TextOnlySnackBar } from '../../components/angular-material-index'; + + +const cnst_NotifierNachrichtDauer = 1000; +const nachrichtVisible = true; + +class HenselMatSnackBarConfig extends (MatSnackBarConfig) { + constructor(obj: any) { + super(); + Object.assign(this, obj); + } +} + +@Injectable({ + providedIn: 'root' +}) +export class UINotifierService { + private readonly MAX_INACTIVE_ITEMS: number = 5; + private activeItems: UINotification[]; + private inactiveItems: UINotification[]; + private idCounter: number; + + msbPoxPosition: { horizontal: MatSnackBarHorizontalPosition, vertical: MatSnackBarVerticalPosition } = { horizontal: 'center', vertical: 'bottom' }; + + public data$: Subject; + public isActive: boolean = true; + protected pollingItervalTimer: Subscription = null; + private currentSnackBar: MatSnackBarRef; + + constructor( + private appLogsService: AppLogsService, + public snackBar: MatSnackBar, + ) { + this.data$ = new Subject(); + this.data$.subscribe((lastNotification: UINotification) => this.showNotification(lastNotification)); + + this.activeItems = []; + this.inactiveItems = []; + this.idCounter = 1; + } + + + stopPolling() { + this.hide(); + this.pollingItervalTimer?.unsubscribe(); + this.pollingItervalTimer = null; + } + + + startPolling() { + if (!this.pollingItervalTimer) this.pollingItervalTimer = interval(100).subscribe(this.checkinOnTimer); + } + + + private checkinOnTimer = () => { + if (this.activeItems.length === 0) { + this.stopPolling(); + } else { + // this.appLogsService.dlog('->timer active:' + this.activeItems.length + ', inactive' + this.inactiveItems.length); + const start = new Date().getTime(); + let item = this.activeItems[0]; + if (item.durationExpired(start)) { + this.stopMessage(item.id); + if (this.activeItems.length > 0) item = this.activeItems[0]; + } + if (item && !item.displayedTimestamp) this.data$.next(item); + // this.appLogsService.dlog('<-timer active:' + this.activeItems.length + ', inactive' + this.inactiveItems.length); + } + } + + + + // remove last MAX_INACTIVE_ITEMS + cleanUp(item: UINotification) { + const index: number = this.activeItems.indexOf(item); + if (index !== -1) this.activeItems.splice(index, 1); + this.inactiveItems.splice(0, 0, item); // neueste zuerst + + if (this.inactiveItems.length > this.MAX_INACTIVE_ITEMS) { + this.inactiveItems.splice(this.MAX_INACTIVE_ITEMS); + } + + } + + clearAll() { + this.activeItems = []; + this.inactiveItems = []; + } + + private createNew(message: string, type: EN_UINotificationType, duration: number): UINotification { + this.idCounter++; + return new UINotification(message, type, duration, this.idCounter); + } + + public getActiveItems(): UINotification[] { + return this.activeItems; + } + + public getInactiveItems(): UINotification[] { + return this.inactiveItems; + + } + public isVisible(): boolean { + return this.activeItems.length > 0; + } + + public getInactiveMessages(): string { + let msg = ''; + this.inactiveItems.forEach((item: UINotification) => { + msg += item.message + '; '; + }); + + return msg; + } + + public getActiveMessages(): string { + let msg = ''; + this.activeItems.forEach((item: UINotification) => { + msg += item.message + '; '; + }); + return msg; + } + + // return: new id + public showMessage(message: string, msgId?: number, duration: number = cnst_NotifierNachrichtDauer): number { + return this.add2Queue(message, msgId, duration, EN_UINotificationType.info); + } + + public showWarning(message: string, msgId?: number, duration: number = cnst_NotifierNachrichtDauer): number { + return this.add2Queue(message, msgId, duration, EN_UINotificationType.warn); + } + + private add2Queue(message: string, msgId: number, duration: number = cnst_NotifierNachrichtDauer, notifType: EN_UINotificationType): number { + if (!this.isActive) return; + if (msgId) { this.stopMessage(msgId); } + const item = this.createNew(message, notifType, duration); + if (this.activeItems.length > 0) { + const lastWaitingItim = this.activeItems[this.activeItems.length - 1]; + if (!lastWaitingItim.displayedTimestamp) lastWaitingItim.duration /= 4; + } + this.activeItems.push(item); + this.startPolling(); + return item.id; + } + + public stopMessage(id: number) { + const foundItem = this.activeItems.find((item: UINotification) => item.id === id); + if (foundItem) { + foundItem.stopMessage(); + this.cleanUp(foundItem); + } + } + + public updateMessage(id: number, message: string) { + this.appLogsService.dlog('updateMessage id:' + id + ' ' + message); + const foundedItem = this.activeItems.filter((item: UINotification) => item.id === id); + if (foundedItem && foundedItem[0]) { + this.appLogsService.dlog('found updateMessage id:' + id + ' ' + message); + + foundedItem[0].message = message; + } + } + + hide() { + this.appLogsService.dlog('<-Hide Message'); + this.snackBar.dismiss(); + } + + + showNotification(lastNotification: UINotification): void { + this.hide(); + lastNotification.displayedTimestamp = new Date(); + this.currentSnackBar = this.snackBar.open(lastNotification.message, undefined, new HenselMatSnackBarConfig( + { + horizontalPosition: this.msbPoxPosition.horizontal, + verticalPosition: this.msbPoxPosition.vertical, + duration: lastNotification.duration, + panelClass: 'hensel-notifier' + } + )); + this.appLogsService.dlog('Show Message id:' + lastNotification.id + ' ' + lastNotification.message); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/page.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/page.service.ts new file mode 100644 index 0000000..a7599f9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/page.service.ts @@ -0,0 +1,245 @@ +import { PageLoadingService } from '../services/pageloading.service'; +import { Globals, IAppPage } from './globals'; +import { AppLogsService } from './applogs.service'; +import { AuthorizeService } from './authorize.service'; +import { CoreUser } from '../models/coreuser'; +import { Router } from '@angular/router'; +import { BaseEntity, BaseEntityCallBack, ErrorCallBack } from '../models/generics/baseentity'; +import { BaseEntityListWrapper } from '../models/generics/baseentitylist.wrapper'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { HenselTranslateService } from './localization/hensel-translate.service'; +import { inject } from '@angular/core'; +import { BaseEntityWrapper } from '../models/generics/baseentity.wrapper'; +import { MatDialogService } from './mat-dialog.service'; +import { LocaleService } from './localization/locale.service'; +import { RepositoryService } from './http/repository.service'; + +export class CorePageService { + protected appPage: number; + protected get applicationPage(): any { + return this.appPage; + } + protected get appPageNoQueries(): number { + return 0; + } + protected standAlone: boolean = true; //true = page data are not depended from the global data.service, and must be loaded explicetely + + protected loadImedeately: boolean = false; //load on opening the page + protected entityList4Routing: BaseEntityListWrapper; + public loadedOverRoutingCallBack: BaseEntityCallBack = null; + public loadRoutingEntityCallBack: (entityId: number, _loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) => void; + public loadedOverRoutingOneTimeCallBack: BaseEntityCallBack = null; + public lastURL: string; + public pageBaseDateWereLoaded$: BehaviorSubject = new BehaviorSubject(false); + private _loadFromTheSamePage: boolean = false; + public get loadFromTheSamePage(): boolean { + return this._loadFromTheSamePage; + } + protected set loadFromTheSamePage(value: boolean) { + this._loadFromTheSamePage = value; + } + private _isLoadingOverRouting: boolean = false; + public get isLoadingOverRouting(): boolean { + return this._isLoadingOverRouting; + } + protected set isLoadingOverRouting(value: boolean) { + this._isLoadingOverRouting = value; + } + protected translationService = inject(HenselTranslateService); + protected globalsService: Globals = inject(Globals); + protected pageLoadingService: PageLoadingService = inject(PageLoadingService); + protected appLogsService: AppLogsService = inject(AppLogsService); + protected authService?: AuthorizeService = inject(AuthorizeService); + protected router?: Router = inject(Router); + protected dialog: MatDialogService = inject(MatDialogService); + protected localeService: LocaleService = inject(LocaleService); + protected repoService: RepositoryService = inject(RepositoryService); + + protected backgroundLoading: boolean = false; //no need background loading at first time + + protected baseEntityWrapperWaitLoadingSubscription: Subscription; + public set baseEntityWrapperWaitLoading(pageDetails: BaseEntityWrapper) { + this.baseEntityWrapperWaitLoadingSubscription = pageDetails.entityIsLoading$.subscribe((isLoading: boolean) => { + if (isLoading) this.pageLoadingService.showSpinner(); + else this.pageLoadingService.hideSpinner(); + }); + } + + + protected isPageActive(): boolean { + return this.globalsService.currentPage === this.globalsService.appPages[this.applicationPage].path; + } + + constructor( + ) { + this.finalise = this.finalise.bind(this); + this.pageLoadingService.pageActive$.subscribe((param?: string) => { + if (this.isPageActive()) { + setTimeout(() => this.onPageActivated(param)); + } else this.loadFromTheSamePage = false; + }); + + if (this.authService) { + this.authService.loginLogout$.subscribe((user: CoreUser) => { + setTimeout(() => this.onLoggedInOut(new CoreUser(user)), 0); //wait till oncreate is finished + }); + } + } + + protected init( + ) { + this.lastURL = '/' + this.globalsService.appPages[this.applicationPage].path; + + if (//!this.globalsService.isTheMainPage() && !this.standAlone || // do not need, because if !this.standAlone, then forgroundLoading$ fires imedeately after create the service, because it is a behaviour + //after creating loads data for not standalone page except main page - for it loading is calling after stammdata are loaded on forgroundLoading$ event + this.loadImedeately && this.standAlone // or load data always the page is created and is standalone (depends from data another pages) + || this.isPageActive() && this.globalsService.urlParam) //or not created page is opened with the id as url param + { + setTimeout(() => this.onPageActivated(this.isPageActive() ? this.globalsService.urlParam : null)); //must fire after init and onLoggedInOut + } + + if (!this.standAlone) { + this.pageLoadingService.forgroundLoading$.subscribe(() => { if (this.isPageActive()) this.loadData(); }); //load data if it is the current page + //if page is loadImedeately - is loaded on activating - there is no sense to load it in bachground + if (!this.loadImedeately) this.pageLoadingService.backgroundLoading$.subscribe(() => { if (!this.isPageActive()) this.loadData(); }); //load data in background if it is not the current page + } + } + + protected onPageActivated(param: string) { + this.doRouting4Id(param); + } + + + private loadOnPageAcivated() { + this.backgroundLoading = false; //no need background loading + this.loadData(); + } + + + protected finalise() { + this.pageLoadingService.updatePageLoadedCounters(this.appPage); + } + + + protected doRouting4Id(paramId: string | number) { + if (this.entityList4Routing) { + if (!paramId /*|| Number.isNaN(Number(paramId)) || Number(paramId) === 0*/) { //without parameters + if (this.loadImedeately && !this.loadFromTheSamePage) this.loadOnPageAcivated(); + else { + if (!this.entityList4Routing.focusedItemId) { + if (this.entityList4Routing.focusedEntityShadowed) { + this.entityList4Routing.focusedEntityShadowed.clear(); + this.entityList4Routing.focusedEntityShadowed.entityIsLoading = false; // to fire loaded$ for empty lists + } + } else this.entityList4Routing.focusedRoutingCallBack(this.entityList4Routing.focusedItem); + } + this.loadFromTheSamePage = false; + } else { + if (!Number.isNaN(Number(paramId)) + && Number(paramId) !== 0 + && this.entityList4Routing.focusedEntityShadowed + && this.entityList4Routing.focusedEntityShadowed.inViewMode + ) { //load details entity from the url params + let loadFn: (entityId: number, _loadedCallBack?: BaseEntityCallBack, _errorCallBack?: ErrorCallBack, _completeCallBack?: () => void) => void; + this.isLoadingOverRouting = true; + + if (this.loadRoutingEntityCallBack) { + loadFn = this.loadRoutingEntityCallBack; + } else loadFn = this.entityList4Routing.focusedEntityShadowed.load.bind(this.entityList4Routing.focusedEntityShadowed); + + loadFn(Number(paramId), + (entity) => { + if (!entity || !entity.entityId) { + this.navigateLastURL(); + } else { + this.lastURL = this.router?.url; + if (this.loadedOverRoutingOneTimeCallBack) { + this.loadedOverRoutingOneTimeCallBack(); + this.loadedOverRoutingOneTimeCallBack = null; + } else { + if (this.loadedOverRoutingCallBack) this.loadedOverRoutingCallBack(); + } + } + this.isLoadingOverRouting = false; + }, + () => { + this.isLoadingOverRouting = false; + this.navigateLastURL(); + }, + () => { //in the case of empty master list the wrapper is simple cleared and no loade only completed dcallbak is called + this.isLoadingOverRouting = false; + } + ); + this.loadFromTheSamePage = false; + } else this.navigateLastURL(); + } + } else { + if (this.loadImedeately) this.loadOnPageAcivated(); + } + } + + + public navigateLastURL() { + this.router.navigate([this.lastURL]); + } + + + public activateRouting4EntityList(entityList: BaseEntityListWrapper, loadedOverRoutingCallBack?: BaseEntityCallBack) { + this.entityList4Routing = entityList; + this.loadedOverRoutingCallBack = loadedOverRoutingCallBack; + entityList.focusedRoutingCallBack = this.focusedRoutingCallBack.bind(this); + } + + + public focusedRoutingCallBack(focusedItem: BaseEntity | number) { + if (!this.isPageActive()) return; + const entityId: number = (typeof focusedItem === 'number') ? focusedItem : (focusedItem?.entityId || 0); + const currentEntity = this.entityList4Routing.focusedEntityShadowed; + if ((entityId > 0) && currentEntity && this.globalsService.urlParam === entityId.toString()) { + if (currentEntity.inViewMode) { + if (currentEntity.entityId === entityId) currentEntity.reload(); + else currentEntity.entityId = entityId; + } + } else { + this.loadFromTheSamePage = true; + const url = this.router.serializeUrl(this.router.createUrlTree([this.globalsService.appPages[this.applicationPage].path, entityId > 0 ? entityId : ''])); + if (this.router?.url + '/' !== url) { + //don't override routing during loading of entity + if (!this.isLoadingOverRouting) { + this.lastURL = url; + this.router.navigate([url]); + } + } else if (this.entityList4Routing?.focusedEntityShadowed) this.entityList4Routing.focusedEntityShadowed.entityIsLoading = false; // to fire loaded$ for empty lists + } + } + + + protected onLoggedInOut(user: CoreUser) { + if (!this.authService.isLoggedIn()) this.clearData(); //clears data only during logout - otherwise can id in url can be lost + } + + + public clearData() { + } + + + protected loadData(callback?: () => void) { + const isActivePage = this.isPageActive(); + if (isActivePage || !this.pageLoadingService.spinnerVisible) { + // if called from constructor or is standalone or loaded at first time - no background loading is needed + const needBackgroungLoadingOfDependendPages = isActivePage && !this.standAlone && this.backgroundLoading; //&& this.pageLoadingService.noOfHttpQueries4Page[this.applicationPage] !== -1; + this.backgroundLoading = !this.standAlone; + this.pageLoadingService.startSpinner(needBackgroungLoadingOfDependendPages, callback); + } + this.pageLoadingService.noOfHttpQueries4Page[this.applicationPage] = this.appPageNoQueries; //means, that page service is iniatilised + this.appLogsService.dlog('%c' + this.translationService.instant(this.globalsService.appPages[this.applicationPage].messageCaption) + ' data are loading', 'color:brown'); + } + + + protected loadBaseData(pageNo: number, noOfQueries: number, callback?: () => void) { + this.pageLoadingService.startSpinner(true, () => { if (callback) callback(); this.pageBaseDateWereLoaded$.next(true); }); + this.pageLoadingService.noOfHttpQueries4Page[pageNo] = noOfQueries; + this.appLogsService.dlog(this.globalsService.currentPage + ': %cstammdata data are loading', 'color:brown'); + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/pageloading.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/pageloading.service.ts new file mode 100644 index 0000000..983b6d9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/pageloading.service.ts @@ -0,0 +1,132 @@ +import { inject, Injectable } from '@angular/core'; +import { NgxSpinnerService } from 'ngx-spinner'; +import { Globals } from './globals'; +import { AppLogsService } from './applogs.service'; +import { EN_AppColors } from '../consts'; +import { Subject, BehaviorSubject } from 'rxjs'; +import { HenselTranslateService } from './localization/hensel-translate.service'; + +@Injectable({ + providedIn: 'root' +}) + +export class PageLoadingService { + public static delayBackgroundPageLoaded = 750; // timeout in msis needed to correctly process page loadings without delays (with not completed filter) + public spinnerVisible: number = 0; + public forgroundLoading$ = new BehaviorSubject(null); + public backgroundLoading$ = new BehaviorSubject(null); + public pageActive$ = new Subject(); + private _noOfHttpQueries4Page: number[] = []; + public get noOfHttpQueries4Page(): number[] { + return this._noOfHttpQueries4Page; + } + public set noOfHttpQueries4Page(value: number[]) { + value.forEach((vl: number, index: number) => { if (this._noOfHttpQueries4Page[index] > - 1) this._noOfHttpQueries4Page[index] = vl; }); + } + + private startBackgroundLoading: boolean = false; + private waitBackgroundLoadingFinished: boolean = false; + + private arLoadedCompletedCallBacks: (() => void)[] = []; + private translationService = inject(HenselTranslateService); + private _onPageLoagingWaitBackgroundLoadingFinished: boolean = false; + public get onPageLoagingWaitBackgroundLoadingFinished(): boolean { + return this._onPageLoagingWaitBackgroundLoadingFinished; + } + public set onPageLoagingWaitBackgroundLoadingFinished(value: boolean) { + this._onPageLoagingWaitBackgroundLoadingFinished = value; + this.waitBackgroundLoadingFinished = value; + } + public startBackgroundLoadingAfterPageIsLoaded: boolean = true; + + + constructor( + private globals: Globals, + private appLogsservice: AppLogsService, + private spinnerService: NgxSpinnerService, + ) { + this.globals.appPages.forEach(_ => this.noOfHttpQueries4Page.push(-1)); //page is not loaded + } + + + public startSpinner(_startBackgroundLoading: boolean = true, callbackCompleted?: () => void) { + this.startBackgroundLoading = _startBackgroundLoading || this.startBackgroundLoading; + // if (!_startBackgroundLoading) this.waitBackgroundLoadingFinished = this.onPageLoagingWaitBackgroundLoadingFinished; + if (callbackCompleted) this.arLoadedCompletedCallBacks.push(callbackCompleted); + this.showSpinner(); + } + + + public showSpinner() { + if (this.spinnerVisible++ === 0) { + this.appLogsservice.dlog('%cshow spinner', { guid: 'spinner' }, 'color:' + EN_AppColors.hideSpinnerColor); + this.spinnerService.show(); + } + } + + + private allData4PageAreLoaded(page: number = -1): boolean { + if (page > -1 && page < this.noOfHttpQueries4Page.length) { + //wait only on this page + return this.noOfHttpQueries4Page[page] <= 0; + } + return this.noOfHttpQueries4Page.every(_ => _ <= 0); + } + + + updatePageLoadedCounters(page: number) { + if (page !== null) { + const currentPageIndex: number = (this.globals.isTheLoginPage(this.globals.appPages[page].path) ? page : this.globals.getPageIndex(this.globals.currentPage)); + + if (this.noOfHttpQueries4Page[page] > 0) this.noOfHttpQueries4Page[page]--; + // this.appLogsservice.dlog('-----', page, currentPageIndex, this.noOfHttpQueries4Page); + + if (page < this.noOfHttpQueries4Page.length && this.noOfHttpQueries4Page[page] === 0) { + //if the page data were loaded + this.appLogsservice.dlog('%c' + this.translationService.instant(this.globals.appPages[page].messageCaption) + ' data are loaded', 'color:brown'); + } + + if (currentPageIndex === page && !this.startBackgroundLoadingAfterPageIsLoaded) this.doBackgroundLoading(); + + if (this.allData4PageAreLoaded(this.waitBackgroundLoadingFinished ? -1 : currentPageIndex /* if onPageLoagingWaitBackgroundLoadingFinished all pages must be loaded before spinner hides*/)) { + // if (!this.waitBackgroundLoadingFinished) this.spinnerVisible = 1; //to hide spinner anyway + setTimeout(() => { + this.hideSpinner(); + this.doCallBacks(); + // this.spinnerVisible = 0; + this.waitBackgroundLoadingFinished = this.onPageLoagingWaitBackgroundLoadingFinished; + if (currentPageIndex === page && this.startBackgroundLoadingAfterPageIsLoaded) { + this.spinnerVisible += 1; //don't show spinner for background loading + this.waitBackgroundLoadingFinished = true; + this.doBackgroundLoading(); + this.spinnerVisible -= 1; //correcture + } + }, PageLoadingService.delayBackgroundPageLoaded); // timeout is needed to correctly process page loadings without delays (with not completed filter) + } + } + + } + + private doBackgroundLoading() { + if (this.startBackgroundLoading) { + //if the first http-call on the active page returned (only one time) + this.startBackgroundLoading = false; + this.backgroundLoading$.next(); + } + } + + + public hideSpinner() { + if ((this.spinnerVisible > 0) && (--this.spinnerVisible === 0)) { + this.appLogsservice.dlog('%chide spinner', { guid: 'spinner' }, 'color:' + EN_AppColors.hideSpinnerColor); + this.spinnerService.hide(); + } + } + + + private doCallBacks() { + const arLoadedCompletedCallBacks = this.arLoadedCompletedCallBacks; + this.arLoadedCompletedCallBacks = []; + arLoadedCompletedCallBacks.forEach((callback) => {if (callback) callback(); }); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/print.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/print.service.ts new file mode 100644 index 0000000..6756b55 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/print.service.ts @@ -0,0 +1,25 @@ +import { Router } from '@angular/router'; + +export class PrintService { + isPrinting = false; + + constructor(private router: Router) { } + + printDocument(documentName: string, documentData: string[]) { + this.isPrinting = true; + this.router.navigate(['/', + { + outlets: { + print: ['print', documentName, documentData.join()] + } + }]); + } + + onDataReady() { + setTimeout(() => { + window.print(); + this.isPrinting = false; + this.router.navigate([{ outlets: { print: null } }]); + }); + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/services/serverinfo.service.ts b/ClientApp/staff-db-ui/src/app/shared/core/services/serverinfo.service.ts new file mode 100644 index 0000000..495f98a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/services/serverinfo.service.ts @@ -0,0 +1,176 @@ +import { inject, Injectable } from '@angular/core'; +import { SwUpdate } from '@angular/service-worker'; +import { BehaviorSubject, interval, Subscription } from 'rxjs'; +import { EN_LoginStatus } from '../consts'; +import { Globals } from './globals'; +import { APPICON4LIVE_TOKEN, APPICON4TEST_TOKEN, ENVIRONMENT_TOKEN } from '../injection-tokens'; +import { ServerInfo } from '../models/serverinfo'; +import { setIndexIcon } from '../utils'; +import { AppLogsService } from './applogs.service'; +import { AuthorizeService } from './authorize.service'; +import { RepositoryService } from './http/repository.service'; +import { HenselTranslateService } from './localization/hensel-translate.service'; +import { MatDialogRef } from '../components/angular-material-index'; + +const cnstPollingInterval1stInSec = 3; +const cnstPollingIntervalConnectedInSec = 15; +const time4TimeoutMessageInSec = 10; + +const enum EN_ServerStates { + Offline = -1, + Live = 0, + Development = 1, +} + + +@Injectable({ providedIn: 'root' }) + +export class ServerInfoService { + private environment = inject(ENVIRONMENT_TOKEN); + public serverInfo: ServerInfo = new ServerInfo(); + public serverStatus: EN_ServerStates = EN_ServerStates.Offline; + public defaultServerInfoVisible: boolean = true; + public serverInfoVisible: boolean; + protected pollingItervalTimer: Subscription = null; + public connectionReady: BehaviorSubject = new BehaviorSubject(null); + private EN_LoginStatus_Password = EN_LoginStatus.loginWithNameAndPassword; + private warningTimeOut: any; + private warningPopup: MatDialogRef; + private cnst_AppIcon4Live = inject(APPICON4LIVE_TOKEN); + private cnst_AppIcon4Test = inject(APPICON4TEST_TOKEN); + + private _pollingIntervalConnectedInSec: number = cnstPollingIntervalConnectedInSec; + + public get pollingIntervalConnectedInSec() { + return this._pollingIntervalConnectedInSec; + } + public set pollingIntervalConnectedInSec(value: number) { + this._pollingIntervalConnectedInSec = value; + this.resetPolling(value || 0); + } + + constructor( + private serverInfoDataService: RepositoryService, + public authorizationService: AuthorizeService, + public globals: Globals, + private appLogsService: AppLogsService, + public translate: HenselTranslateService, + private updateService: SwUpdate, + ) { + this.resetPolling(cnstPollingInterval1stInSec); + + this.createWarningTimeOutSubscriber = this.createWarningTimeOutSubscriber.bind(this); + this.createWarningTimeOutSubscriber(); + + this.authorizationService.loginAction$.subscribe((resultObject) => { + if (resultObject.result) { + if (this.authorizationService.user.showFooter !== undefined) { + this.serverInfoVisible = authorizationService.user.showFooter; + } else { + if (this.serverInfoVisible === undefined) this.serverInfoVisible = authorizationService.user.isAdmin; + } + } else { + this.serverInfoVisible = this.defaultServerInfoVisible || this.serverInfoVisible; + } + }); + this.appLogsService.dlog('Server Info is initialized!'); + } + + createWarningTimeOutSubscriber() { + this.warningTimeOut = setTimeout(() => { + clearTimeout(this.warningTimeOut); + this.warningPopup = this.appLogsService.warningMessageBox(this.translate.instant('core.msgbox.header.connect'), this.translate.instant('core.msgbox.body.connect'), () => this.warningTimeOut = null); + }, time4TimeoutMessageInSec * 1000); + } + + + resetPolling(intervalInSec: number) { + if (this.pollingItervalTimer) this.pollingItervalTimer.unsubscribe(); //poll always + if (intervalInSec > 0) this.pollingItervalTimer = interval(intervalInSec * 1000).subscribe(() => { this.init(); }); + } + + + private init() { + const _isLive = this.serverInfo?.isLive; + this.resetPolling(0); + this.serverInfo.firstOnlineTime = this.serverStatus === EN_ServerStates.Offline ? new Date() : null; + + this.serverInfo.save(this.serverInfoDataService, (si: ServerInfo) => { + this.resetPolling(this.pollingIntervalConnectedInSec); + if (!this.authorizationService.versionObsolete) this.updateService.checkForUpdate().then(res => this.authorizationService.versionObsolete = this.isOldVersion(this.serverInfo.clientVersion) || res); + if (si.attributes) { + si.officeFileServerURL = si.attributes['url']; + si.officeFileServerVersion = si.attributes['version']; + si.officeFileServer = si.attributes['server']; + si.officeFileServerDBServer = si.attributes['databaseserver']; + si.officeFileServerDBName = si.attributes['databasename']; + } else { + si.officeFileServerURL = null; + si.officeFileServerVersion = null; + si.officeFileServer = null; + si.officeFileServerDBServer = null; + si.officeFileServerDBName = null; + } + + if (_isLive !== si.isLive) { + if (si.isLive) { + setIndexIcon(this.cnst_AppIcon4Live); + if (this.globals.appTitleWithVersion.startsWith('Test - ')) this.globals.appTitleWithVersion = this.globals.appTitleWithVersion.replace('Test - ', ''); + } else { + setIndexIcon(this.cnst_AppIcon4Test); + if (!this.globals.appTitleWithVersion.startsWith('Test - ')) this.globals.appTitleWithVersion = 'Test - ' + this.globals.appTitleWithVersion; + } + } + + if (this.serverStatus === EN_ServerStates.Offline) { //first time connection + + if (this.warningPopup) this.warningPopup.close(); + + clearTimeout(this.warningTimeOut); + this.warningTimeOut = null; + + this.appLogsService.dlog('Server connected!'); + + this.serverStatus = this.isLive() ? EN_ServerStates.Live : EN_ServerStates.Development; + + + if (this.authorizationService.useJWT) { + // if (!this.authorizationService.checkJWT(this.environment.production ? 60 * 24 /* relogin one day before expiration*/ : 0)) this.authorizationService.loginStatus = this.EN_LoginStatus_Password; + if (!this.authorizationService.checkJWT(null)) this.authorizationService.loginStatus = this.EN_LoginStatus_Password; //only if there is no JWT + } else if (!this.authorizationService.useWindowsLogin) this.authorizationService.loginStatus = this.EN_LoginStatus_Password; + this.connectionReady.next(si); + } + } + , (err) => { + this.resetPolling(cnstPollingInterval1stInSec); + if (this.serverStatus !== EN_ServerStates.Offline) { + this.serverInfo.lastOfflineTime = new Date(); + this.serverStatus = EN_ServerStates.Offline; + } + if (!this.warningTimeOut) this.createWarningTimeOutSubscriber(); + } + , null, ''); + } + + public isOldVersion(mustVersion: string): boolean { + const isVersion = this.environment.appVersion; + const checkarrIsVersion = isVersion?.split('.'); + const checkarrMustVersion = mustVersion?.split('.'); + while (checkarrMustVersion.length > checkarrIsVersion.length) checkarrIsVersion.push('0'); + while (checkarrIsVersion.length > checkarrMustVersion.length) checkarrMustVersion.push('0'); + for (let index = 0; index < checkarrIsVersion.length; index++) { + const isVersionElement = checkarrIsVersion[index]; + const mustVersionElement = checkarrMustVersion[index]; + const isVersionElement_no = Number(isVersionElement); + const mustVersionElement_no = Number(mustVersionElement); + if (Number.isNaN(isVersionElement_no) || Number.isNaN(mustVersionElement_no)) { + if (isVersionElement !== mustVersionElement) return isVersionElement < mustVersionElement; + } else if (isVersionElement_no !== mustVersionElement_no) return isVersionElement_no < mustVersionElement_no; + } + return false; + } + + public isLive(): boolean { + return this.serverInfo?.isLive; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/utils.ts b/ClientApp/staff-db-ui/src/app/shared/core/utils.ts new file mode 100644 index 0000000..85d0b15 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/utils.ts @@ -0,0 +1,395 @@ +import * as AngularCommon from '@angular/common'; +import { HttpErrorResponse } from '@angular/common/http'; +import * as moment_ from 'moment'; +import * as Cnst from './consts'; + + +const moment = (moment_).default; + +export function guid(): string { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + // tslint:disable-next-line: no-bitwise + const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + + +export function getMethodName(level: number = 2): string { return /at .*\.(.*)\s/.exec((new Error()).stack.split('\n')[level])[1]; } // we want the 2nd method in the call stack + + +export function ms2ToTimeString(ms: number, fmt: string) { + return moment(ms).format(fmt); +} + +export function getDecimalSeparator(culture: string): string { + return AngularCommon.getLocaleNumberSymbol(culture, AngularCommon.NumberSymbol.Decimal); +} + + +export function getThousandSeparator(culture: string): string { + return AngularCommon.getLocaleNumberSymbol(culture, AngularCommon.NumberSymbol.Group); +} + +export function getLocaleCurrencyCode(culture: string): string { + return AngularCommon.getLocaleCurrencyCode(culture); +} + +export function getCurrencySymbol(culture: string): string { + return AngularCommon.getCurrencySymbol(getLocaleCurrencyCode(culture), 'narrow', culture); +} + +export function getDateTimeFormat(culture: string): string { + return getDateFormat(culture, Cnst.EN_DateFormats.DateTime); +} + +export function getDateFormat(culture: string, dateFormatStringMode: Cnst.EN_DateFormats = Cnst.EN_DateFormats.Date): string { + let formatString: string; + switch (dateFormatStringMode) { + case Cnst.EN_DateFormats.WebAPI: + formatString = Cnst.DATE_FORMATS.display.date4WebAPI; + break; + case Cnst.EN_DateFormats.JSON: + formatString = Cnst.DATE_FORMATS.display.dateTime4JSON; + break; + case Cnst.EN_DateFormats.DateTime: + // getLocaleDateTimeFormat(culture, FormatWidth.Medium); returns {1}, {0} WTF? + formatString = stringFormat(AngularCommon.getLocaleDateTimeFormat(culture, AngularCommon.FormatWidth.Short) + , AngularCommon.getLocaleTimeFormat(culture, AngularCommon.FormatWidth.Short) + , AngularCommon.getLocaleDateFormat(culture, AngularCommon.FormatWidth.Short)).replace('yy', 'y'); + break; + default: + const localDateFormat = AngularCommon.getLocaleDateFormat(culture, AngularCommon.FormatWidth.Short); + formatString = localDateFormat.replace('yy', 'y'); //localformat "short" returns yy - that shows only the last 2 years in year, not 4 + } + return formatString; +} + + +export function toStringConsiderDateFormat(obj: any, dateFormatStringMode: Cnst.EN_DateFormats = Cnst.EN_DateFormats.WebAPI, culture: string = 'en-US' /* does not matter a culture, Cnst.EN_DateFormats.WebAPI uses explicit date format*/): string { + let ret: string = ''; + + if (obj) { + if (typeof obj === 'string') obj = new Date(obj); + if (typeof obj === 'object') { + const formatString: string = getDateFormat(culture, dateFormatStringMode); + const momentFormatString: string = formatString.toUpperCase().replace(':MM', ':mm').replace(':SS', ':ss'); + if (moment.isMoment(obj) /*'_isAMomentObject' in obj*/) ret = moment(obj).format(momentFormatString); + else if (moment.isDate(obj) /*obj instanceof Date*/) ret = AngularCommon.formatDate(obj, formatString, culture /* does not matter a culture, we are using explicit date format*/); + } else ret = obj.toString(); + } + return ret; +} + + +export function formatNumbers(locale: string, num: number, digits = 0, prefix = ''): string { + // const num = +data.value; + // let val = num.toFixed(digits).replace('.', ','); // replace decimal point + // val = val.replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.'); + return prefix + AngularCommon.formatNumber(num, locale, '1.' + digits + '-' + digits); +} + + +export function isEqual(source: object, target: object): boolean { + if (target && source) { + for (const prop in source) { + if (source.hasOwnProperty(prop) + && target.hasOwnProperty(prop) + && (target[prop] !== source[prop])) { + return false; + } + } + return true; + } else { + return !target && !source; + } +} + + +function arrayIsContainedInReturnsDiff(arr1: any[], arr2: any[], notExistInArray2: any[]): boolean { + if (!arr1) return false; + if (arr1.length === 0) return true; + if (!arr2 || arr2.length === 0) { + notExistInArray2.concat(arr1); + return false; + } else { + let result = true; + arr1.forEach((e1: any) => { + if (!arr2.some(e2 => { + if (e1 instanceof Array && e2 instanceof Array) return arraysAreEqual(e1, e2); + else return e1 === e2; + })) { + result = false; + notExistInArray2.push(e1); + } + }); + return result; + } +} + + +export function arraysAreEqualReturnsDiff(arr1: any, arr2: any, diffArr1: any, diffArr2: any): boolean { + let _arr1: any[] = arr1; + let _arr2: any[] = arr2; + if (!(arr1 instanceof Array)) _arr1 = [arr1]; + if (!(arr2 instanceof Array)) _arr2 = [arr2]; + if (!diffArr1) diffArr1 = []; + if (!diffArr2) diffArr2 = []; + return arrayIsContainedInReturnsDiff(_arr1, _arr2, diffArr1) && arrayIsContainedInReturnsDiff(_arr2, _arr1, diffArr2); +} + + +function arrayIsContainedIn(arr1: any[], arr2: any[]): boolean { + return arr1 && arr2 && (arr1.length === 0 || arr1.every((e1, i) => arr2.some(e2 => { + if (e1 instanceof Array && e2 instanceof Array && e1.length > 1 && e2.length) return arraysAreEqual(e1, e2); + else return e1 === e2; + }))); +} + + +export function arraysAreEqual(arr1: any, arr2: any): boolean { + let _arr1: any[] = arr1; + let _arr2: any[] = arr2; + if (!(arr1 instanceof Array)) _arr1 = [arr1]; + if (!(arr2 instanceof Array)) _arr2 = [arr2]; + return arrayIsContainedIn(_arr1, _arr2) && arrayIsContainedIn(_arr2, _arr1); +} + + +export function compareStrings(str1: string, str2: string): boolean { + return (str1 ?? '').localeCompare(str2 ?? '') === 0; +} + + + +export function prepareArrayFromList(obj: Object, listField: string, arrayToPprepareField: string): number[] { + if (obj[arrayToPprepareField]) return obj[arrayToPprepareField]; + obj[arrayToPprepareField] = []; + if (obj[listField]) { + const reglist: string[] = obj[listField].split(','); + reglist.forEach((vl: string, inx: number) => { if (vl && !Number.isNaN(Number(vl))) obj[arrayToPprepareField].push(+vl); }); + } + return obj[arrayToPprepareField]; +} + + +export function prepareListFromArray(obj: Object, listField: string, arrayToPprepareField: string, newArray: number[]) { + obj[arrayToPprepareField] = newArray; + obj[listField] = newArray.join(','); +} + + +export function getErrorMessageAsText(errorObj: any): string { + if (!errorObj) return 'unknown error'; + if (errorObj instanceof HttpErrorResponse && errorObj.status === Cnst.cnst_ErrorCode4Unauthorized) return Cnst.cnst_CANCEL_ERROR; + if (errorObj['errMsg']) return errorObj.errMsg; + if (errorObj['error']) { + if (typeof errorObj.error === 'string') return errorObj.error; + if (errorObj.error['errors'] && errorObj.error.errors instanceof Array && errorObj.error.errors.length > 0) return errorObj.error.errors[0].toString(); + if (errorObj.error['message']) return errorObj.message; + return errorObj.error.toString(); + } + if (errorObj['message']) return errorObj.message; + if (errorObj['statusText']) return errorObj.statusText; + return errorObj.toString(); +} + + +export function extractError(error: any) { + // Try to unwrap zone.js error. + // https://github.com/angular/angular/blob/master/packages/core/src/util/errors.ts + if (error && error.ngOriginalError) { + error = error.ngOriginalError; + } + + // We can handle messages and Error objects directly. + if (typeof error === 'string' || error instanceof Error) { + return error; + } + + // If it's http module error, extract as much information from it as we can. + if (error instanceof HttpErrorResponse) { + // The `error` property of http exception can be either an `Error` object, which we can use directly... + if (error.error instanceof Error) { + return error.error; + } + + // ... or an`ErrorEvent`, which can provide us with the message but no stack... + if (error.error instanceof ErrorEvent && error.error.message) { + return error.error.message; + } + + // ...or the request body itself, which we can use as a message instead. + if (typeof error.error === 'string') { + return `Server returned code ${error.status} with body "${error.error}"`; + } + + // if (error['error']) { + // return error.error; + // } + + // If we don't have any detailed information, fallback to the request message itself. + return error.message; + } + + // ***** CUSTOM ***** + // The above code doesn't always work since 'instanceof' relies on the object being created with the 'new' keyword + if (error.error && error.error.message) { + return error.error.message; + } + if (error.message) { + return error.message; + } + // ***** END CUSTOM ***** + + // Skip if there's no error, and let user decide what to do with it. + return null; +} + + +export function getNextDate(dt: Date, hours: number = 0, offset: number = 1): Date { + if (!dt) return null; + const date = new Date(dt); + date.setHours(hours, 0, 0, 0); + date.setDate(date.getDate() + offset); + return date; +} + + +export function today(): Date { + const date = new Date(); + date.setHours(0, 0, 0, 0); + return date; +} + + +export function setIndexIcon(iconpath: string, icon2replace: string = '#favIcon') { + const favIcon: HTMLLinkElement = document.querySelector(icon2replace); + if (favIcon) favIcon.href = iconpath; +} + + +export function setIndexTitle(title: string) { + const tileEl: HTMLLinkElement = document.querySelector('#appTitle'); + if (tileEl) tileEl.innerText = title; +} + + +export function removeSpecialChars(str: string): string { + return str + .replace(new RegExp('/ ', 'g'), '_') + .replace(new RegExp(' /', 'g'), '_') + .replace(new RegExp(' / ', 'g'), '_') + .replace(new RegExp(' ', 'g'), '_') + .replace(new RegExp('/', 'g'), '_') + .replace(new RegExp(':', 'g'), '_') + .replace(new RegExp('>', 'g'), '_') + .replace(new RegExp('<', 'g'), '_') + .replace(new RegExp('___', 'g'), '_') + .replace(new RegExp('__', 'g'), '_'); +} + + +export function dowloadFile(filename: string, data: any, type: string) { + // const blob = new Blob([response.body], { type: response.body.type }); + const blob = new Blob([JSON.stringify(data)], { type: type }); + + + // window.open(window.URL.createObjectURL(blob), filename); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + link.setAttribute('href', url); + link.setAttribute('download', filename); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); +} + + +export function cleanTextContent(text: string): string { + // strips off all non-ASCII characters + text = text.replace(new RegExp('[^\\x00-\\x7F]', 'g'), ''); + + // erases all the ASCII control characters + text = text.replace(new RegExp('[\\p{Cntrl}&&[^\r\n\t]]', 'g'), ''); + + // removes non-printable characters from Unicode + text = text.replace(new RegExp('\\p{C}', 'g'), ''); + + return text.trim(); +} + + +export function isWorkDay(dt: Date) { + return dt.getDate() === nextWorkDay(dt, -1000 * 60 * 60 * 24 ).getDate(); +} + + +export function nextWorkDay(dt: Date, shift: number = 0) { + const newdt = new Date(dt.getTime() + shift); + const day = newdt.getDay(); + newdt.setDate(newdt.getDate() + 1 + (day === 5 ? 2 : (day === 6 ? 1 : 0))); + return newdt; +} + + +export function stringFormat(str: string, ...opt_values: string[]) { + if (opt_values) { + str = str.replace(/\{([^}]+)}/g, function (match, key) { + return (opt_values != null && key in opt_values) ? opt_values[key] : match; + }); + } + return str; +} + + +export function convertTZ(date: Date | string, tzString: string) { + return new Date((typeof date === 'string' ? new Date(date) : date).toLocaleString('en-US', {timeZone: tzString})); +} + + +export function now() { + return moment.now(); +} + + +export function isBefore(dt: Date) { + return moment().isBefore(dt); +} + + +export function isLanguageSupported(lang: string, appLanguages?: string[], supportedLanguage?: Cnst.SupportedLanguage[]): boolean { + return (!appLanguages || appLanguages.indexOf(lang) > -1) + && (!supportedLanguage || supportedLanguage.findIndex((lng: Cnst.SupportedLanguage) => lng.langCode === lang) > -1); +} + + +export function isCultureSupported(culture: string, appCultures: string[], supportedCulture?: Cnst.SupportedCulture[]): boolean { + return (!appCultures || appCultures.indexOf(culture) > -1) + && (!supportedCulture || supportedCulture.findIndex((cltr: Cnst.SupportedCulture) => cltr.culture === culture) > -1); +} + + + +export function callProtocol(protocol: string, filePath: string, replaceSlash: boolean = true) { + if (replaceSlash) { + filePath = filePath.replace(new RegExp('"', 'g'), '').split('\\\\').join('\\'); + } + window.open(protocol + ':' + filePath, '_parent'); +} + + + +// export function translateString(stringToTranslate: string, translate: HenselTranslateService) { +// let res = stringToTranslate?.replace(/\${(.*?)}/g, (found: string, translationKey: string) => translate.instant(translationKey)); +// if (res === stringToTranslate) res = translate.instant(res); // source string does not contain placeholder "${}" - try to translate directly +// return res; +// } + +export function isEmpty(value: any): boolean { + return (value == null || (typeof value === 'string' && value.trim().length === 0)); +} + +export function inputNumberChanged(target: number, value: any): boolean { + return isEmpty(value) && !isEmpty(target) || !isEmpty(value) && isEmpty(target) || (target ?? 0) !== +value; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/core/validators/hensel-validator.directive.ts b/ClientApp/staff-db-ui/src/app/shared/core/validators/hensel-validator.directive.ts new file mode 100644 index 0000000..d6cd4db --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/core/validators/hensel-validator.directive.ts @@ -0,0 +1,75 @@ +import { Directive, forwardRef, Input } from '@angular/core'; +import { AbstractControl, NG_VALIDATORS, Validator } from '@angular/forms'; + +@Directive({ + standalone: true, + selector: '[hensel-validator]', + providers: [ + { provide: NG_VALIDATORS, useExisting: forwardRef(() => HenselValidator), multi: true } + ] +}) + +export class HenselValidator implements Validator { + private valueFromExcl?: number; + private valueFromIncl?: number; + private valueToIncl?: number; + private valueToExcl?: number; + private valid: boolean = true; + private control: AbstractControl; + + @Input() + set greater(value: number) { + this.valueFromExcl = value; + this.control?.updateValueAndValidity(); + } + + + @Input() + set notless(value: number) { + this.valueFromIncl = value; + this.control?.updateValueAndValidity(); + } + + + @Input() + set notgreater(value: number) { + this.valueToIncl = value; + this.control?.updateValueAndValidity(); + } + + + @Input() + set less(value: number) { + this.valueToExcl = value; + this.control?.updateValueAndValidity(); + } + + @Input() + set isValid(value: boolean) { + this.valid = value; + this.control?.updateValueAndValidity(); + } + + constructor( + // @Attribute('greater') public valueFromExcl?: number, + // @Attribute('notless') public valueFromIncl?: number, + // @Attribute('notgreater') public valueToIncl?: number, + // @Attribute('less') public valueToExcl?: number, + ) { } + + validate(c: AbstractControl): { [key: string]: any } { + // self value + this.control = c; + if (c.value === null || c.value === 'undefined' || c.value === '') return null; + const val = +c.value; + if (((this.valueFromExcl || this.valueFromExcl === 0) && val <= this.valueFromExcl) + || ((this.valueFromIncl || this.valueFromIncl === 0) && val < this.valueFromIncl) + || ((this.valueToIncl || this.valueToIncl === 0) && val > this.valueToIncl) + || ((this.valueToExcl || this.valueToExcl === 0) && val >= this.valueToExcl) + || !this.valid + ) { + return { validateEqual: false }; + } + return null; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/cost-centre.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/cost-centre.ts new file mode 100644 index 0000000..d444f42 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/cost-centre.ts @@ -0,0 +1,19 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; + +export class CostCentre extends AppBaseEntity { + typeName = EN_AppEntities.CostCentre; + costCentreId: number; + costCentreName: string; + sortOrder: number; + + + + public get entityId() { + return this.costCentreId; + } + public set entityId(value) { + this.costCentreId = value; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/department.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/department.ts new file mode 100644 index 0000000..85dc1d3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/department.ts @@ -0,0 +1,39 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; +import { AppBaseFilter } from '@app_models/generic/app.baseentityfilter'; + +export class Department extends AppBaseEntity { + typeName = EN_AppEntities.Department; + get entitytitle(): string { //is used for messages + return this.entityId ? `Abteilung "${this.departmentName}"` : 'Neue Abteilung'; + } + departmentId: number; + departmentName: string; + costCentreId: number; + departmentTypeId: number; + headofDepartmentId: number; + executiveDirectorId: number; + managingDirectorId: number; + departmentNameFolder: string; + adGroupDepartmentName: string; + clientId: number; + isVirtual: boolean; + costCentre: string; + headofDepartment: string; + executiveDirector: string; + managingDirector: string; + public get entityId() { + return this.departmentId; + } + public set entityId(value) { + this.departmentId = value; + } + + insertWithIds() { return true; } //because departmentId is not autoincrement and is set explicetely +} + + +export class DepartmentFilter extends AppBaseFilter { + departmentId: number; + departmentName: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/document-art.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/document-art.ts new file mode 100644 index 0000000..edb5f82 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/document-art.ts @@ -0,0 +1,16 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; +export class DocumentArt extends AppBaseEntity { + typeName = EN_AppEntities.DocumentArt; + documentArtId: number; + rootPath: string; + folder: string; + departmentNamesList: string; + clientId: number; + public get entityId() { + return this.documentArtId; + } + public set entityId(value) { + this.documentArtId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-attribute.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-attribute.ts new file mode 100644 index 0000000..2cb2563 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-attribute.ts @@ -0,0 +1,16 @@ +import { EN_AppEntities } from '@app_consts'; +import { BaseData } from '@app_models/generic/app.basedata'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; + +export class EmployeeAttribute extends BaseData { + typeName = EN_AppEntities.EmployeeAttribute; + employeeAttributeId: number; + seqNo: number; + + public get entityId() { + return this.employeeAttributeId; + } + public set entityId(value) { + this.employeeAttributeId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-status.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-status.ts new file mode 100644 index 0000000..99453af --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/employee-status.ts @@ -0,0 +1,15 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; + +export class EmployeeStatus extends AppBaseEntity { + typeName = EN_AppEntities.EmployeeStatus; + employeeStatusId: number; + employeeStatusName: string; + public get entityId() { + return this.employeeStatusId; + } + public set entityId(value) { + this.employeeStatusId = value; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/project.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/project.ts new file mode 100644 index 0000000..8791d73 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/project.ts @@ -0,0 +1,13 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; +export class Project extends AppBaseEntity { + typeName = EN_AppEntities.Project; + projectId: number; + projectName: string; + public get entityId() { + return this.projectId; + } + public set entityId(value) { + this.projectId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/rang.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/rang.ts new file mode 100644 index 0000000..372ba9b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/rang.ts @@ -0,0 +1,17 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; +export class Rang extends AppBaseEntity { + typeName = EN_AppEntities.Rang; + rangId: number; + rangShortname: string; + rangName: string; + rangOrder: number; + + public get entityId() { + return this.rangId; + } + public set entityId(value) { + this.rangId = value; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp-to-webapprole.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp-to-webapprole.ts new file mode 100644 index 0000000..5a2e6f3 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp-to-webapprole.ts @@ -0,0 +1,24 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '../generic/app.baseentity'; +import { AppBaseFilter } from '../generic/app.baseentityfilter'; + +export class WebAppToWebAppRole extends AppBaseEntity { + typeName = EN_AppEntities.WebAppToWebAppRole; + webAppToWebAppRoleId: number; + webAppId: number; + webAppRoleId: number; + webAppRoleName: string; + webAppRoleHierarchy: number; + + public get entityId() { + return this.webAppToWebAppRoleId; + } + public set entityId(value) { + this.webAppToWebAppRoleId = value; + } +} + + +export class WebAppToWebAppRoleFilter extends AppBaseFilter { + webAppId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp.ts new file mode 100644 index 0000000..d355214 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapp.ts @@ -0,0 +1,19 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '../generic/app.baseentity'; + +export class WebApp extends AppBaseEntity { + typeName = EN_AppEntities.WebApp; + webAppId: number; + webAppName: string; + webAppLinkLive: string; + webAppLinkDev: string; + isActive: boolean; + adWebAppName: string; + + public get entityId() { + return this.webAppId; + } + public set entityId(value) { + this.webAppId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/webappadditionalrole .ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webappadditionalrole .ts new file mode 100644 index 0000000..6ba0a26 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webappadditionalrole .ts @@ -0,0 +1,17 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '../generic/app.baseentity'; + +export class WebAppAdditionalRole extends AppBaseEntity { + typeName = EN_AppEntities.WebAppAdditionalRole; + webAppAdditionalRoleId: number; + webAppAdditionalRoleName: string; + adWebAppAdditionalRoleName: string; + webAppId: number; + + public get entityId() { + return this.webAppAdditionalRoleId; + } + public set entityId(value) { + this.webAppAdditionalRoleId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapprole.ts b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapprole.ts new file mode 100644 index 0000000..1020f0a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/basedata/webapprole.ts @@ -0,0 +1,16 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from '../generic/app.baseentity'; + +export class WebAppRole extends AppBaseEntity { + typeName = EN_AppEntities.WebAppRole; + webAppRoleId: number; + webAppRoleName: string; + webAppRoleHierarchy: number; + + public get entityId() { + return this.webAppRoleId; + } + public set entityId(value) { + this.webAppRoleId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/documentart-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/documentart-to-department.ts new file mode 100644 index 0000000..0d1f7c7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/documentart-to-department.ts @@ -0,0 +1,33 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class DocumentArtToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.DocumentArtToDepartment; + documentArtToDepartmentId: number; + documentArtId: number; + departmentId: number; + isActive: boolean; + useGlobix: boolean; + + documentArtName: string; + documentArtShortname: string; + documentArtFolder: string; + + public get entityId() { + return this.documentArtToDepartmentId; + } + public set entityId(value) { + this.documentArtToDepartmentId = value; + } + + public clear() { + this.isActive = true; + this.useGlobix = false; + } +} + + +export class DocumentArtToDepartmentFilter extends AppBaseFilter { + documentArtId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/employee-to-attribute.ts b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-attribute.ts new file mode 100644 index 0000000..767cdc0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-attribute.ts @@ -0,0 +1,17 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class EmployeeToAttribute extends AppBaseEntity { + typeName = EN_AppEntities.EmployeeToAttribute; + employeeToAttributeId: number; + employeeId: number; + employeeAttributeId: number; + + public get entityId() { + return this.employeeToAttributeId; + } + public set entityId(value) { + this.employeeToAttributeId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/employee-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-department.ts new file mode 100644 index 0000000..82ae77b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-department.ts @@ -0,0 +1,22 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; + +export class EmployeeToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.EmployeeToDepartment; + public get entitytitle(): string { return 'Zuweisung von Abteilung "' + this.departmentName + '" für Mitarbeiter'; } //is used for messages + + employeeToDepartmentId: number; + employeeId: number; + departmentId: number; + departmentName: number; + employeeBudget: number; + employeeStatusId: number; + rangId: number; + + public get entityId() { + return this.employeeToDepartmentId; + } + public set entityId(value) { + this.employeeToDepartmentId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/employee-to-webapp.ts b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-webapp.ts new file mode 100644 index 0000000..a5087e9 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/employee-to-webapp.ts @@ -0,0 +1,67 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { prepareArrayFromList, prepareListFromArray } from '@app_core/utils'; + +export class EmployeeToWebApp extends AppBaseEntity { + typeName = EN_AppEntities.EmployeeToWebapp; + public get entitytitle(): string { return 'Zuweisung von Webapp "' + this.webAppName + '" für Mitarbeiter'; } //is used for messages + employeeToWebAppId: number; + employeeId: number; + webAppId: number; + webAppRoleId: number; + departmentId: number; + webAppRoleName: string; + webAppName: string; + departmentName: string; + extendedDepartmentNameList: string; + extendedDepartmentIdList: string; + + additionalRoleNameList: string; + additionalRoleIdList: string; + + private _arExtendedDepartmentIdList: number[]; + get arExtendedDepartmentIdList(): number[] { + return prepareArrayFromList(this, 'extendedDepartmentIdList', '_arExtendedDepartmentIdList'); + } + + set arExtendedDepartmentIdList(array: number[]) { + prepareListFromArray(this, 'extendedDepartmentIdList', '_arExtendedDepartmentIdList', array); + } + + private _arAdditionalRoleIdList: number[]; + get arAdditionalRoleIdList(): number[] { + return prepareArrayFromList(this, 'additionalRoleIdList', '_arAdditionalRoleIdList'); + } + + set arAdditionalRoleIdList(array: number[]) { + prepareListFromArray(this, 'additionalRoleIdList', '_arAdditionalRoleIdList', array); + } + + + public get entityId() { + return this.employeeToWebAppId; + } + public set entityId(value) { + this.employeeToWebAppId = value; + } + + clear() { + super.clear(); + this._arExtendedDepartmentIdList = undefined; + this._arAdditionalRoleIdList = undefined; + } + + public assign(source: Partial): EmployeeToWebApp { + const oldId = this.entityId; + const oldDepIdList = this.extendedDepartmentIdList; + const oldAddRoleIdList = this.additionalRoleIdList; + this.clear(); + const obj = Object.assign(this, source); + if (oldId <= 0 && !this.isNew()) {//don't update extendedDepartmentIdList and additionalRoleIdList if the entity is reload (f.e. after insert) + this.extendedDepartmentIdList = oldDepIdList; + this.additionalRoleIdList = oldAddRoleIdList; + } + + return obj; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/employee.ts b/ClientApp/staff-db-ui/src/app/shared/models/employee.ts new file mode 100644 index 0000000..e217218 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/employee.ts @@ -0,0 +1,98 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; +import { prepareArrayFromList, prepareListFromArray } from '@app_core/utils'; + +export class Employee extends AppBaseEntity { + typeName = EN_AppEntities.Employee; + get entitytitle(): string { //is used for messages + return this.entityId ? `Mitarbeiter "${this._name}"` : 'Neuen Mitarbeiter'; + } + + employeeId: number; + employeeNo: string; + salutation: string; + firstName: string; + lastName: string; + shortName: string; + title: string; + position: string; + loginName: string; + email: string; + rangId: number; + clientId: number; + mobilePhoneNo: string; + phoneNo: string; + isActive: boolean; + + mandantCode: string; + + departmentNamesList: string; + departmentIdList: string; + webappNamesList: string; + webappIdList: string; + attributeNamesList: string; + attributeIdList: string; + + private _arAttributeIdList: number[]; + get arAttributeIdList(): number[] { + return prepareArrayFromList(this, 'attributeIdList', '_arAttributeIdList'); + } + + set arAttributeIdList(array: number[]) { + prepareListFromArray(this, 'attributeIdList', '_arAttributeIdList', array); + } + + + get _name(): string { + return this.firstName ? this.firstName + ' ' : '' + this.lastName ? this.lastName : ''; + } + + + public get fullname(): string { + return this.firstName + ' ' + this.lastName; + } + + public get entityId() { + return this.employeeId; + } + public set entityId(value) { + this.employeeId = value; + } + + constructor(source?: Employee) { + super(source); + this.dontUpdateFields = [...this.dontUpdateFields, + 'departmentNamesList', 'departmentIdList', 'webappNamesList', 'webappIdList', 'attributeNamesList', 'attributeIdList', '_arAttributeIdList']; + this.dontInsertFields = [...this.dontUpdateFields, + 'departmentNamesList', 'departmentIdList', 'webappNamesList', 'webappIdList', 'attributeNamesList', 'attributeIdList', '_arAttributeIdList']; + } + + assign(source: Partial): Employee { + super.assign(source); + return this; + } + + clear() { + super.clear(); + this._arAttributeIdList = undefined; + } +} + + +export class EmployeeFullFilter extends AppBaseFilter { + name: string; + shortName: string; + loginName: string; + email: string; + departmentIds: number[]; + attributeIds: number[]; + webappIds: number[]; + employeeId: number; + clientId: number; + isActive: boolean = true; +} + +export class EmployeeFilter extends AppBaseFilter { + employeeId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/generic/app.basedata.ts b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.basedata.ts new file mode 100644 index 0000000..90ca118 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.basedata.ts @@ -0,0 +1,16 @@ +import { AppBaseEntity } from './app.baseentity'; + +export class BaseData extends AppBaseEntity { + id: number; + name: string; + shortname: string; + comment: string; + + public get entityId() { + return this.id; + } + public set entityId(value) { + this.id = value; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentity.ts b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentity.ts new file mode 100644 index 0000000..587bb40 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentity.ts @@ -0,0 +1,6 @@ +import { BaseEntity } from '@app_core/models/generics/baseentity'; + + +//here define App specifically properties and methods +export class AppBaseEntity extends BaseEntity { +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentityfilter.ts b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentityfilter.ts new file mode 100644 index 0000000..ef8625d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/generic/app.baseentityfilter.ts @@ -0,0 +1,4 @@ +import { BaseFilter } from '@app_core/models/generics/baseentityfilter'; + +export class AppBaseFilter extends BaseFilter { +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/subsidiary.ts b/ClientApp/staff-db-ui/src/app/shared/models/subsidiary.ts new file mode 100644 index 0000000..8b0b536 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/subsidiary.ts @@ -0,0 +1,19 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; + +export class Subsidiary extends AppBaseEntity { + typeName = EN_AppEntities.Subsidiary; + + subsidiaryId: number; + clientId: number; + name: string; + subsidiaryCode: string; + comment: string + + public get entityId() { + return this.subsidiaryId; + } + public set entityId(value) { + this.subsidiaryId = value; + } +} \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/app/shared/models/user.ts b/ClientApp/staff-db-ui/src/app/shared/models/user.ts new file mode 100644 index 0000000..59b6eef --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/user.ts @@ -0,0 +1,4 @@ +import { CoreUser } from '@app_core/models/coreuser'; + +export class User extends CoreUser { +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-department.ts new file mode 100644 index 0000000..bfaf20b --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-department.ts @@ -0,0 +1,23 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class WebAppToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.WebAppToDepartment; + webAppToDepartmentId: number; + employeeToWebAppId: number; + departmentId: number; + departmentName: string; + + public get entityId() { + return this.webAppToDepartmentId; + } + public set entityId(value) { + this.webAppToDepartmentId = value; + } +} + + +export class EmployeeToWebAppFilter extends AppBaseFilter { + employeeToWebAppId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-webappadditionalrole.ts b/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-webappadditionalrole.ts new file mode 100644 index 0000000..14ace30 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/webapp-to-webappadditionalrole.ts @@ -0,0 +1,17 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class WebAppToWebAppAdditionalRole extends AppBaseEntity { + typeName = EN_AppEntities.WebAppToWebAppAdditionalRole; + webAppToWebAppAdditionalRoleId: number; + employeeToWebAppId: number; + webAppAdditionalRoleId: number; + + public get entityId() { + return this.webAppToWebAppAdditionalRoleId; + } + public set entityId(value) { + this.webAppToWebAppAdditionalRoleId = value; + } +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-index-to-windream-search-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-index-to-windream-search-to-department.ts new file mode 100644 index 0000000..407678d --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-index-to-windream-search-to-department.ts @@ -0,0 +1,34 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class WindreamIndexToWindreamSearchToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.WindreamIndexToWindreamSearchToDepartment; + get entitytitle(): string { //is used for messages + return this.entityId ? `Ausgabespalte "${this._name}" für Windream Suche` : 'Neue Ausgabespalte für Windream Suche'; + } + windreamIndexToWindreamSearchToDepartmentId: number; + windreamSearchToDepartmentId: number; + windreamIndexId: number; + seq: number; + attributeSzColumnName: string; + objectTypeAttributeSzName: string; + + get _name(): string { + return this.objectTypeAttributeSzName; + } + + public get entityId() { + return this.windreamIndexToWindreamSearchToDepartmentId; + } + public set entityId(value) { + this.windreamIndexToWindreamSearchToDepartmentId = value; + } + +} + + + +export class WindreamIndexToWindreamSearchToDepartmentFilter extends AppBaseFilter { + WindreamSearchToDepartmentId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-index.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-index.ts new file mode 100644 index 0000000..cc0a7c6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-index.ts @@ -0,0 +1,39 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + + +export class WindreamIndex extends AppBaseEntity { + + typeName = EN_AppEntities.WindreamIndex; + get entitytitle(): string { //is used for messages + return this.entityId ? `WindreamIndex "${this._name}"` : 'New WindreamIndex'; + } + windreamIndexId: number; + clientId: number; + attributeDwAttrId: number; + attributeSzColumnName: string; + comment: string; + comumnLength: number; + attributeDwAttrType: number; + objectTypeAttributeSzName: string; + + get _name(): string { + return this.attributeSzColumnName; + } + get selectionName(): string { + return this.comment + ' (' + this.attributeSzColumnName + ')'; + } + public get entityId() { + return this.windreamIndexId; + } + public set entityId(value) { + this.windreamIndexId = value; + } + +} + + +export class ClientIdFilter extends AppBaseFilter { + clientId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item-to-windream-search-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item-to-windream-search-to-department.ts new file mode 100644 index 0000000..84a1ec0 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item-to-windream-search-to-department.ts @@ -0,0 +1,32 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; + +export class WindreamSearchItemToWindreamSearchToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.WindreamSearchItemToWindreamSearchToDepartment; + get entitytitle(): string { //is used for messages + return this.entityId ? `Windream Suchfeld"${this._name}"` : 'Neues Windream Suchfeld'; + } + windreamSearchItemToWindreamSearchToDepartmentId: number; + windreamSearchToDepartmentId: number; + seq: number; + departmentId: number; + windreamSearchItemId: number; + windreamSearchItemName: string; + windreamSearchItemCaption: string; + windreamSearchItemPlaceHolder: string; + windreamSearchItemSearchTemplate: string; + windreamSearchItemConnectedList: string; + windreamSearchItemComment: string; + get _name(): string { + return this.windreamSearchItemName; + } + + public get entityId() { + return this.windreamSearchItemToWindreamSearchToDepartmentId; + } + + public set entityId(value) { + this.windreamSearchItemToWindreamSearchToDepartmentId = value; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item.ts new file mode 100644 index 0000000..adeeae6 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-item.ts @@ -0,0 +1,37 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class WindreamSearchItem extends AppBaseEntity { + typeName = EN_AppEntities.WindreamSearchItem; + get entitytitle(): string { //is used for messages + return this.entityId ? `Windream Suchfeld "${this._name}"` : 'Neues Windream Suchfeld'; + } + windreamSearchItemId: number; + clientId: number; + seq: number; + name: string; + comment: string; + caption: string; + placeHolder: string; + searchTemplate: string; + connectedList: string; + get _name(): string { + return this.caption; + } + + public get entityId() { + return this.windreamSearchItemId; + } + + public set entityId(value) { + this.windreamSearchItemId = value; + } + +} + + +export class WindreamSearchItemFilter extends AppBaseFilter { + departmentId: number; + windreamSearchToDepartmentId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-search-to-department.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-to-department.ts new file mode 100644 index 0000000..dce4058 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-search-to-department.ts @@ -0,0 +1,36 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + +export class WindreamSearchToDepartment extends AppBaseEntity { + typeName = EN_AppEntities.WindreamSearchToDepartment; + get entitytitle(): string { //is used for messages + return this.entityId ? `Windream Suchkachel "${this._name}"` : 'Neue Windream Suchekachel'; + } + windreamSearchToDepartmentId: number; + departmentId: number; + windreamSearchId: number; + seq: number; + departmentName: string; + windreamSearchName: string; + isActive: boolean; + + get _name(): string { + return this.windreamSearchName; + } + + public get entityId() { + return this.windreamSearchToDepartmentId; + } + + public set entityId(value) { + this.windreamSearchToDepartmentId = value; + } + +} + + +export class WindreamSearchToDepartmentFilter extends AppBaseFilter { + departmentId?: number; + windreamSearchId?: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/models/windream-search.ts b/ClientApp/staff-db-ui/src/app/shared/models/windream-search.ts new file mode 100644 index 0000000..05d11c5 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/models/windream-search.ts @@ -0,0 +1,40 @@ +import { EN_AppEntities } from '@app_consts'; +import { AppBaseEntity } from './generic/app.baseentity'; +import { AppBaseFilter } from './generic/app.baseentityfilter'; + + +export class WindreamSearch extends AppBaseEntity { + + typeName = EN_AppEntities.WindreamSearch; + get entitytitle(): string { //is used for messages + return this.entityId ? `Windream Suchkachel "${this._name}"` : 'Neue Windream Suchkachel'; + } + windreamSearchId: number; + name: string; + xmlPath: string; + comment: string; + clientId: number; + color: number; + + + get _name(): string { + return this.name; + } + + get selectionName(): string { + return this.name; + } + + public get entityId() { + return this.windreamSearchId; + } + public set entityId(value) { + this.windreamSearchId = value; + } + +} + + +export class ClientIdFilter extends AppBaseFilter { + clientId: number; +} diff --git a/ClientApp/staff-db-ui/src/app/shared/services/app.baseentity.wrapper.ts b/ClientApp/staff-db-ui/src/app/shared/services/app.baseentity.wrapper.ts new file mode 100644 index 0000000..19c1221 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/services/app.baseentity.wrapper.ts @@ -0,0 +1,5 @@ +import { BaseEntityWrapper } from '@app_core/models/generics/baseentity.wrapper'; +import { AppBaseEntity } from '../models/generic/app.baseentity'; + +export class AppBaseEntityWrapper extends BaseEntityWrapper { +} diff --git a/ClientApp/staff-db-ui/src/app/shared/services/app.baseentitylist.wrapper.ts b/ClientApp/staff-db-ui/src/app/shared/services/app.baseentitylist.wrapper.ts new file mode 100644 index 0000000..33e40d2 --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/services/app.baseentitylist.wrapper.ts @@ -0,0 +1,32 @@ +import { formatDate } from '@angular/common'; +import { AppBaseEntity } from '@app_models/generic/app.baseentity'; +import { AppBaseEntityWrapper } from './app.baseentity.wrapper'; +import { APP_TITLE } from '@app_consts'; +import { ɵDEFAULT_LOCALE_ID } from '@angular/core'; +import { BaseEntityListWrapper } from '@app_core/models/generics/baseentitylist.wrapper'; +import { EN_EntityEditingStates } from '@app_core/consts'; +import { removeSpecialChars } from '@app_core/utils'; + +export class AppBaseEntityListWrapper extends BaseEntityListWrapper { + //here define App specifically properties and methods + public createFocusedShadowEntity(defaultEditMode?: EN_EntityEditingStates): AppBaseEntityWrapper { + const appFocusedShadowEntity: AppBaseEntityWrapper = new AppBaseEntityWrapper(this.TEntity, defaultEditMode); + this.focusedEntityShadowed = appFocusedShadowEntity; + this.focusedEntityShadowed.entityList = this; + this.focusedEntityShadowed.hierarchyLevel = this.hierarchyLevel; + return appFocusedShadowEntity; + } + + public getExportFilename4List(prefix: string = '', postfix: string = '', midFix: string = '', useListName = true): string { + const retFilename = removeSpecialChars( + APP_TITLE + '_' + + (prefix !== '' ? prefix + '_' : '') + + (useListName ? this.translate.instant(this._listName) : '') + + (midFix !== '' ? '_' + midFix + '_' : '') + + formatDate(new Date(), '_yyyyMMdd', ɵDEFAULT_LOCALE_ID /* does not matter a culture, we are using explicit date format*/) + + (postfix !== '' ? '_' + postfix : '')); + console.log(retFilename); + return retFilename; + } + +} diff --git a/ClientApp/staff-db-ui/src/app/shared/services/app.data.service.ts b/ClientApp/staff-db-ui/src/app/shared/services/app.data.service.ts new file mode 100644 index 0000000..2fdf08a --- /dev/null +++ b/ClientApp/staff-db-ui/src/app/shared/services/app.data.service.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@angular/core'; +import { EN_AppEntities } from '@app_consts'; +import { CostCentre } from '@app_models/basedata/cost-centre'; +import { Department } from '@app_models/basedata/department'; +import { DocumentArt } from '@app_models/basedata/document-art'; +import { EmployeeAttribute } from '@app_models/basedata/employee-attribute'; +import { EmployeeStatus } from '@app_models/basedata/employee-status'; +import { Project } from '@app_models/basedata/project'; +import { Rang } from '@app_models/basedata/rang'; +import { WebApp } from '@app_models/basedata/webapp'; +import { WebAppToWebAppRoleFilter } from '@app_models/basedata/webapp-to-webapprole'; +import { WebAppRole } from '@app_models/basedata/webapprole'; +import { Subsidiary } from '@app_models/subsidiary'; +import { AppBaseEntityListWrapper } from './app.baseentitylist.wrapper'; + +@Injectable({ + providedIn: 'root' +}) + + +export class AppDataService { + costCentreList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(CostCentre, 'Kostenstellenliste', EN_AppEntities.CostCentre + '/all'); + departmentList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Department, 'Abteilungsliste', EN_AppEntities.Department + '/all'); + documentArtList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(DocumentArt, 'Dokumentartenliste', EN_AppEntities.DocumentArt + '/all'); + employeeStatusList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(EmployeeStatus, 'Mitarbeiterstatusliste', EN_AppEntities.EmployeeStatus + '/all'); + projectList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Project, 'Projektliste', EN_AppEntities.Project + '/all'); + rangList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Rang, 'Rangenliste', EN_AppEntities.Rang + '/all'); + webAppList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WebApp, 'Web Applikationen Liste', EN_AppEntities.WebApp + '/all'); + roleList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(WebAppRole, 'Rolenliste', EN_AppEntities.WebAppRole + '/all'); + employeeAttributeList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(EmployeeAttribute, 'Merkmalliste', EN_AppEntities.EmployeeAttribute + '/all'); + webAppFilter: WebAppToWebAppRoleFilter = new WebAppToWebAppRoleFilter('WebAppFilter'); + subsidiaryList: AppBaseEntityListWrapper = new AppBaseEntityListWrapper(Subsidiary, 'Subsidiary', EN_AppEntities.Subsidiary + '/all'); + + + showIds: boolean = false; + + constructor() { + } + + loadData(listLoadedCallBack: () => void) { + this.costCentreList.load(null, null, listLoadedCallBack); + this.departmentList.load(null, null, listLoadedCallBack); + this.documentArtList.load(null, null, listLoadedCallBack); + this.employeeStatusList.load(null, null, listLoadedCallBack); + this.projectList.load(null, null, listLoadedCallBack); + this.rangList.load(null, null, listLoadedCallBack); + this.webAppList.load(null, null, listLoadedCallBack); + this.roleList.load(null, null, listLoadedCallBack); + this.employeeAttributeList.load(null, null, listLoadedCallBack); + this.subsidiaryList.load(null, null, listLoadedCallBack); + +} +} diff --git a/ClientApp/staff-db-ui/src/assets/.gitkeep b/ClientApp/staff-db-ui/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ClientApp/staff-db-ui/src/assets/icons/Master_Icon.xcf b/ClientApp/staff-db-ui/src/assets/icons/Master_Icon.xcf new file mode 100644 index 0000000000000000000000000000000000000000..29f4457bd0cd1b6fee5248fb3f07ffec4e24631c GIT binary patch literal 23887 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 UJH-TJzjXpMRCJWf6m2m73j*F|2mk;8 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-144x144.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..1c6692254ab27af8f2b662b4203b5b25fa206740 GIT binary patch literal 12830 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 Z^fmwEvM!3EAMYptrlO@>diPQA{{srwp*sKo literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152.png new file mode 100644 index 0000000000000000000000000000000000000000..f6ef7e28d8eceab5c10107640a3f2c087564ac0b GIT binary patch literal 13410 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152i.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-152x152i.png new file mode 100644 index 0000000000000000000000000000000000000000..57d930cd92f87b3bc3502a0fab85f1e47abac87a GIT binary patch literal 12868 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-16x16.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..befcc0b478c7c5a88428ffdaed817ae9a31fa86e GIT binary patch literal 4814 zcmeHLdsGwY6(2>z8iB?7!gmZ>L7ik~G9k$^K?PfNKk?`pb zM#8vQGX%MATjS>XU6S~`z80LibZw8pYa(yP-1bdv+>#f=Y#Y6*W^J$CO?97sTNs(Q zuBvP*oZao<%=`%ThsWK0@09kb4lW4I6far-@J64E6>k(fUCt@KV-r?24$n@J8GA2k z##Syr9y`i^Za@WM7?j;lWc@UEYF$-BcFNO1;eILcm+Cg>ETZNXm%xvP^}nSIcF(Z- z>}m>P-AHlJjl~5%+pphPTerDK@1IWX>su>QHq7~Yon=Ba1a(`=Mn=ZzA|u~s1oHSI zb6r^UrC$v#ODLZb6+iUQu7_)Pryk8+sopqtKtugER(Y*Svt&vsoi%yX8uV^)jw;8Zg16U%C+BP! zo&Dn%uJ3mB{>236$F`awPxCHyzveUOR&8i<&g}7Z#g&&1CGEegxJ*V>1SS0G#GD7` z%H|Z_nDcZ;WA@@DC-WW<-z1MJUOLL)Kk|2L#J?~0&z})krrlcqNcIN(a;J3Dw8P>6 z&44(!_^W@qn@eBXzIj+{{3zJpyWx|h*HriFm)#4OSr?7Cllr_zb-358_?rm}x^p}C zs?Nm!_(4FWNOt(_)^pzT{s9HXo}r`HJkAg9mwWN`pv>vR1J3jm-MC$nQlH!a(FYDz z4Y_~cKWBZ=!n;*>n@UQW78aEM@ZqVw&Od&;@61RD@|(ee4x6o?Mo@OEjHK-*M&`0Q zKR7(HTx=dPaLC&yOWXNGF*nhQ7$$WlZJ~W zp-$RN7_^gGA;4RhG?C{Wgj}AMmL^M6$m~vw9Mxzvas-oO7z`|6F5SkHF4)Ee3J@(A zT85*Xtb=FmHi>{qn(Qfjm{bb%lDF|$9eRBmyp3yR0q`Mrkq$X3L*!PgyrT!lN2LOg z)_{K2gENASDmO5kJ;g~eQK^iL59|m*Q*Hi^6lanr9h#CeNsJYka$r@o(~^^Q`nWa^ zfdUI_b$Gl0*_|wT*4$23r`QCIC!LOg0QWZBPS$U8_ZR~!y`Iq8sT3hRoi0El^q~roh;}|GO1%!0u&9P)EZKQVl)Gr7!3;J zCN+pgsUqPJ+Jqx21)^eiAy4R zGjITVfVI)~G_GA`WUb6}o)q{*L(~|eR$`b2!_*2~({41AadMy+1ymG~DR7TQC=3D8 z0o0O0rvdL#v`hT+)wvQyVrRdQt2i8ybh+6j4bSAmwt>ra|^=u}I#Ir33l4?nT zBU2gL6DPoGQBjGc&BB2B(b}+Y$DL@_1A@l*dR9<(EMWIsoMs{>+?re zFLSTo8=mc!I`vEe0MZ0vnV$+ z^Wcdm*SPc@uYPKJ_9A`w{m*xQm3&Kmig|7edr^N_@=`P^JCm46)kFxp;t zg_j5%Z7^%JY z`Iu<>N`-t;K|R*A`s_AY%)$J{<>iXP_)5z$!xlqT$%t5gXueO_Z|>EXmFWte{55OZ z0aK#?_~l!+<{JXVD<0je80-g0%MV{{S~;so#AjsogJffVd2HGB(--)o)r!nGZ*{I1-&Lp(ZlYD{5D-F|!)eP+8 zyRr7x3wGZ{#lDNj9y}=+-AJADD(-%|dG+^Y0TdJt760(&V$JsDpN;*yugGo88#P#* z9hBt-VOciAu2Of<%4ZJsRnw6GPCZn4J+W4t^}6@QvK8{<_I|fO*&tn1jP~%v`Ahx{ Dqf+bh literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-192x192.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..7d4ec9c7c4be91ae27ab687f3923c67a85869372 GIT binary patch literal 16035 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-24x24.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..78f821a438ee0b52d9ee0819ddf4629fe6288e73 GIT binary patch literal 5188 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-512x512.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..f84c4b523b6915c4db15c673be7b535eb7e45e78 GIT binary patch literal 38893 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 RK=x4_FgLa|$~)o~{$D0j&CUP- literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-96x96.png b/ClientApp/staff-db-ui/src/assets/icons/develop/dhr-icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..174c72fb0db69d849cf6abf5e53e1a2087eec44c GIT binary patch literal 9790 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 JDN(Wx{x5#ym978) literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/main_48x48.png b/ClientApp/staff-db-ui/src/assets/icons/main_48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..ebe0c5aec0379fd59b2c7f950e82b273988083f9 GIT binary patch literal 6589 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-128x128.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..b7c9c44bcadd7bdbe1d9a02dffd606132d192022 GIT binary patch literal 11771 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 L)KI9BGY|e>YsgxN literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-144x144.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..3eed0bd084cebe920532773de220b0afec16fb01 GIT binary patch literal 12787 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 KsC;b_^nU7xJu literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-152x152i.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-152x152i.png new file mode 100644 index 0000000000000000000000000000000000000000..56d817f11d9d0a25b8a9d71fe799b823f338b138 GIT binary patch literal 12805 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-16x16.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..b155fbb6dad1bc382abebb5fd604a2c02319685f GIT binary patch literal 4821 zcmeHLc~nzp7Js6Mrh>SjSY&(#Is-Z{c`tb($&;W!SOP>@q5>}XlJ_ONl8r1RKsi>H z89F+)Vy!b2758P7!L2j3(#kfY_BhhIqF5{pWt^U)SW!FTGGD?Xoas4poHPDM&Pm>T z_q+G^-TS-C$@kt%UL5Dmd6R=6h_@nMo(iwNuJ45L@ORFG7c{&y7pT&0sk8$%TTEJ3 z4^Uga8KA()Y7xYF!;rkfrxBgh*FAkfRQcGl&X$v#^GX8O?%R{rs-4&w&O|jlFNkP3 z6203qG4Y&8H}`PnmDm)fI&gNg&!a_)iLS=|)k*8bvFXPi@Ay~9<}|(Pj#_nhb$WM{ z=rKPl_POs9dBV|8Q|v+i2$74kJ6BZXWYlD(JAR+?mx(Byj z>7?ua$TPG$#XqCoUK^ScFmKj@h>0_QFfI8-LqJ$tM$6?XmHQB6Oeq^3ovetC9t;SE zQB|}_7T>sNc5~LHgqY0PhpRh2*qL{1{cj{6&6`ml#m+zR&o!1iGf6f+b>(c&YsDpV z)-Uy%saqAe(lfGWY}1uy#aA&2PqQ+!r*zimF8t%`c$2NAjD zTiz=BvC8>%^&3+cT2>h!1awz4dR&||tF<>gw>)r{`#Ps`R7e^T)+bs;ynwlp}^ckb?uoI|y~dzS_^%PSvs@}3ia-ND_ORKxL? z&PXodoV#E0qW+%oLPxJ^L8!0Slhyh@jYrQtk0ZY_tetZ+@B48*5o4EUUdzhyu#l&y?``*y$>(BJfDoXpA|0&P$S8vqWALTwln1g@l z3b=jSxBSD9!dqRpp4HVoE8KUfee$37SQ=XPpPGvxK1*3xVCl*vN@FtcXvU-lJg317 zD-S`!7dp+fCI{G1HPEp}8Ta02UvN>Dk#U!cl(^Cy4YJwz0t-khSgg_%@%sg#ck_yPe2H85+w(MCHlqcz9{(T^bq zR*i)<+gOtkbz#zKlieoca^X5U=%2x?R1U!#tphATKKM@B%qMs_-(cVmx3Jn`@*v27 zLqBO@Rlz>xrvj_VZqb04JYcj14ToSfL-uC7Meh!W(eQyD7@(>Z?n;c|-0IKv%*=0mt6vxX;gf?^<)L`q8u0Ru2KkP;ZF zmOyVrVj2r$)Fdtz;$k2IZf_V36>G8>XqZmcKR~u&16xTOnMpDv{47({1_9JB>Q>L8DhD_EdzuF#NyRE3VzcVq)s9&k842myvmRX9$Ga7Y=K|N6rd zX$VrPhC?fiAYi))VW~=RDZoS|d=^UqL1_DHV2Hf`IXoeTlh{y2ki=kk;e6LX986|7 z|3A{*uP|(aLR$J|a5BR|&mWrf1AIYWU*~6_%wFdfC_1{yEAcx@*C<`D#K0>lk5<A6a_-wX2jj)f+|1(2H>Y~;M0f40SnX5hQ&yTNim9;QAtt<) zvHV{9*M4Qb$N%=j+V1;BRWGW>KK<%+VJJooq^{P))?*UTfdPV zJ^SE|g3F?l-d#_q11D!sD7l%xxrW-kDCJU!A6t-=wd%c=RsNhPT(lDvzrJdr{~j;sn!T$fW)?>l*%2RWUSvaz$beoc?ZnckV}iZ?vUD!+aX PrVmlXESA?qtttLD3P<4^ literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-192x192.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..1c1e6df1c6f7aef6964233fd997cd50aaf7aa195 GIT binary patch literal 15887 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-24x24.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..80ad47b5a7aeedfd2c13844d6e4aad4e95d90757 GIT binary patch literal 5189 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 literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-384x384.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-384x384.png new file mode 100644 index 0000000000000000000000000000000000000000..3accaa520e6741b9a936d81f91c3872ec4e8d145 GIT binary patch literal 29318 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�Yz{3@34B}_*hrAy(?TinHq$iTdfH zOeBAD>aa^$$(8%dNlo3H?&W9u?wV+oY9cio(pZ)oLY8U8kBGKZl$1rFkc&{L50}F04kq1%2oMAGMZKdw*te z8_VM5P|*>+lGY@qW!Cf889RuB?qk(gcePatVms=h9ujW!>DJyv%AY(aqo=}0MFzaq z8s3I8=9YunEm{RTDevz+u(1=a2Y{8dB*pXmNwxR+v&*uNtxgYPa+qypb|PindDXx@jzt^xKK!k7dspD zqpz*@^YqKJb0?I2pU^9XgFMHoBBElk?=>VW{bH;jvN>O-e3WzSdmF;moXY8X8U_m$~&IF4GQnPa=Mv-5=((I zcUoEwU2km6CGFqQ)6;Wn2AGCG4o7XZq2b*~BHV zK@va)!g}5?fQ(s%v*allwN=G|eXYlmyD3+nO8o#5U<6dg*4+J5XQdV+D>GBm)xg+$ zUek>m(_{l3O)v`V;xua*(53t}_bk?QVF-(r?U*pcyVm`3E>NzHfd!dUX|QB+fBA!> zQ_?)Qx>-lsc3Grs|EQZh= zJ}fu)w!6EH-bt9k>f*^pC$^fx7EwLz;*H$~59gar&COkYD)joZdqwr_?JG|oJ?eI% zq$DeH_3ECXA@S1>Z-=|eg%7X1>~6RLm?JLaY7d6mVT(?57F?he5{2?Tfd5FluR6Wj^z?vmgH2<{}fdvJFrxI=Jvhdq2Bul-eR zy<7YKu~kp1l6&u*nV#-X%k)goNw9*P1S%3C5&!_GQj%{!0ss{F6$(Ir13%7Pe&2#0 zU2aNh4j=WL$!+Ycjm<2K$Q@j5jL3~#%!~oRWzJGT1gnD_q46w45CTCJ>|x)L@gCiB z4xf>lI}GzFsw^6PbQ9d3qUh^AUHci=?xS2duE336MfIwNN>0*&$@3P&FOG7LyfG}r z*c(Y)4pmtY@kZe5#e1dDlgF1h{#AUtcr_RW6hBzM;y_t?gi2p*+y^>t(RmQ>>Y+|{ zU_LEbwq4eQ@w}-p|M*U+T2J`y!+20ThIly|e}5jERTEpPF2&O&yNESct$H_d=CU*Z zKmyFf#1y2&#Qq@=C`O9sHv!2GVd5^GiTC0f#6=lvQJGE^p&{IHZ}8eg&FHFjb?tUu zu$xJK)Fg(T_VXtTRfd0IqD7(!D{>6oIoTyOCjS0jN5d3zz0Fo=Y0-V52|B>|dwvcR zTwapV4{TeOcpcn_(qlb*k+;lmSQO=r@hWXdbgqt%FBtnP7e*d<{NA@2`bbbmuq>8+ z<@##E#gKX?X#4g1%fRatm+=f_EFn8Bt23gl=nkk66oT1ve%r5V^cQ6d9Yq#-ootl-n; zSlWP=2LSv+E;f1w=0*0Ec1DVBa!Lkn z<_0{5ltO|?{4Ts80ZStXJ#rUI3oCnG7Xiw@=<>H_|s|(Pz-(W-$awaB_hpI9M2rx%D^2bUfLr=dPOGZz~(ml222U!)8Tc;8vu zS?Yo6G_%w*F=Dc@GWqMlGvK@;3Q_`;tc=Y6YEiJzb1()6fIeVmWoYee|F1_%W|l^Z z4tmdcvT$;ZbmIWQkP|rc{t)7DsNR*kCjhC67mz70{g@c!a zm6w&Bj+vF0`QQ3m8=4ur{y+78b{}&7zbReP%pRQI^{=MC`IMrO?caX=?Wcv=U(Q5M z{+CKXh^1baOvBg4P=1Zn;4k%6h6m5C7;KmKm8|7bV+KNy3)k)AP^KASNEJ2M+6 z13QO-Ap7 z90r_h+?*VS21b9gjemmo|5`jY24;4Ke^~_QKg8o_dJc&HP$oaq|4rS0>+o+86oln( zZD3>u13l9}BmLj;0(t%4{PTA+``?^`oczC&{EzVcFI@kH>wkp6|ETkSt?R#V{f`j% zA9en(b^U(^7t+7>ibhsog69nG1ie*HozUdvNR7 z`TQ61oeqr%Y=n1^k`;&Fg26>)CnORjpalSOK`%o$y=#&?b>!dT~UaDmT0U8pr8bq0-ZJoV^qL)8L4%(&TpD`kY|D#adxA&Ni| z@c;XN7+%9j`(PxUNl)>#y!BY+9)zVn{>pM3WME@mo*D5o&oPVm%Z(2T05Gz^HA{k@ z`nIr}53Iem8$n)zBOjxROnfi^1%NdS#S|aOG(F2c5{s0%Dk)Y`FLF4>)=H(4lM#=^=THH^=z7Sjkd zBp(bY7(guqpa51A)~Es9KaBAH)M-!=S*<@ZsZ}Md90LrXX?fv3o}>IAOps*9@-~{G z`!yj;Z%C*vIW^I2C_uNW?27>h1jIF|>nI(e_Ed#t;=@p}yqRvFbZ;+zUyBc|N(0AB z_}(nZ!a0~_jwnJzO+^?o+Jze!*&EMiC;n@}m(J$KJ2sLXtsl#+l#E@aUqZA);>jBd zz@cazgJEZf1o}vb#U!Xpi-kmd>-cz|A^NQxg$kNC?sGbNKgkXp9z8!vf9>bDjY-dZ zj7C>rM4h*pYVsY#kPmg@y`?&F7tl+z4KmEi%xA#lX&$HQCMWNrpri{bBc6V15YKm2 z2Zf=EqY$feAcFgSD)j!eg$BU+MT|xR1y1i0hlNUv%W7`A!c!pD5f$M;MMY3`o~*Bw zC^f~F=|B~l3FraB2#cigo8qhEqWDPk4oKo->FGAo8gYJ>AL+FZQG433!|nCit-`w3 zFhZd_aeQXJWAa1l7RCze>{}AUNh#v@-eN=1JM!QsuvalD%S#gm?T*?iNmN9brK9$f zD4TiE%(v^23*!SAqFg!7+Bk48sK}*RmW($qQFycKd0INR)Mo@D6vCW?^ijlH>AP^h zcHv%c6Y}jZSbO?QVghlmS}`bd2os{>UXkF)@>;yA@ocAaR5CfvOp+migL<|u2i(+0 zP1CJBx_a9=x|2R$w-Hf=%`IqFW*p2c7T6!$P6yHi(wG^v7_x-ChEt;?IItwY@Jbe6 zggeLPeir*ltAPT801b$4uME(Y)&ji&wLD6*6#zQB-7 z=&j^MSRhX`(vFt%DsFYYp+Er;z+k}Ri-64*BkHKcQV{u)6~LB8_ehV6xtiONwB&Xzqxy4-4`R4 zYGTCNyb}%wEfrNPg_bvms-v?83yNvda5qKWctQUwI8p5A?PiyZiNa$Oi|U_e7GL!v z!9l)rHu8(L{`i>+Vo5dB+1$?dr?r6ofmj6|v?&_j)I_AYPSbrIIO1=22ZB;B!u2o| z%%Nozfp@43^I`ib875u{CdQBP)2!IPq+Iw}o>>!3x{_{Wqn?(pqm+dX{pKb?)7@h; z;PaVCUlgc9fhBzH>Oq?6Ljv6#`)cqMe3mV# zflob=QP3;hF$Mj&Zvv?ny3NJw+f+nnDBM&&&mw&tp7p=aqpPrNV|q$djI9l%4ugD_ zzywIdg8d?_I81ju>Bes&2>A^Wo~2=Nob&IC@Hzio$9EgM$b`&Vf-dvvic1SDIt5a~sEUQ}kt8XMH+N8)=bR3x0Nq7H&R_J1h#t<(ftq7(GW7tkH7J zgw+bV<9qfmUm9y%TN<6)u`Q3qZG3epR|%kK z-8Nfqi65FLIUgWJU_B;4!H>WuAW+=N)5IcVouZon4MXR|=XPMbUkZVS%NVTbBo-T{Se*vzM(m6T1r>NUafd!9e^n>A{n9 zK1F8<4F80FSZU-5k|aLgvdNeGtEqQpy6@i0;zK<tOY>+|Ex)Wg0-YZi8Dn)*L=t(pw>^6aqLNMgDl%3`d;>(VeXvB<2c^~s zYjG1b$|#??MBLu~+M?HvYewoI4y*Yhikk*Xm#usljC9w+fv{r0v&59UNvMmeXX9D>CQLME})cBWHwel zqeP7)4pBqsYp-Iu_4nmDA;a^>id1eR00~3!3J_ord*%Of7F<{fUP1GHt3NiL$&q;9 zyeqS~oJ*+Aqyhul1Wj95J*D3w$?QBQfmjjQFWC#J%RixDI@&M@2$ z=qb};2oD;tD&dv%;ZL9A5+9;lC*+8EsL`ychpR@u%99YG@~^_yIOA9z=Re4Lo+)EWuGAqwmN0`$%X8bzH zCt#PJUSrOzvMju%`h6>d-(Sk!E!LLrNZ=diUyp|^dbj3)uaf4psaDtB^SKBgDvn1J z8jSah=t>$IcJ!JCNoj2y5JXW3kc*GKzhrur+>{3QcjI!adz0T~Y)k}8!iXY69jY&r za3(dB+YSA9{ZD33PQ}S!&nE;lKx3J_5{BSky$b|`v%5j_wnkC!X~42-z^Lrl_{Qz{ zSGrqkD;DGSK;K~BOavTiTkH6o&n=C#BR-K>-OuP#&Z!u><@0LYF(Au_s)cuw_uwX+ zzdLe<|G7ykkMqKxu@?C95=;_MR7j{8;C^~)B)#Voz`ZwcrjCFPg8|dD?L>4gQ?&wk zAgwEep3DUqT##iKn#rYDcW?op$8v(b!K^PBb&aB$aYh+xvL9vQ@6&U0sV=gLG!?0` zJw&quYO&+KunVjg4NP%Z^>eLV3WLs?`EzjRgiX%6m7iw|Mn@qa5tfU4L6Bw;=eh!F zJ}m=(Y>2OEhJV?*D4Z6GzDw^61ugN!0ymYdtxc5%BROh$%vB~=il=Vy43<8a< ztReof?b7^jdK~=Q;qS=FobF+8f}jHd3|Jq1HSz#Jb|PcUMi>DSx6UZkfk&gTatg%( zz~YGC^rrh;xtfRqDnCAN9lc>aEK97j`b$ZpBo*5ym5;hJf6i|+Og{N2lA_znyt36Y2{kyw2IzzFZ6 zz-w73?myv{JkfC|56Kc{ce)AoWv7^4XvY9D5N^bCi#;6Be0<&&f+@Bs2Yo^q9C-j# zY6QIKhYSotwPHN(VzhDAi8fPq=$<_YJ{m%%j}gAE8XQd$T%ZEbzY&$O5)*Dk7)Pm) zSm0_e9(3qTH{q&@^YuA*DjZ^PyRJE;(27p0MZgp5IR2AjWvs`t+-rX1*uXz{U4(7? zLV&lFtMv|wG9Zf;h7t=Vn*~9NwG#)nS0V`-7N_oX`uo^96JhAf2`wx;*Se>+Wr$DI zKxwoAzAg#C>VV)lf{ToJ&;I5=xxR4K0-tzQ({8C!q&jewUJ zAxQx8jUKLj1#ti)&VX#E4!2eCpx^X+rtg;83O*ddkk6RDZ_%IwGc{tX>4h$4bem}n zpvOZl?2|>~gKqq~>}&dL{tqI26Rn75Td@+zH1u;M){2~tNWtW{V$w;7IhpB0_U|4( zq-d_;cOK~r?eMs|CZ;wg&}(Dzla6JSH!WM+ z_-ZBGxGZ5vSPgaRPH_}QSN4_l$cri>6{DSfHOyx-AF;8u5p`+Fei2eRvD=;VVoGb9 zY<(gI#eGY2!Kc;=V3;{V4pRj$4-rhcV6%!zP z41u`RzYa=OkmzM*vKon)u0cuWPj=-ymzuziN{Z(-Lva5X{#8K!FLCVw7I((*8Q6$d z?!4|2*L^&>!>i{f$X=LGm;^su?)yJGr8Mh=`1(-7uoJ_Z(L!y@zADQx5w+4|DRaX% zt=7=xLG8r05r9B^*afJjjQ70E?VC?H8a1A?sb@hXXD`ezan@}VWRPmv8Zyx0$BhZd>;fdqxt-1t{{$4l=255HPj_+dOzbE?)@n>)D-pKI1FVf&Ae@J z&AHto2R4ey(h`dIh?2*68Yz~rBfMNp(L~en5paN@9P*caQ13!v-xn6NrX<1Q72@Kf zdf%wDvGypy6iifGm-LT&meZ(*B15qN@X`+^%n6SBc{z}TvqDDgh=1hf_;7HbzE}C}BS=ed4o5{3KtI3tMoK!gnp3M|u`37q zn$`diHdQA`w^iH3TO@k-dTV!Ulf<33J}9s)n8$05s9lb1F^gH)C)uX4N60z*LSo{PZ9EUHjrB^?RIW0I3`8@>01@EgtfRA8&nx%5pCje3%bT z&)VoF?hqKn$%wU5k_>$vl2Jocr+lKm!KSEOeS_y^AW>mJb$&t6^6S;7Cweb8aMiCj z09QL6+h(DGjgteOX*NwEK@L?R?q97Vx8h$t%OuD$H)7y?a?E;Vq9~ zV4c=O5;mNVB4ffPD%H|IC7QLDHXm5hZM54SO>Jr|*5GY!>b<_0vv|7ji zsi7}onYXJf?usL$Zy$a&BYG{6bbi?*S2i$3qJKw)6BjG2eS=hHYzP@JE0G~wc-%{) z1SWUpYWf`(hYK78ebS%z5LSstkAEmwjf|pnny~`TWysm>=e;QH}Clc*&pnh&I@|wO~67 zmA^cX6g)Y@)@rZo=#emBp+^x-_nEedGN=?WT6B}_>xYC7+YFe%AOL@o)NSp3Gc(_4 zeW?VV0cI&SVVcd^!b>M6s1>q3cc?wM|3mrKz&2%9V*3pNX$IqH~+0IO1o z8PY$HVc|%EPv0lZf2tY!$gP~Z>;YqQ0j%wN5vnX$h zP3}~P1so5p=b2FUx!G8IzEC%UY!qhzJ|7BwQx-Jy)EdynE6#lNXOd4%*l>K63Fe^b z*c?&2uJd%knCBU{r7dVml$PLXXE^wHX99m<*8DX0eNf8kP15 zpwDf}bcBKdDrAZ(S!F*}7WW$Vyjd1Ri31p3^zhwTdUnLfJ82TTWF4$US&ox*=AKYE z@JWQhkiY2zuOOghug63sr@|^b?oqIn;&W>|FV@2G>&uV>kJ^1TMb5J@AkWS%ne`h$D~CBWDx9eKTDGy3KoCj%hp? zR+KOk#TqY5%QQXwLhvZ_rCraH8{IM=a}6IM(!S@GL%QV@S$7tBm5ecroke1q{^Gmd zK_*DjddY6fL?w;|9rOLgCe-?}9xe-z0dwKBm#76Fk!B8NEM;DXZ3F9`UIB4rK{*sc zTtq4*%P3~QV1=KOw4iYyYRNy%3kSxI23hT0hyZBdJ@uEldJ7UQX!*1w0j2989UQzvE5Z&iT#%zAxf$;A5j zO}S^KPa7YI(rB{1J}-GFHc4{3?QzyhIRTwO0m@MzUxlqGuh_pGw@^5n&EuNRe7u@X zIkEmbczT7s2c8||51tHrfqtYgk%|2xjdzTT_Nz+(lPDtHYbufgE(@qnwmi%!;K^;+ z(Ie8?=D49Hm&(>udkipU>3F-=S~87Z%~9=qdBDq7{x#bx0BhmTKCw*8BO%VFv*=Kq zW$V^vk|yLv1ORvRY=9&xT(`;f^b%i_yOUGqP58Q2yFRmDs*pxp$yUM3mQ!n&1MiPo z7lf!vD$1>KlSak!g{)8cIqXNN)G?%?fe?T}wY0@s<=BOPNQloy|0>vvkEv@-4aZ@N zFC`LY6#X$V(=5Y`P^J;iGzluAsnJa>{>j5+btL9ol>IsY7-0q11K}}tn?|$%Lr8Q?jED)dXv!Ec zWZTM0oIw9dR~?UA4p|sefo3y@BN=85U?Bi-5JL5$j0ikPnK}&-4QZibiG6*R;k6^- ziP2ua6&3MuLCN}v;x|SkX}52X`cvaWfN=N_5+7GF{@_rxr@{Q~u5;xCjE5#O98mRJ zmZ|RgsKw5-*4?)J=KB;Qglsm{Y760G4{Iwk`>`9e;g4M3+0S5J^X11M97(Kb-zigH z1$G4-SR7esaT*1|DdMHWjQ4`4@<^TQEMI%pF(SJ}eqrIa`vUa5#2BZp zH{xFd{4hehD5(1iP-ci_+j631PL^)x9s)MgygrY3x=4a6Rh3e8<1|HppYLY;lIfzS zolR0?m+kLJE0GTI-i@t^2^h7Az^Ygr=1;{Ll?YKWIsmUd7Df_m+`5lm!a&Q@X>4l+ zDkoV;k4W6hC~8C;btsmVz{GsoW4;&USV*ns=fqz#F(g67*}@`F47d%UQoyi=Y0PMU zGG1;jzrE{ntvM`)t>Wicd9YhwVwag9CS$VVkJzdUOkVFq%J74wMdUb zpbIHUiRjPwSP&7|RBh**4^_et$Vo(=FN0f4 zu(8|Xx-te0fVv=lj7a~iP6}cqAA2vfxAD+Hw|A{uPW}UAFg&F2p9y|ILNI2OV$t?g zEFURe6E2=oqR+B4-HW$dfbR;nyoP+S^lY>G^D&eP= z0z*!@awf|>MnR7C^YkK}PXsd9gJho|ULN%1VGZrj@pzO_+KybKur#Vu*a2e9d@N{? zE&ebxbpMe9NIJf6T^9Y$tgliN9O+U;`?u)0`<{8uA~*Yv{xx#15`18k;WEZq9yubg zYqJ)NPAT|FU1n+yvZ&}3Ff^j%13v-_?j7<98EtX?n2<5`%6Z4@C2$pnR0!E0T?O#9 z>!cu7r<8{_P@|-A?f6r~*Al;@#6Y~!v&cYiM6P7!5rlwtKq-BWf*yjAH!Ov=+@!ZL zQpq-v=5@+-*p><&HI5das_d!Hm$M1DN2VTHZ6`V!h>R+8{T2p_G|*K3{Cq<)XIl+lr{9f0`M(TgzS14r$|VHb`a z_k$?hnv79@t~XlC0`Tq(@m;U)FDEZkQU-IKE%KIhlH!B6;J~dJ*F@K2dC=6vi_6EY zk%*b@MG^k-7h2*vqCP)qXyjN#%|zk~os4YV#Xk(|1sQpNOp4zbl#!}0392`Lbw27Y z_DIGjT7g&EJ}>-180EU{$hO^PMBGMZUT?S@0h6|d+6o&3ENih_(2n4dH9N0ARw=Eb zJ6UUQw4$Ry1NDgYaNS3@H>--J_dVu4im90hCFc??aZ(+kfwCCRRs~LKfj`Ko395vO ziW$>K24sG%j?D&_3!i>vTUc(v$2`_(98xDI{gQy=+cis&KuQu&-sWXf$B*&dFoR|{ z0)DvPfo*@LuEKI_s(QJ;u;$eAz7t%3iEJv)K6dbZk@q|jS~`?Om8u&j^Q@sPB%Meg|Xz@vb{5I@!%-;Kysq^Wm>ABIMyL>rhsPgL@3f#oL*Mc+k$UshD}W z5v+88tO^f_NIFh)HPbrtKsE-d;**mvH3uU@lHJco%A?h{eZJVJxpPdMPgkpFP=bT- zo~L=pKAALmGF%-~_3yWmb}J$lihg_U^i8RJO1g;SXe_;`dpcz`i=y$HbYsZe4o(*EGE653F^Ki};2GL0NO zmU`fQdR%uVlyh?6XmK=Fh$=smATw7&v|)#>KDCP1_{UvvN`jilZ|6oetP^nNC`q_-pKkh^PcZh_|cddCC|AT-WD zsCaVN&o8BWHdkoT)+00&)2B<7?{?% zis`%wgGy*_xz%jllB*Qvye%`~|Y3xgAtg{hW6_~ly~GP58nQkw2|4GcsS zp=dzb_cnZzK_k2TWW;;R%OuMy9rHH9`z}45t19)t%Ij`03ZsVtw|-nV?iG>lR?hc{ zNnG)f7n?=`Ej0zEQYkf?NPXwNkfW9hhPRIj-7sbJ4VekVu<7QQ-M96+KWbm#X{OCr zm@-dieVN4l1)p|%aCcQ)O3N4J@?Bz^N?X98ezjQab@C^<3&i+ztRO4`afBb+9A(ux z3XRU@i+p`5XX#6odK=dt-BYbE-O>(H5CyQ~SOEI1D1yiy3gY7qHJuk>+Pl7qvpipW z%Rk-PJJLhzG&_g0wUF1Iptrc_Aj1K%QF5tA=G@0#?q@A6t{*Xe;^R@b5gDM$w$1rD zxGpB0ikYj#?iVr+nQIl?Sdys6dK|l4QJBMkha2LY|Lf+akh0 z4DY9SBU65L-ZeJgK4zBZRBClxSVB83dB&K~BLaV3?_}0jWEd%nuTD2VZoqF%YUsc* zm3MOR^Yl17p|iKRpVK=%B8Ef_gl0IEyul%>cb<4mDLT)cE~e3N8u>WFT8@D*APfNU zkb>!&YFtWy7#}~~OzVTX$B0(8;xfNePVL%YYnAbbu%+17F>e6oT{OR^dtI^U2wLvn zPOFI|M4y+yN}Tz-d*Gwp~eOgKJn|;@=(gNF&)h6>SsV_RoewUu*@Lxaz#ErwxTAX+yZL zs&>ciC=R{GD-{@fXOus!6{)L_Uz_N7Nh(tSCIHrG-`PWh#wD4hSBp6@-xJIa1GDS!A?4wN zPgD121^rn^FN|^tUUg16Efl|eXN9(re|_6MtOE57yRAbVzC2uv_O zzKdi*A7F9G&ep-`__k@%e20C#IZdi4i_i*0>0Uk_K~~{~+-r9hF9k&+R<)nrDkl8+ z(nGeu`pfJfL}<3I{$5!*+?WOmMioL`^`&+)1h858E_P6S!$WZKy#rge!(gIe?lqpZ zDJMCp>PjkdwjchtBpr|Shb;Hnq8m9dFX;w+;=-v++ybd`hq=<5nX3i}+7G;fjqN}1 z?l+n{N-MjbOc1HY&re=H7V#2p-edJ%e|X&};ar3bS!vBj_9tOGi^vIY64UWKQgSxF zDuNgOP{Kz^dXS7IZ1y1Z=+lcHHnLAQG@v;(55odbM;$(nn1!|MYZvJv|)(8kwTWbmO4NGy3LVPxyJ55$XSxcJmXaQe(Flo zw{4EvFCkg2V{HUqTN+z3SM8nK5~Z`l&FPThjGmPQXy4p?YpgkgUgnwN3JiV3`gsNq z_-?HP!*lYes>X9I>FCU#UceymOIoJWg2}CeDZv|uZ11V>{>5mT#3`n@MVq(8^TLYr zH@>%|4Kb0lC+0{{Ay76Rrg(p9HHfMR@fgG9xKwZq85+PCBD^tt5st{za`X7)xzQU) z?@_O_)?2x~^6j8-M5xYwf{kMX)>=<|)DE>GLZOIiU~sYOjJ819P8{Gqp1U*AVEY)T zbp?C>bUQqD#`D6s#F8y6i^k@&3tEEevia9OmhF8qYfY`V+9FY~7X6*ief8tSud|29 zy0f9|wJ&#?Sr9Ht)`R~!%a}$d^#_EPf-xm7b0S_S|uEL$S z5?7bl4-yWLf|;yC{k0to|cs$vb*^Q z2|i1KN-G7Nje_=#lT{vF?^`SXxOLs`RVy&P);L`jK>^;dGYcBHo{i==33(nB$#&m8 zBI?=e5#Gyn2rx{3?+X7OSQC(PY71i&bz-NAn-n#V1qgx}4if-8Jq-6Df2rnOj1g}V zlP787rmTCrQ(z3ebd(Nv`1**wjF^shp?O(eij`qUU>YA#$}6<~LnkrMC}?pNq80|D zpc4&|-=AHq$SNu;=YB1qcXajk1Vwi;{LzsZ7BB6a)zwI|wPH94kS1Vz_|g5t;Z4q! zoa3ZUg2tax;}?@{X^2re9(!C)R@$B@z@t6wbVB=pj8;VI!J=c;!P=9%gH4diagM2I z*nP|Cj3+}i-2hfSXz2(8wyl;WyY1thJ*079Jy(r^V!)!bbTe(J zo~d^g7gw=%Z&ZD-twP`|5r`#H315na3(E_Pvf!vyNgJeSd@$W>F*!?O68dFwmHu>+ zJ-@$UhDV-mdmEcYb3By@$!w~uz42Zatf4jmFOKAOmRB}4%ne@(PO==f9w@vyx~H2M zI&O_{WOy0)D|}BCXO&bQun9Co=tGM9u7Dl_s5!8!xw!Q;<}8F6jtmbKJ~>YISD?!3 zxMghEn}@s==<(R4jr~ZER+_er`J66Crtf{SqX4WSd98aA!>8bBs3q^{((4s7@7*|q zO})FI?+h=+UBmgfidu)CLU>wWmTXYSV2UW&DOx}N5F3de{pfCawOl$|QG0H2Zc6J2>jbmq zbDY&^Yl$o!`g{eO_tQ7a>X{qw&PE-|LmL$2%p5=%LIaQxyt0zAGU*?X!Gx?-Q;`T9 z!15$MUEj9FL=qpSjegnCX+jfNrMaIb>VegvIdvFVWlNRbh+=GnEgR%$IV~C5x;#8c zw_k^%!DX{Sxj*zzCed-Vn0~sd?r~z&7Zi#r_^gp+ubPXMs*5~2FYiU$WQDwbb_go#WB`CFSxzxR4A(!)g zs|IxR`wx{3{gs}uH$352R@#$(lh=l9g2CPXKEJz)GNG4jiX3^GHgD&U?z-B7d$P-~ z53?Evo2h5zPD@G|0;pu&c>5L0C3HgbWM>FD!yqV2* zc9%6|KJDAnts^h&!jrxf5h*&U6J@MnzkE1|4|N(`VT8IfDT?Ytp|VIc>EU8c z&Ci0Wq?FX%n;o7mt6T2A zyQ}cUI4*o?!BfR?Ie1%ZQ|@efw0D$VzL-D#wHAoWto<}H6H%S|)D&?d?l-CM8oHQ9YSivLdJ$q%&8ZR(16kR)ED?!p%P{A) z-5f8GYrw{VZ6*7*>b=CP=Wdu=bv3$k*iEu${Zyl!0#P$2wj!(DKJ_?T$tNYMao&CV z0fux|b3^l!;>r2ep@wBoh(}EdwUsI}A(z3+-~J{vl3dIb)s5+nbkb-Gp3`$Z>0YO2 z3|FPJw>G{j3491W^9@9eg5GDH`)ighsiADZfXwpOheI&qiHxZ8Q$yi!dJJd{S{v-` zFNiLko>pGXYAH;H^r8+R`TME~3~J2nAogf~oN%viDCy_n+45K*LOB{97{0EZUJ{Du zIlx}s@1(pxFP>VIlh@?}7N(B)hXHyjEwLC6lM&sCG31VS9^>h^7@`@%%&jHG)z;S9 zioU5&$_e0&Pnxdjx3-Xsf*(ZNE)~AYi_pUTuvq4O^i&i;M)OO z#Oq%qUM0ypTrPrTIL|EK5AF};mxs4EK-zWgJGcnnAotJk$Y&KvDtKEkWt1&x(y@*o z)MtIRbo1cFz#G7J3qLZI_=a3nwT6zHK27uA%=lj{H@b_bfvWIw`qMb-R=-y&r$sE& z2KWeWj_z1B?~U6i_O!A`W_vqEJl3jixxaaj+;XDpc|fo7XV;}G!IqO8^Zs4lm!MZs z#)c!gglft{Q|Bd<8^hf_hwhii=?#S^kwk|{CbUpr-Q+B4cR5u}wl5*X$|gG$8NI?5kIV!QB$rI|A{WKOC$V70w#GudksQzU9fh z>p5^oPpfws7=dpE%1~1FNEVNW`%3nOmAduwEYIZur|Iv!wU%lZ#o?1L(TaK}iPR8~ zVRX?+Aw{G(kQLMMI4eW3;LD|>l0t`){5M{WR>HoXk!vFlq?`~_GpPJ`moiD;WP9OL za5jE~0;3gA+p`K!*ZZm@jLW=$X%`Tcf%jtZV)4P?;t?U@aWW{IcBZWUM{y&~RfAgi zUOw6EI%*Hh{?nvb&j%5a5fZ6$-u)#F_mx!a7jmyY$=067k%RHDo%gQiW~?tU2RXZv z`&Kpc0GHF&(y^z5$V0o9H3my#nhDVXq2yP^oKIlJv<($OdKV6_F4&Q2f|_V*C1A+(C9z&X8d zwBbPjScj9tM*)HlB&>1<9T>h#dAV808Jv5pP@P2X2-1+rir(ZaUQ62AnGB zF+onZRJ*)SWZ=rlNWs!*;$Sx%1e$jyE!6z9@?7Yd#fSk%iTt#MBzO~l;W0NS;wxa7 zG}GoG;y>|(4`9tBm)4$2$U9G7FxuMnM4?9V#-~J*W)5uqA#hL=wZCsmfVMOVjTfdqTyxd)vGn z+9{)k=%@g+=4JA`CEddm`a;MvhZx;l?#?wQT2sFCe9p5tPme(X53HCh)D?ZRpZ0#U zy+-=L^T@~jPzs*3fY*uHRInR-Cc!PxXhg~(7B5ry6zoe)gu++!;=1;hfdaS^Ph4+f z^&Jfk^L!?rb~7^(x7p7}kYE{>&N_jp6&<*^$MNIq6rb-36We4NZzhleZ)TY+K79(# zej;M7!q2~Yx5mwv6L$m$P@jYe35kbF=otW#7GS8$X;OnFq5hj(zjcw+91^(umc^9jI13F1sWAQ*~Vz0WDY$;HpCqB)u@ zHt#nnC*(SQz%aN_6r_c1A=z!K#6jS_os7mQCVPfN?^h$_cKrDFgP0;RcT;}Om=Hx- zc|A>?p7N}Gu`x8`ew~~_2|^1-bPHDW8evh;`(`2_s=$Q*73zaQQFp4ZJhUd|t1Y~k zd+no+by9u;71{A~!n`+h+}-BCDnVbF=ETIwY5GVa7m=TLmWg1PILle+o7nw%1w~kY z1gP^!j&L~Fusv$2SNikgD}h zH4~A#hwbOvnnr7l5SmFz$Ht%#75~t_TfzStG-)Z84Ji{EjjA3JLrHNyi{5e%pW zE=~>|A%2dY^#|_@W?K{`JQL?4tq);XmfzmI&klLPt(6P;Vw!yNUj8~8j3C&Bad^f2l}rPJtIp8S z!uorpNq@iec ztBL1x0&JC`P`XsPgm|dPk7eiMV)IjL=TDB{t?b$Ely9#aF;Th;J|D4Hr5H@!t6D|B z`pX55mxLCnP=@LuM^A+k^}#Q=it|mo-fOmW`P~1>Ba(RfEDB__wnu2V-lG0xkIr>X z63i!qq_s49EWgKlF`@QU@Z3BzY2==Cat*S*=6}2nxq4LQy3LJ+5;^OD64`70tP4oG zKxaEW{t2YejxZ3*#p4(Al^bY&2z2LKp&}`rXw-4D8xPI)t`2_;Elx5Ejc~;TMFJqg z8WpbcG#FTAsfv-O4#*4DUXxL}Ed6TX=FU!U>dYC*g^&%k`Rdt1X)lIg?|Ez zOaSnj_b#v;mTBdrWjB+HAjLk^iht?cjn~^ficABA3w)&vrRxpR!wbX|0jZvqOf~R4 z6=>Zlp`egvK0Fb(&B((;k!|xNQvJI3x!>0N%(2WptD$Fc%#9yYQEQNp&<=b(BlhQ7 zd5d((P&?KFfsorBw~XxY@kf+eo_z5FZRj+G^PjupnhTH4;c^jomQ6+ChJ} z=<=tupcy+};)x|$`OLbDc8=irda;A}QSUjg4)fr%NlMC>!;GNHq;!&gHpH_cbZgwgK(K1@$@15A@8VwBiw3wa zUp(4>2HM2X5m)MS{N}io-y~pJ?DT4&|L$xc4py@0<{G{fi_hjqzOS2+;uzGx%SnBV z|9t%TGzq^NC9^rpWVW=_Pb^G-P14Qsr2N|g8}LB753M|Kt`mSp}B18 zz|JJ5=2LDocx?i#O{*_Fc~3@!U0WbSTub3|AC)C~J}N{PxxSq2B<%+6O}NF-ZmC)> zqRS=aQYo_E4`p=Ek$dhJ5_Ck_3PP{D#Ic@G0ZK=g%COZa>&TDoSsE2XvyM-IbL%7a z3%%}8&p@|#{3t~TVx zH?c;BDMn^}K{9tk&9?F(^ zhwX&(dlp{6z}{se-xQ9#?+1G7KH*O5XO9Zkmd?A5@}qF~tjM4;3Qfi5<_)y2_j9lPg!o6dZsvTbEZ$f7d7l-cPw&u*e~C}y?ZovNG(^Uk z`B;vhzScyse2C`0{V0qx(xi~BL_)QRlw_^+i<&ID@Q>~JZxMQ?XlsC?A zGV%TqO5~0ayfWTes+^Sb;ANC_$w7-}!pPH(S}B-+Al!1rb@!tE_AQOeRx6Cl+Xd3X zB)F(-->mJLA|-Q#!V~c3_x2+Ac2dg-3^k-Mvwhefh<$Cok4JLmQ2(vVa|j>sYSIkt zPPNiceqX$xtNB59l%V`#F!+h1j{NZ||HNn41iJo9PAgH|Nxvd^^AX&Ni0f=?Ch2y= z9aBX_-m(ox+@=vZh%4GO74nuoI6$wDFoPG_P1e%>FUr39EvoK|_slSKw=~k-C7mkL z4U*Cwf^-a^G$P$8AtfcuEXdO_lOn`H&SVyqd;v0MBo=6qD>HLz5+|$ld;dOJ;k?mAowMX$^ zPrP8hklg(Wzh09L<}#Y{%x-y}e`!LIh z>h6)>XvQ+V-pTufs6k8J`Gp4gDWAq`k3(nW} zR)@Je-j+St25I;n>`Pd|z;73|gc3YS^0yaT!9{QIYhhEXKe&z}`0ABHNDXM*pGppy zP$cCdEDNdS&v(EfCVX&^YrU|k{`X&l)KLjTON+k#KHiSR1t3*Kg7rvP4A-;j)BH7Y z@^+7f$7ZdaH68=;$t#kQJE+>N_};rX(e>$LdI=y&SJ?55l_et!!*74s{3Jjn203ZQ9xjLzVxrqs zs?3iMz<3bx6Sgeq{`9X+a^pUH-`wmRYwqGcc+g^#SLhtXcxqI-?IkJ;Y2s2iM4U0- zGq%e{QT<4s_C{1~BiUn^8CVbh%@n{_H-!In=J6(IzY&A>{$W;{mhyF=qX^~@Jjo3I zpV&2LSXU+O@^UMV|2$dvlqcbjo4Z0(0@So5a@N)BJ`(s6&FTvF|LX-XHv}ghgyfb| zEX*_iY82|2p>^0x5+RXqSoIpl*44Q@*MLLLq8|xXw8I6?#CQn_kSJoe>jq4M8Oggx zjeD%2s%gJ5EmIpAT8?8N>vfCot?lJ`tE08q4|3=~0tyQDO53Mwa2Ap5KNspToCNJwDV@4)SDu|19dnF=dJzlL^Z9R=B1(*nOnsE#3+=}Z<;<(~V0VwdC*Z&=PTZe{b(JmJfSQn? z+J(D%a5Tj~im(%KenY>n=klib*0_e<;CshZ`;~YCG}#FqLzuP>^yb-P3&HFX$LB}l z{FEI_&|M<_w0|qep3WUh&i=v|#t1*H<>*2T+ZSzKKK@K za&{7iI&OJ|=AYZwtiXCq?;fs>oBnajO%1nB{?_l5fVl!M++eV>o8YN%5t5BLB*WE}N?SJX4K6|Ml? zIQAU!$>Z1lpQAQa7UtZOlOl{q;EZv-1j@PwFf((@3aD#tGfS6iOx^!WK`XrA{G2XQ z)MI6dPz_IZfV#n8IijhqKl>;B%>1x8?z(|W82xEfHP~YR9RvT~C&{=*WIb8l1<~>m zFThdwSE(7#P0hUgQsA~nYfuN zjQr;53z*2rEzdSH++!6ZvukI;pWmJHNQH+vJDMX^h$apLpMRrxBIH^;8-e5OB39U9 z&XzpWqJJaM@J4SLqX@Fxw-{_l1^<$q5rcM$ZSe!ePVNMs`3!HBp+5X5v@S8 ziZ{dcv(xeD=4Q#5&uPG@z&(x4ulI2lL-!HUoz)AbvnE}RZ=v$>3^?S_Ul*$kt%CLJ zzuK2Mekl#aj88KY;He9;Vb#go3y=j@og%Fg4(s_79*AC{XTYo zDa;xCA^+9dE7zF*#E1E>{l=H_IGn>x~ z+y#)eDfhmLPE)-7iSg0z`SYKucMbLtk6X-g+u3AdrN1fR%O5W>=9&<E%jj2(w#R^@$&8Jk24Wa@?;N#pG^Vd(2EDoi_ z3GeSFm7pQ`kN~zXkA|@&9_c|b8N1;v*G8`E6CrKZukivc&@DX$+gk(J|F;)R$#8L> zta@wEM|>RD$g51`Z26ud_RV4lUKWAb^Jh~H*f5Jg#ko+z%nTv}$8~zgnWd!n2HjFq zZ=h#@^vu(7ao~Kxg!!G=`|g4-ewnc)P^X7j63QtL_j=fK%{YUESj}&qyxhP_`*2-z z)CoE(-JM|1cXD=CoM>VT?btJ?Sz$$BcaXKQ{%+@N?q|l>N!=MIC@wHhfIB5t_{oC9 z;?s(`NU($taMt&WW@p(Cc)*;WoSC_N?GG`bsAzhCwtgPTwzf^WTiIp*o zy*7Ha9pE-JkXsVyeAePW5cf($&6@Xga0s82@3S=Sb<5riYt8B7p*5Cft6Tr|u1|UH z4rxnO;#10?wBT+UxuO)TPoVab~R7ThIP=jvaxWu%=L71;M#mJ4TywHG~iavzid zz{ECoVIPzJxkw_-w~qzgZZQ-uOYzVm4}!v|nQ_&__z8w5v5Q65rm>-3*SbdJ-D{Ry zugJ_3U|Ia96&#CN+Kqfbfrlm=i_-ycPJ-@<-m5ZCiK4sjvqzGD1`#MWB%G)e4PN0W z1rFUYawO~hMkJj5G=sQ3gU(Wh@x;fC2LLDYTXgVGBI&_Qzk0Jo7s*(M%wzE}CE1E| z2dL`nu<5nE%OZnXsV+~~G%*sZPe{KXhbaId zhCDr0Kh2m{aa3$1Y_9s8uo!vLVUh@cm@!v6^BV;-GW5o&eC%y=_cliQ9#taqPNu(T z)ve++;~~RYiN<;%^4-mS?{i(a1UNtA%fq0#1#d`~?15fUi09>RlNl4fPsd9|A(RJb z46iz4)~nv>3M{n!tnT>LRM$Veu7WQJ0pRbF_fC#x$30jx2GfF9V)gI4i=$L}=74<7 z4l?=hHtYOBn#dSW`^m=%Puu;aXqk47%6^}O6i(lV-EgrWcw*G^trUWDPA=wDp?0(l zcaF|Ja%m9v8BRN$$vT#vZ9X`nKpwMnyfRii*G7gb7iDtLQ2^LLe5W;U;Z)xDFn)nIG}Plx zKdAkZ0kFD;H7NN5&rQwr^Y8yeO87SjzUN;=RKqI?34A;FFY%hw}-j$#r?h{u{W>FN!N>?e#}tGms^8!p8gwYy!a}?nfnAkXY7Jl zE~l>JZ#gqxd7EWndh^}HD`OG-*=D7{lF{7Xn?VshI{@!2u^ z#%Ddz#8x5s>MSs+^~6-O0|t_StJ+e*fXiOO(n76d3wz3r*rPCh9EI{-Yz8V@s;G)x zRQmFRe?>LSad5sS*+O`RG>ONy3TUPZYw5^Zhg*r_TMl~BS>(!b3aN4-9o8c!4RFtAd}p(kqPDlGBc zhT2kWk>c`4n!6KMQd7|M?=Dn0Qu{!(J zL@0`mwb}e7=3`sVrHP*c1^oOSa8>su;xTr*AXK=!bO{Mxp>-pHG0k+q=ZujfEG-f|U#S&_DjDK8PWj&J2kV*Yj;g5zbu5L7 z*&PlXiNAn`{Ke;r3S@^O<(%ePLWC!&&)>PNaXMmyPG6!y+gu-eR&QOceE*5Uw*ymX z<5W41(dl(Cy?yH0;dhU7{R?NlCIK%Cb;~))%1%KZ;p9{s^sT$Ckd1DqvA8&O@r&?%}7Q&1u@Gx;WC+a@L&Kj`xH`?gc3wieQ*Xjxg6A6q7nzyMu=J#a#B4NW1VeIv!YM z-SA@$$dYfUqEwCJEUE~a<`m&?NCGQoucO#K@DA`Y_AYBiJ6hXA%OOi_)b2{9Vzp6;v$@d6Uv159A)Of5y zPDjSi^2|zfAj?wtrpOTct^nW<9M7S8Z1oEZfvTE)z_|0>-M^;6Lz7l0_@=H!7srwp zo{!5U(HfDPC1}2m$CuSotMX{~=n(K_+{#$Ga*su z=BZ@eJoQ^10zD+z)8Vm~q~+$5PZgdZ~ z5COnPjT`ea@ttYI*rNeQf6Q+)DfobWAX9`Y0SO`^M}HhFT?zY78k0=bqDj?)s(}GC zbO=$c3dlo|Ps(LNlT{0{q!VT~}T^jNSzcQngT5=pXH0v}_z088}CrYy*SB)QZ z;|ctpHG-K2aA1-I^eKvHFsaXMLpU%s>;o$+Ea;7_%BC^_oFaT4IinV%CN8XEh9DD zt9M0iE|ob{pQ@WWE|%WM(0BX?0K6=X?VOu9)9#i++U7?uZ1&ynfL)C3| zDZ1jAW}}jS9U343`%uPi1QnrU>W|r_k7w zm_j8%$f14PHQ=-KaO$J%WoD&~!9`3xct}>FN2ID@@-I`}`mTpA`E0sOoptUKL|S+G zv@07d#zLQ*(k1*sP;Nx{&ieJ9AF;U_%f?HmqK|P@+>jjCs&-m~ zEo{bPiTUa4$I%7@I#z}sC4(U^2d~n900e3D!xt%}AeN^}Y)+W7LmN3bDk@{FL9Ooo z^G+X3A|8gm-z#r){0yN|Nppp~E48I&X0TR-g;mEH;&PYwPaExXOBnw7Hm7*5+ceMe zn-X|8gxr@-^e~jRv*vebQd3%2M|7UV@n#_3Rt$H298lBdQh?enN7RE-bd53e|JTJL z(svs!2JrEG;pi)-KQB6-_g=pkr0x5PvPq!Eyn*nq|GvC&%N*-rangQJH=1>v|3k}d&BJcE`=?}J>5u$4HQ zfCwWxUUZL=I$*9Q*=YDx@j9hm=_9KO!NOmML`RN&+ABacMDOs*;oMTw={~16z=Ebg z8o*JYo0y&qsk_2T2&hEn-RAs#aT{s!so{d%?v)ChX;bA*HC@gy#~WL;1n?P%-vyX1PQxfTCw$DQ58?)^N1EC?K2xof}}n zBk7hUC=AizMz?Cg>RnM0UlZ5jWrccar$SW2%b9 zv!k}_r^|x+(zs$*vduX@$s}1%w3QTLGa^g&CX`Vc?0r<6Ous37Ko3XNIx&w|blV>k z?;;Jl!RQ-BfXT<+({=8IdBpx#86bCd6`Az z1zJtxzU(kGDy~pAXPBeo;sb-;J~4cYYs;sdk?p>F<%zAi*4tSTvXFu-8coHYol%I9 z;H?WtH6x=&kiot5RC&C09)$^J#CHLKN=Et{nsp0`f3Cpt54C2zcY@hVzn*`6vgag#d{Guz z2CXGckP6Wv@gyNpCP4`Y_Q+#;3`8UKpxkX?E$EvhUTYGixD$zN%?;A zCx`CQ)YIvkPu+HDNK!aCZ}HwmMyeVZ1=_f7cNwZfnx|0Zxm{NQzm1VMIDkBkiH>Xo z`ya_febjVw7l%}t1xA#4?SJ2b*@hHA?Z#+d`SqBzBWV9vF^640U$gOuF^9v&%2P&! z4w~%7Swf!s6}b?anCdW5e>F4_72+fiWR%iJ6X~4x+qzf=l~AwXI>U0$P^#k`QQ#F< z(exjSNL(-gs7#1(SuZr5cLY2fq++g#PH&AZUhh?=eW=w{ zu?@Y3&@do+`NiV`xZWN0>9Pr6)}3m2Hdx*8bGi5c>-RK;2AWbXPf=HqFAW3W#_?3? z*KW0GcPw7NvC_?oaJtN7zg_u$y>bcE`JlAo+RCO#Rdpk*niW*3Z`ALgd`fU|MpZxX z<4GY+I8>2lz4~o2PxAq1-Ox)tyyxaFdTd#|#YLVX@{GScw+ruOLC>M2??Lgt(Q#^N z?9qD&5|d^I(EzB2@I(B^oIk*lB#<~Gy&^EDk|)SPfotKa znZ$-fIH-4hNV?J`bW!=DzZbzU9sNc7m9~}%sfpcx{K2?uHvXw!>#!5Jik+fo}HoDITRDv2r_h!sE(-1UFZ$=1yP*sx@Mu2!6$~+;i za*fa~kNkji`ZA0BjZCp&IMIB5bZ5%qUX}a@R~8Hr#|&wckVIN3ha|qW>{#eDENaQdQ()MpIdnwlz2$h-s-iCDK8LsykpSuaQs=?bG-+3O zxjd*}y`4i&hnMzipVoEA>M3sCd2prGtMsOw{^dl2+FRn&$p`h=%Gr34EF&U*8y0AY zh)~m3L#mm&89FZ^r>SZENXxxcz!FTrHa0kltGUboV8y}Tt|6{|#*2%!^&|Lf7XcOaXs|H?# z%JPcxNCZan3{)?UI(66?ME$>72n0gOf=ojeEZ=-kgV?(x!{i|_TsR;#jgKycGiDzl z+9FepgxU4x4AJ4By|5eNE9CVm()s}`MZ7S)q;j9rH^*g=M@hGM`G-dVbY=63raW2d z9zSrfl0^vSM@*#&PHlHg@(QMZT7MB>R{N)_YY`KM3T#DO>R*-JJ(7vcinc$#9aTaj zPe(U|59D{))O45%$l%DK#9^dQeTkbi6(Yx)r{J)zCc%;GXW*q%3+nz5N*%$KK7xY? zDPhVk_V#2@xcSXVC|<$3sbTybwd+lLLK>Rd%yn%zWBj-}vnFA)iJ-iZ+IZg|dNp`A zn>6khbJ2oB9M}zkyuC-7oUS>VRs0#o&1B}*PdI7+f`0#gMRXnP5a zPfrrF<=#$XxyBA+vzAs^Cp{tQZ$Gy|;@}&M{t$*5)HtTj!(TEuFkN;cu%4kb?Ssh& zSe9bOTGvNm3?%;oM9I5Xj@T%Q9217k3xtN}hPIX(hW-p{nwEHEX6oR_h0 zrN=dW?|T(mU3bP>7Y{fbujlFd^MGb~@>M3r9LRgHnsE|O4;~3$@wg*rE0~t?d2_%@ z(D%Ij4vV8`Og7HB5cf+=0p?x&Q;}aRoy*Pf7nOYS5+vXE*dvTPjwso?nkjmJx+qvV z^*r`^(6uXcc|r-#!`3m`@SLC=tcxAb5+uE!-G#l$bYv(Og;kX`6 z<+iviA>%LhFcb^lZIQPRdbqr3m%zOpeGF)# zk5yDWzq;MV>WQ;Y5SZ35#UdEg5v?kF#HiiVkd9czTN;I7dtNxu3o&R+Y5Rk zm_dzmgvV{%ZRzu$)uq`gxv(%Xz^(Uynb1eazSx^WWVVzuC{{4egl7w{mw%Q`dAIM1>RDs@ng2Hc}$)^1)ACUpARl6 zLc?~^Pr03;!rmo^X`j+py$-(2xwAW-eVM2Bl8u%1Jui`4W#!bb_MWL7dPOezAA#5- z=|+#+7km7y?Y_5ppIqNH%5r7Xsk6+seHuTX{fa&Nurs7TkN>~ls=ROZDk>@{cO9`? zy85{|H`x~v==GZ}T=&z0uhR-hUb{yh{{bpBs5uvE`d8$aZr2y(x5vr#WsBNt12d4@ z1Xw?wV~c0fbr2%2&hvzl@uKFoiz}Hijc_pGZ-$1__$( zxla$(|Kb@T1HCo13`b}Ex9#wB1s24rtgog=>~TR3%2G`%FX*^6wCx4Xtu0&^?blOX zVSF|NRh4_drbn#aaKn%P*h z?V*~^wC92OsbbA}L1W6U^m!xCYf6X{{y(Dm>#lV@sO%dy++6QB+kN~zwEWg^$mlt} z5nu+wt>ijv#=m|xl{`E-t$2D->3{ie4WqrMov~K--1SYV(_!O>`zmcarYv*BPEoGb z`EWbV#`RV^j`ow|pY3iF#|t$7BPTbvV5n)| zQ8+~8S@FK@CYBz(P(rY_I$=fhf6Hw8p71rAypjFy7MFZ}2Dmx}*9!jrBh{#!Bx~Ry z<#4ubm+ZuJMex(eYk_7Iof?c_7xGFJezSLlSEVu2f{&i}KZA$X%8zCF2IPYp6$xN$ zB`jS93Oi11TWJ<5Z0#mQ`-nK)5b8TOWU}|~n!H=ETLOMOWzE$cS1hh=e;MQs%xHT> zu*9zWX^Y0mOK#!cK8NA2y`WV7WwrmQOwm&H{o9%1q^~~Mlp?L(bAcge8jp}4X@j?r zSMOqF4R~sJK5p`VN@p32plUlTDLAwz{7)OQZPq4w7oyoSpDX>wHuhKj+gBI=pi9qm z5F)&?1vRMjXQ^E_zu91SvayhrhL;P(2jPDLZaVUBuPy#=)pM%hfPJ{^Vcv7pT~t2O zh7*ePF`=7ov(UnoroOzzS0lV=J-6Vz$fHW@f9ne4%U5P+M^_2UGySj+#hiV6MiCgx zi&~_vkp8Y?$`BwL@D&gU8h&!=mP5CC-aU)lb~G9KA72dm(uK>!9-jzT{1C7Yy`Sd` zM6TzWm9H>gW~na-y(%2H?TQ}S@!IFexIeeykI!l_9U$i*ru$D2w`n5xWgEJtcUP@% z+E!;*FU!S{$x5(luW0*Af?mntA+lwvM}Ye|8mZNvgewq_`PYtH>>#J4`qZGpp^^ev ztiZY6^&tVA3oZoDcfojet;>x3INQhsu=O^E0epZO5L+`!`+>YADFsj!_puwBD3RoH zQ?Yw9=23qntogB_YHATbiX;*7_Hhi6G96XNn9nZfsH^c=++*>tu|btNmJV756(Sr# zk`R6i5CJI`4?f&L5w2)YjnQ|AD&#kS0qi1<^?ps0U{d7W`#!VGYAPKMnZU zKOSx=2za5bV6Xl9Lvw}Xn}FXz1FS)uDd2IqNDr>4`BDHTU<5nCgD0t><-|kEkSjeC zM(J%YkXoSYg22}os8BGB`~JB^{yRnCw-x*L?~z%w11l-%QqqycVZHVOq7l0>a2Pse#)jpJO z0T>B*^S@JX>9$IMd>R*sfw##B=if+T| zH^s;hfd{k>l_<$HRNiRD^E7VJ7&c5`?jKe;bl=n?7h^&7u z^e^ud@zk^OSUc-xOtWW9Z!XJR1@35Fw5iBiXdr@LhmeiZ}JfZn>2 z>O6yNs`Vi8*=K6N=WABCJg^qrcHo#_{4p2zb2}f_&PK2}=Q?r!@;DM0uMH-_I!l)A zejPLT3V`y`_E9Pnj>GG_B+6F{4A&P}4f;NQCvtcwJ@E&eWOeG8k%cP2_zlEfdG9*hff(KsPhu@_QZJ4+d{jNh5oHgv6Qvw2O2mq{PqrG@-e zP$97MrAmcFnDQ}B2#w2cby7TLLS`kAcquzY9C7-}{jnET^|91I9JM5o9MgZfgml#s zR?HAm(MsC85@|Ok93xx)0R_n4cTkfr;;YXqqG(U>wxEq3=W`60=R&rBxFd=56*bJ)+SIDQB+C@|@))xei9Y244>U1a~rfBqv+ zr-iv8i^fbVf75XKzM2W8t7w(lTn$c##-)(w-;YL6hSmKzaEh`sItS zs5HOwRO!AZlyr%_fabg;ji$vTYt>TZ2qlbT>atZ^|D^{OfMn&*SgK($OIVQupSz%p z_S)#8UpPL~REbeM2Kx+(ISQ2#d7@=9eO%b6)azEFXtgsN(ERJu}l&T2ive%F0US)NO z$n$bW2bm_eACXMJUNs6x-}CVy@Ay8>I8~r;GluA=zH#RAv}}anOnjjQ1yQ!OJzw3W zka~&j(eC9-g76O}OkujBFBLi1os*IYR!C6f90oMeGX2D@(?W7hUIceegl7idDxrt1Y3b)f3Sb@h@*gpXpZ7XfWC!-TgJ z+oPFex>cq<8_h>erJhI2jm|>k8s>Um!}E6UhKX(7^CiA3h#SZsUtN8A8qE|r+@Gu9 z^t#TOKoVTsYBM`(m4JpO&()pc;>ejD|Ba1J@pW-g zmhjB%tUFum+nZWkRV{wJaM>WA>mxDu)>q})xdO?h#{_}mJP@!s2AfGaea z8y7b-2I{LzXO;iP_wwHi6(1j8OZ>Y6==%^kn%MQb%l)Ctf-b6qk_NI5;@8o{x%vmz=dz?cIw5 z9lSwT&8*$6csBJC7v+)RVPS3G$nI9pX)(oDD%$S;DHLnks*=%)XCJpBQ+k@PUT~kp zwp=q^tYA*@liY>KER3U{7?1C`;^5-?{oKz@PNq;hS!?>V&s$Q0Wo^br8jUntrZr@LM+kXlU-B47+wuZ}6OvjQlQVi2G=7u+d>qpW~+epXK9L z9YsErG608C4Fw_)z}vN!T}+GU*G(OpEC_CvL<(fmq6kzG8+mR#RvlbDv-$b?-8;2E zUKQeIM548}I5o+IY18nYGx4~PBdY!$N)HPYAEJ`s42##!xqZ5BZ)YTp{_1l=<-R+f zOEEsQSx6?d{{~0MF6X!>786wxr(>(7B|L0*D$4qHvD#t?Ngw>wvc)Mfgl2jFD~^BL z&MFS9$MG#qS%`XB$v|_UH>eEjTtJ@~$ifu-j!8b_(iM+2zs$tMM2iJC={UMqPHnfA z9~P=DR`~)xV|JkB>!=AJt!pOneKE-hO+*Diq72yKf8308b##bZHbTe_@|e=95A!1; zBTJ8)kK2s$>qW9q{Af&shj#G*WlJ@U;f@=7tzj5EjA_Ua&R5!N=r$pD5B?mz<}@EB z#bpTcbaira(#^v>BYr!+1}z75&xtL;28$Ne1S%;jYxNe`rftQvH(k5w6^x*h|7gBH zprxtFW>94+r;x_U2{z0@)dPOxya7 zjr0*0?!CNH6$i;*+t~g=z5$AF?uJNH0UX?|mxz)U!klG4e>zq#9ZuCeJg}Ybj8So% zrYkQg%Aa4~RWm_=3olAEd{7@q8E8jFoVLfZC8&o!@+_%1pZy)UYHDh7TPnocD~F+2 z=s{IOE<(J(!YhB$c%&{MVnPtt@r_g{xA3hFsVd3 z<`qg{2*p%h05c}#KSCxJCJ%{b>Et7}yHL@Ba?pZs%q?PKol?xU~0d%oh03tq~H z@($s_mH+R9h2Yz6MmJCQ$HW(xmlVU>@l$;4{(t*%saub3U>6R4Q)&qosFJkRRvyy- zEzqNetP4%1?9MJO+Ah^QWs@vuogUGeR_UH4>KM5c+@3MPulS7hBMwqwDS$K70O>6# zF9|vXp>LKr$wt1Xa&~M)LyJL@jLI28ZT^pUZuoHb-FRS%n?4c`&IG5$KkWKXd>1`m z0hFTiu3Edf*$g33{{iV5DzP21x&%%?rGd zOd+kJ_W2KS`?t;08RD+pYJ_GTqj6c3*}GSGk0o_@>Hxj`1~i5^XQAwCiP0kEeG%>&EXXSoKpc0;Dqb_&->JP zo@^+d{`z`<+#aAqhld*F0d+oE@4N;sV%81ffG5Vuwc#D@U03Almk>_`Z#5b)`l!%D zZ`#L)Rtr~F9`=o&n`nt5<@#7}>VN%mTlL;A_oKx~TLB8Ab10s%ye~UWv7TIj>yt?a znmkS(VsEXESXkz+lmB`8RFy8909I%FX5Esb-H7D6FVWuIX+44`qe9jb8AS7>`o9&X zJV9%35mf9)()bU9gM;t;Y=@u6b7e#vTQ6rNhlBG9z?RRpURJXpSZvD!Xn*z4~yoUIp=KQS&0FsRxQO-Q8f{RnB(eN&3R zqe^0OTG7x5XB)v8V{^F=EQXRW#qSSl?)}8qK4@vtrlLKB%jO;LPJDMNH)_2zK|*lk zg!j-|iy(GX#8N0c`}Y?GfXj_*!S}XsQPXoa{*6o8$?|cuGB#c-mZiZ}WZW$+A&r)$ z36u%NI`mx+L|%PunY>s4JkY+@ZmWlSOBI|d16Kf3>Mn6r$1yjq+WYHKAIJm7Uh>2v zUom)`FT|Wiz7L}!$7Lm;vnwkrYtfCPQzPifr$#9O{|aruxehHYc`Yq^0<=t9N5`*J z!ftPu8(hpfhdA2}Q2eS587QEYcz1P;drf2=yl(@b9~f=`Uy6?XmayL&>l7F9q@C+5^PY$_{I_S;5W_BF zW>{F*>oP1!hS^!G%~;q8!6fIch$7O7P;dRs7;e6C3;6vmJ`AXrT;t}-4r)g;q2=M# za}1py5@pEHht!&Hv1Ypl|5KYS*2Xi3igE@V|n~%SMhPY%VT-<0P zRPWeyj=%o(&#XWR&oqZ?UzL(Fqyd_70ve9lI6heHi0@xP4NyT~8d3Gpg@}e$QQhl6 zd;t?&PI)k9D7ZrGxw8sg>2E-BynyotA6BACnnaD!BCUhBMR9^V#Nz=0*e29N2mxpv zYQUV?Uxmj}ZG`pt7ugDe7kKTCM*gz0d|3p$GSKGSW3g<9&UUH}30l|9$L@o14<+)_ zpU)^4{7(uwV?ER~G=pfA05;SbZWQR)g7Az3|1@5Ism0^_lL!9%0k&1Odn5t0l75d& zCc(wEpoK^_#-flzaeC)HF0Y|CPP;>Y?7zExt*7Q)q7PWb1u79bs1TU83*=;F8{<$2 zAU9|ij%V7mBrl?m&gcLMcJ<~Vj#kQ(*SJxz*RHC$*oAQm&r~LoDpJ>I^K3C zdo~PQ&CG_c5*~#bSr<`w4=h>k8lK?NhJAfwQ1xO*&4vy!K6j3YiQikItoNCgv{TeR z;|=GV?u!F%L^b{Y z%Kra-5+dmYAh>GUWUHcYx)=qK?rsW&@pIWjJl-aZ3ImQbZmSJs)VLG#5}wR}`DUf` z8qJ&oxg3C&>r`ZiY=U4SU_=XWNv-j7qWU3sytpV2=pL^h#ROh(eSHat1Ht3<*veU# zRzDpp_My&Ty8q&E8a)S5a!T(_smrL#cfS;JE(kRZDKEojCFBQJmO&BZ2lrDW6pjp^ zLOHUMm?*q=3%IIl>ek<9h^7YXmrk(04ao)Thvv1LfRFULXuu%wzzwGYe(*erdufj! zBaCCL3&HV$f6=m?R&OKm%MS?p3O;PQ0)$6YJXz)Hjajau3k}R+t!P}`{V6&w;SEXrq;U&U0}eyoG>7UeY>YREOUi`8}is@Ut;x z$A3+ecR){~a#s)BaPIQ1l3eimesO`CWX3N`4bioLZJi43yx#4`jm#kq z1tEc&?_xVzM@8MXV#Xy{Ku=tz6_|xz( z9`H?`BpouqYOoP;cBjC7jL?PNd1l-c)dsk(BMUo{mp__9^<7*T=wSpHQ!0pCqWWiwVy1&3H|O+#ZRs$ zvE(DW?&dp8r`7nTy~6b6AnMO@Y8c^pF9=~TX;7r4aXvRtqfqJTfOxsgCM~a|L~e>N zvd|_;lV$7R@KEV+wN=DY^l;GXF;&3{bq^LxP2r?teanv5(LvNHFe%k&xWq%z70I=;)YPvH39!xNx2LH8`0=&i=kATX zw{(BPUw`lEG#Rh8nJO$_Sy_<-aR~@UHJz3lxFfJV*oS9Z(c@lMjPmwQgbx$GV1b^n z!PBdEeIH*>o{znr>;}!V-&0*5X&rZW=8jG8>gf+aQ@`qMH)vW#-uiU6k8U}dp{J{= z>RjE@(lTvXGeRWC%@JX$P9P_T^O@W48O*%F7AUYh1A;0|C#T~jqY977jtY)|gV zpe`!F{MftS1<9Imlt}a zw3!bgC#@;4v;jf0MjFD__SG(FbsAEQOl+O-j8#a^Z`-0bNN5(*>U-1VB*#n?ekS#- z({Y#f!Qr^vfhmd7x~J;=9y@h4H8s0VqHslVm6Nnt2}re0f9u!xI?Hr|>oJe>`w{3f zc_g=OG-OKGb_Ks(rVX%4 zSgjG`_5Py+jRWsvKBXhvPSL_XuFq})5H=q=O`Bxt9(s{S6KR}SyKtKM^W;AP5D(8F@vv3fsG9f zvIo|e}LTtR5%972GP{xy9KA%4kMkcP%zJ3^T$eUD_G=c(hxyQ<{EON{j&_>9n z>BiK|3&+7HRNI(J{zJtUUlMsGVLR}6{6nMs=eikhKi#g6c>QHn`|nOXwvRwvstBF6 zVY$U^HxT=7QG23eRIFPPx93yU+71Yg({?FnaDkFauJF0lcgTsI)jd5u7}WUgKJ2*< z;@8~`+E4anz>Ca-CyKAo-fShh8?)vY$uS0Enb4XEP8ZyqUHv5sQFA7wY+uwdvX`Mm z&TV^^zI-@XCmu$i4!UCOX4o)vK3ubRuj-9tcpg!xCJ(E~*R1wsd#?U6`xc~xq567( z+My-qz`($bdQ^i?uBGKUO{b7@X(E=5c89)?HiRm`J}9XRB6%(3Wl^A3{qMfk=?hI1 znbCfC9-JCwAC4(bhkRz-e@bgFVqT;^ibkX=csE`As^cg3Pxyl&Ft^~yyA}^ zBS!v6`aZQW+6MVtm8GG=srw=fpbp1mss{H_oCD~fUdEQ?EE7V01}IhK+SA_9VPuL< zP!mvpJB9o%iWOa37toHmD5U~uw7{9ZS9!*M?mEbRq_%YTn3#OP!NIQ%C!52XrI(5) zBQI@mrI1^lDZA{77=bc^e#ef-q2;Ec>LRU|+yNEXVl+2-@SgBMrQ4bGo1D;*%7gLa z^(a<2^^uaJlLloBy68kP&Xe_mRJaFBbgad6Y8GpC==5L^8+68-rh1G783rVyap(M|J|4xWaa2=2gp8uOPFP5cGGYI#D_ zwwOE0s;a&|@XJ+9{p^~fN>85!8J4V_4;w`5+5k+J<0-`jn>#QARHQgiDn!ki3z)S8 zL{ik?!oVC4xH{-9VnIJQB{|O0T{1O#@@Nhrsgp*<9sFVI) z+e+(WY|Aqfd3q4%N)(gYMRq(Fd#lF*S3B2`c<2#N?w2LVN@ zNE4)q2+~myLFrP4?hEM5IP1N&-kP`G@4v~)&AoS@y}z^fxA)oip0#q-_^d7)3qK10 z0BrhtS|-%9-rm8)K>anJE7hf*n*GcyDJE!dkei1qp5TH5QGDHSAe;{Y4*))cL}PXK z2GGH(*q%1 zZD;LxXyT>2>gb67a1C8JJ~`(RgdsZxmwCh;cFXSQPSGNoS6vG#0W&qibC}lD4;v|tl8l6#b;)N1i?L%vIPBfJr<-79X_^3>{Mb(2*=pVid8?TC=jXGtGX9qyvV;i4v- zLJ#9va*H{$%te~CQr0GIUEoN*M8J z%Njxr-86BI1U)|woT=YgGmM`z28k6`Rbf%`K~VvSI0_o%Lv$gLQ9jDT`?x6T^`00a z4BA(rI4cWV8XAK%T|IChgfv1L3fA@^c*zK>uz-|2uy~Y-md;NI>YcK%BZcCIf6hb6IezhP|w7sYxKOOoXEy!lng$gmj zkzGAKFgR^59El?GD+Ctvr@fn}hs%CASPTT`f+JE@$<$e4f16TQ-_ZC^i#-Y)2t>Di zD=OK4)1(maf06Y!-}XlK!}-+_s`;O|f7AXW_I+ilmZ2d^%N66f=bpZnvhd#gD6A`n zfJNW zK*g~~!jMpV1qHA@PDTNYK*}S*Xc>Dn7(uniA`uFBECT-vgpmhOn+P(@7wr9dHmglEePM z9^oi;V|`^|8ENQW5@Q!M1y41gt^ooG>*`JZYsid1#FPn9 zv;1?|kh-9-XbM^jO~Fw?p)zn36oHa~nZaaHvQU&PQW7eIg8riKiY4HE|2OTua>D;q3^+7i-X4wzBcO0OFhUlC1uGzAFkl!IfsjXHW#KS;`M;x+UGWrev5)A{x z;81Fe2s9jw#LD5pczZk=kHz89@^U|F;7{`Y&*8zrPz3mAMZorI;b(YCkiCZZM>3Tl z|1I4=6n^QTR9b$>sGXVG=plc0`k#DJef>{T9W+`3%loBv8!EpY3*5 zl#|SJO*AFQ8X70t#T!G^vl3rE5^z&#~8JmXtKKB(1(P_isqP^FV)ny1U&(uNI!)R+;5cKnY%|$29?@AL5NtK2+Gz;-0ALOD!Vi~Sy81nA_6S6zyH{ z!OfxWV`p&39fla$qoJ*o>@)8tWmw7ccaxUam<`_yve{ifKeh>y=Z`aVnrE_k%NL(; zUDks4nruw7uZEmwGW%THPlOgvp_-`O8)S@bpU zA*>?8s0Ldy8JlWlKK3jiK~*Wwv@dm=cjlr3x9;W3bZhg2G>;muB{_NPXM93qbYpoEkK4(<#wDqM>fk z;KF$JvaNt=Ci(|YPHYWS$0Ahfa9bDRHLc4w?|dH!yvUSN{^6?7*xcwAmZ;zD(-x?QP5ZADsV3G4R3tEBy!4ll9yHm!tZVVpfZ<*7y^1L3j5qz_5xZh?%f?N z#$6`h8CnRrT$Y~uEX)49F4jQC>#gWH>CUnjDp1JI)q(S8hrC)pJ^7wkn04Q8IpEw5 zIc_QBYCrzW74AjzpqjPhxu--M(~Mja#A9d_+-~^7zhjxh{6q;+|7PmO3oHBYwWC{( zajGd?$O?;AdB01|p{J(eQ@+1AeIk4K)^R!*kQlxNmjEe?xpt-6bylOz(4TuX;d2X5 z88AIgDFJz;%BiJp-H7zwg+L9buNOYcd+8K*`;Pm*o+w7#pKsk<9d?$s-QDv4tdn4Y z#~gpT{j%ZV_iXW?@71M|Hm2jPm2t57!E;03rtC&nr(0CSri)ywRSQRXs^v3aruD1Q z=1!2;o@1+TYUFE>Gf7vsp#pv^zy*_fqi&BSrd#Yl(B?>y=8UaW&{ArTGF&QYov0b} zoumB5&Xe>mrp=CtpeKGi4@z!ECEd+td#rEFFjXm7G5?x%REey0XyN1guF2G@>xY68 zlkR8!el%tw?+)rg<~ww0K6`iuIk0Ly;@ys(A*HUs{Hf{Pstlf!%Q4)QMAvvh+p_V> zw#O^C*RgR4czqwvlT3HTbCmiWIBt%n1D2Oxg|+Dny7V0fdi8zZgzDbAZjI6)E8;p* zro)$AOq>I6IxmfnjSfCstSzlEz2>Qsyxgd4n~qKB(DD|XPjL{eEp>8pM;pEs`nL6I(5&IEju^4I)I$@Y)MWnJke) zyr}I06S};i(r@=E&xvz}r)B~k-Mh4di6YZ+dNP&Ilw&6J{ycMHjryvN)fD-<-kg%QD1@yO>S~~{HMb?4TU>apUiz}V=1gjI z(GW+<11|H^J-kK={#Nw4LnfIw?-dRWbKW_0ZbP^^F=^T|NlostRk*5+mvu^?82yNX zoCvjpx0Q54vN^;dDiu#WhX?0Eb_xkAx|!LXhtHO$hBa}4DcN1`7iKdOTpep9K&3eT zi2?m^ix`^>j$sv{JQyExy)|xBMX2qTaFR@17~}YCK~Q-!H)N|_aXT*(x}ko_a9HcG z9X*KN>~KUFcK{?{vXnS*49q66NtT${V1BPeFI1%!^gG<>Yb187Jj|~?v=v!^lzU=! zxWylxoV=N_>3=L&GeLPL=l7NR;g#oFS5u~gOFA9TSdiBs^mN!(odqjHbx)igI$=g? z$;LbcWDoC-Xpm_?I^|<>-S&%ezGU@ca@Qz#-+a8|tYF+rLPlnUqNMl4+ZhC@ey%_z3@G*BB&ME`-H8QU_scMl3GnCAr2q8f3<4O0G`fJF@7!$_ZJ z+X0_v9n767jk`BCS{*x7LaTeEyBQ5UOh-4Hpbqy13Q_hjtKB>0;-Jzh4F3yTjH*{} zDoott_>vw|;w2!l5ExH{a#=ClX6IzNZWY?(6xQ)El=|GuYiRA@mYld;oTtHT7Na)m zX&ruLKIOK}z|$E22Mr>^pK51jYKry? zF=HS0YN>iyhcCoih_6;K($vi=3i8#~JX=jp>2z$ZT^KTLZ)w-l^|O$>$Y)jjxB~rT z09|4UivErIwqZ=`#@>lEF*UJn$LAy-9_JBH5f@TC8RAlYr-f8*KJ4##RWWiRJTsa6 zxqwydeDBi&N2Vr50TQP^*QJ}Hw@)6SR}Tg;U5X8XM{0O~ZC;w_eD3@0fa%O~YLXnP z>$Q6*=nJ9>)Aq{qdZ0=TOD?K2=(aW@&AlZz(($4W^>HnJSX+T#Q-S+RIUE6krK=+)z?hcR-R0Dl;u^oxuW%b?&cn(d=?g%cWYYM(oF zmm)n4N6Gf?lQMQ789B~GR{InZN6wjPLf+sRW(dVfQkQ#D3R#6+cm91;3GR2T!p>oM zJ9u{1WuAgMcj3ZmGjklELc3_kaLAk1vc#y-h0)mQB6*wXYjb7X*qb;z7f;{IX$LAF zu_YfR8jJIH#YkHFUFCj3TV76sNP`E3zA!K`&xfHj+;QI-!ZK%8!t@hqG4 z9YiF};<1E<%CVrChei4}7}nK|s>KF(yU?D4rp93oZ4 zSr=Fw0l0X09u^lHuldzrM=CveXcXw`ZUMWVfci;5nqkplMbi=pNKH%YkdTy|*aoI6 z3srYkdfb8Ibp<2f%q73ESJC$}qV8qVGXo~6XT{0~TvRL64NkeEzLQC1{=UCodNt>= zlMFhbc7aF)6P=tk^~GP8v^zOD(Tj|DFQjJ*G@e~nHwX<3Q>2+*{@l^CHaqZey0TMY zN=h)ndFFjlg1?d=L%LucCvZ5}n}exHJoxmRghaLvbU?u7%9p_sT-&GU=;;114wY;l zB|!nT<7#&fX*}i|eQU^0x0rEGe%1NlfkpX;0JgbfCUWWqUvDY>r2&=3GCE5VXFvdJ z6NWzT+{pwPt#ZCPZlH?I!~|#ut}&(`sVfJb(HOh4h}HSMao1uAJ`T{aEx7STxVAGr z)B)H46uYA_oF-Nlkt?Vs$xg1eRBF|G!W-%@6wDg?x}P|G#=G@xf$TYv;aZwv_Bt_O zjsKG;;L}+Al(Fu-PT1Ddb9478f;a3lKOuqN0Jo{h$)%-A&<$wH1a%xvN zZB93>lIEXt$d<8BcQW$)J+9j{Ae84XZ2R`1y>*D516z3sX}Oh)ty#w{{|3 zzl&pHPm2%ZnxhcVV{}vW+i_sG`Iu`XFQ!KLvl=}u4Q_XPBUxcB0KP5uO?uJl7@FZot$zNd=@X^`wihy3T6y#^lCpNV;4yDs(#ix^RbcN@Pii4EaQg(s;zyku(rKbGTNeubyTWdhZ2W`aJ0U h>~z;@q05oq8Ogz0a;nlV_x_py=xd+VD%7|X`d>Z>+?oIY literal 0 HcmV?d00001 diff --git a/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-96x96.png b/ClientApp/staff-db-ui/src/assets/icons/production/dhr-icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..9706b81268d91e862b5676d89b54c15e9f22dd23 GIT binary patch literal 9791 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 0.5% +last 2 versions +Firefox ESR +not dead +not IE 9-11 \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/environments/develop/environment.js b/ClientApp/staff-db-ui/src/environments/develop/environment.js new file mode 100644 index 0000000..627e463 --- /dev/null +++ b/ClientApp/staff-db-ui/src/environments/develop/environment.js @@ -0,0 +1,7 @@ +const environment = { + production: false, + useLoginWithJWT: true, + apiUrl: 'https://staffdb.hensel-recycling.com:50101/api', + sentry_dsn: '', + translationFolder: './assets/translate/' +}; diff --git a/ClientApp/staff-db-ui/src/environments/production/environment.js b/ClientApp/staff-db-ui/src/environments/production/environment.js new file mode 100644 index 0000000..0a7dc32 --- /dev/null +++ b/ClientApp/staff-db-ui/src/environments/production/environment.js @@ -0,0 +1,7 @@ +const environment = { + production: true, + useLoginWithJWT: true, + apiUrl: 'https://staffdb.hensel-recycling.com:50101/api', + sentry_dsn: '', + translationFolder: './assets/translate/', +}; diff --git a/ClientApp/staff-db-ui/src/index.html b/ClientApp/staff-db-ui/src/index.html new file mode 100644 index 0000000..dbdaa17 --- /dev/null +++ b/ClientApp/staff-db-ui/src/index.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + info + + + + diff --git a/ClientApp/staff-db-ui/src/json-typings.d.ts b/ClientApp/staff-db-ui/src/json-typings.d.ts new file mode 100644 index 0000000..68275f7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/json-typings.d.ts @@ -0,0 +1,4 @@ +declare module "*.json" { + const value: any; + // export default value; +} \ No newline at end of file diff --git a/ClientApp/staff-db-ui/src/karma.conf.js b/ClientApp/staff-db-ui/src/karma.conf.js new file mode 100644 index 0000000..f8d563c --- /dev/null +++ b/ClientApp/staff-db-ui/src/karma.conf.js @@ -0,0 +1,32 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../coverage/staffdb'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true + }); +}; diff --git a/ClientApp/staff-db-ui/src/main.ts b/ClientApp/staff-db-ui/src/main.ts new file mode 100644 index 0000000..323b654 --- /dev/null +++ b/ClientApp/staff-db-ui/src/main.ts @@ -0,0 +1,69 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { AppModule } from './app/app.module'; +import * as Sentry from '@sentry/angular'; +import { APP_TITLE } from '@app_consts'; +import { IENVIRONMENT } from '@app_core/injection-tokens'; + +declare const environment: IENVIRONMENT; +declare const appVersion: string; +declare const appBuild: string; + +if (environment.sentry_dsn) { + Sentry.init({ + dsn: environment.sentry_dsn, + attachStacktrace: true, + debug: false, + release: APP_TITLE + '_' + appVersion, + integrations: [Sentry.browserTracingIntegration()], + tracePropagationTargets: ['localhost', environment.apiUrl], + // new RewriteFrames(), + // new SentryBrowser.BrowserTracing({ + // tracingOrigins: ['localhost', environment.apiUrl], + // routingInstrumentation: SentryBrowser.routingInstrumentation, + // }), + // ], + + // Set tracesSampleRate to 1.0 to capture 100% + // of transactions for performance monitoring. + // We recommend adjusting this value in production + tracesSampleRate: 0.5, + maxBreadcrumbs: 50, + // ignoreErrors: ['Non-Error exception captured'], + beforeSend(event: any, hint) { + // Note: issue with double entries during http exceptions: https://github.com/getsentry/sentry-javascript/issues/2169 + // Note: issue with a second entry not being set correctly (as a non-error): https://github.com/getsentry/sentry-javascript/issues/2292#issuecomment-554932519 + const isNonErrorException = event.exception?.values[0]?.value?.startsWith('Non-Error exception captured'); + if (isNonErrorException) { + if (!event.extra.__serialized__) { + return null; + } + let realErrMsg = (event.extra.__serialized__ as any).error ? (event.extra.__serialized__ as any).error.message : null; + realErrMsg = realErrMsg || (event.extra.__serialized__ as any).message; + // this is a useless error message that masks the actual error. Lets try to set it properly + event.exception.values[0].value = realErrMsg; + event.message = realErrMsg; + } + return event; + } + }); + Sentry.setTag('AppName', APP_TITLE); + Sentry.setTag('AppVersion', appVersion); + Sentry.setTag('AppBuild', appBuild); +} +// MinimumBreadcrumbLevel=Error +// MinimumEventLevel=Error + + +if (environment.production) { + enableProdMode(); +} + + +platformBrowserDynamic().bootstrapModule(AppModule).then(ref => { + // Ensure Angular destroys itself on hot reloads. + if (window['ngRef']) window['ngRef'].destroy(); + window['ngRef'] = ref; + + // Otherwise, log the boot error +}).catch(err => console.error(err)); diff --git a/ClientApp/staff-db-ui/src/manifest/develop/webmanifest.json b/ClientApp/staff-db-ui/src/manifest/develop/webmanifest.json new file mode 100644 index 0000000..3362f7a --- /dev/null +++ b/ClientApp/staff-db-ui/src/manifest/develop/webmanifest.json @@ -0,0 +1,77 @@ +{ + "name": "StaffDB-Dev", + "short_name": "StaffDB-Dev", + "theme_color": "#1976d2", + "background_color": "#fafafa", + "display": "standalone", + "scope": "./", + "start_url": "./", + "icons": [ + { + "src": "assets/icons/develop/dhr-icon-16x16.png", + "sizes": "16x16", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-24x24.png", + "sizes": "24x24", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-48x48.png", + "sizes": "48x48", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/develop/dhr-icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ] +} diff --git a/ClientApp/staff-db-ui/src/manifest/production/webmanifest.json b/ClientApp/staff-db-ui/src/manifest/production/webmanifest.json new file mode 100644 index 0000000..020ee98 --- /dev/null +++ b/ClientApp/staff-db-ui/src/manifest/production/webmanifest.json @@ -0,0 +1,77 @@ +{ + "name": "StaffDB", + "short_name": "StaffDB", + "theme_color": "#1976d2", + "background_color": "#fafafa", + "display": "standalone", + "scope": "./", + "start_url": "./", + "icons": [ + { + "src": "assets/icons/production/dhr-icon-16x16.png", + "sizes": "16x16", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-24x24.png", + "sizes": "24x24", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-48x48.png", + "sizes": "48x48", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ] +} diff --git a/ClientApp/staff-db-ui/src/polyfills.ts b/ClientApp/staff-db-ui/src/polyfills.ts new file mode 100644 index 0000000..aa571da --- /dev/null +++ b/ClientApp/staff-db-ui/src/polyfills.ts @@ -0,0 +1,69 @@ +/*************************************************************************************************** + * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates. + */ +import '@angular/localize/init'; +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags.ts'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +// import 'zone.js/dist/zone'; // Included with Angular CLI. +import 'zone.js'; +import 'zone.js/testing'; + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/ClientApp/staff-db-ui/src/styles.scss b/ClientApp/staff-db-ui/src/styles.scss new file mode 100644 index 0000000..9ad987c --- /dev/null +++ b/ClientApp/staff-db-ui/src/styles.scss @@ -0,0 +1,19 @@ +/* You can add global styles to this file, and also import other style files */ + +/*===================================== +import global directory +======================================*/ + +@import 'hr-core.scss'; + + +/* for sidenav to take whole page */ + +html, +body { + margin: 0; + height: 100%; + overflow: hidden !important; + // touch-action: pan-x pan-y; + // touch-action: manipulation; +} diff --git a/ClientApp/staff-db-ui/src/test.ts b/ClientApp/staff-db-ui/src/test.ts new file mode 100644 index 0000000..06aa8e4 --- /dev/null +++ b/ClientApp/staff-db-ui/src/test.ts @@ -0,0 +1,14 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); diff --git a/ClientApp/staff-db-ui/src/theme.scss b/ClientApp/staff-db-ui/src/theme.scss new file mode 100644 index 0000000..e69de29 diff --git a/ClientApp/staff-db-ui/src/tsconfig.app.json b/ClientApp/staff-db-ui/src/tsconfig.app.json new file mode 100644 index 0000000..6ba02cf --- /dev/null +++ b/ClientApp/staff-db-ui/src/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "types": ["node"] + }, + "files": [ + "main.ts", + "polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/ClientApp/staff-db-ui/src/tsconfig.spec.json b/ClientApp/staff-db-ui/src/tsconfig.spec.json new file mode 100644 index 0000000..de77336 --- /dev/null +++ b/ClientApp/staff-db-ui/src/tsconfig.spec.json @@ -0,0 +1,18 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts", + "polyfills.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/ClientApp/staff-db-ui/src/tslint.json b/ClientApp/staff-db-ui/src/tslint.json new file mode 100644 index 0000000..aa7c3ee --- /dev/null +++ b/ClientApp/staff-db-ui/src/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ] + } +} diff --git a/ClientApp/staff-db-ui/src/webmanifest.json b/ClientApp/staff-db-ui/src/webmanifest.json new file mode 100644 index 0000000..905f3c7 --- /dev/null +++ b/ClientApp/staff-db-ui/src/webmanifest.json @@ -0,0 +1,77 @@ +{ + "name": "StaffDB-Dev", + "short_name": "StaffDB-Dev", + "theme_color": "#1976d2", + "background_color": "#fafafa", + "display": "standalone", + "scope": "./", + "start_url": "./", + "icons": [ + { + "src": "assets/icons/production/dhr-icon-16x16.png", + "sizes": "16x16", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-24x24.png", + "sizes": "24x24", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-48x48.png", + "sizes": "48x48", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-72x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-96x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-128x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-144x144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-152x152.png", + "sizes": "152x152", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-384x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable any" + }, + { + "src": "assets/icons/production/dhr-icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable any" + } + ] +} diff --git a/ClientApp/staff-db-ui/tsconfig.json b/ClientApp/staff-db-ui/tsconfig.json new file mode 100644 index 0000000..48bb628 --- /dev/null +++ b/ClientApp/staff-db-ui/tsconfig.json @@ -0,0 +1,57 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": false, + "noImplicitOverride": false, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": false, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "module": "es2020", + "moduleResolution": "node", + "downlevelIteration": true, + "emitDecoratorMetadata": false, + "experimentalDecorators": true, + "resolveJsonModule": true, + "importHelpers": true, + "target": "ES2022", + "lib": [ + "es2020", + "dom" + ], + "paths": { + "@app_modules/*": [ + "src/app/modules/*" + ], + "@app_components/*": [ + "src/app/shared/components/*" + ], + "@app_consts": [ + "src/app/shared/app.consts.ts" + ], + "@app_core/*": [ + "src/app/shared/core/*" + ], + "@app_services/*": [ + "src/app/shared/services/*" + ], + "@app_models/*": [ + "src/app/shared/models/*" + ], + "jszip": [ + "node_modules/jszip/dist/jszip.min.js" + ] + }, + "useDefineForClassFields": false + } + // , "angularCompilerOptions": { + // "enableI18nLegacyMessageIdFormat": false, + // "strictInjectionParameters": true, + // "strictInputAccessModifiers": true, + // "strictTemplates": true + // } +} diff --git a/ClientApp/staff-db-ui/tslint.json b/ClientApp/staff-db-ui/tslint.json new file mode 100644 index 0000000..4f6dfca --- /dev/null +++ b/ClientApp/staff-db-ui/tslint.json @@ -0,0 +1,131 @@ +{ + "rulesDirectory": [ + "codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true + ], + "curly": [ + true, + "ignore-same-line" + ], + "deprecation": { + "severity": "off" + }, + "eofline": false, + "forin": true, + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 280 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + false, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": false, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "no-output-on-prefix": true, + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "directive-class-suffix": true + } +}