@sumaris-net/ngx-components 2.6.4-alpha4 → 2.6.4-alpha5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +24 -0
- package/.eslintrc.json +74 -0
- package/.gitattribute +1 -0
- package/.github/CONTRIBUTING.md +10 -0
- package/.github/ISSUE_TEMPLATE.md +6 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- package/.github/github_disclaimer.md +14 -0
- package/.gitlab-ci.yml +46 -0
- package/.graphqlconfig +15 -0
- package/angular.json +230 -0
- package/capacitor.config.json +9 -0
- package/ionic.config.json +7 -0
- package/karma.conf.js +32 -0
- package/ng-package.json +19 -0
- package/ngcc.config.js +14 -0
- package/package.json +137 -23
- package/public_api.ts +343 -0
- package/resources/android/build/tools/android-accept-licenses.sh +14 -0
- package/resources/android/icon/drawable-hdpi-icon.png +0 -0
- package/resources/android/icon/drawable-ldpi-icon.png +0 -0
- package/resources/android/icon/drawable-mdpi-icon.png +0 -0
- package/resources/android/icon/drawable-xhdpi-icon.png +0 -0
- package/resources/android/icon/drawable-xxhdpi-icon.png +0 -0
- package/resources/android/icon/drawable-xxxhdpi-icon.png +0 -0
- package/resources/android/splash/drawable-land-hdpi-screen.png +0 -0
- package/resources/android/splash/drawable-land-ldpi-screen.png +0 -0
- package/resources/android/splash/drawable-land-mdpi-screen.png +0 -0
- package/resources/android/splash/drawable-land-xhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-land-xxhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-land-xxxhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-hdpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-ldpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-mdpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-xhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-xxhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-port-xxxhdpi-screen.png +0 -0
- package/resources/android/splash/drawable-xxxhdpi-screen.png +0 -0
- package/resources/icon/TODO.md +11 -0
- package/resources/icon.png +0 -0
- package/resources/icon.png.md5 +1 -0
- package/resources/icon.xcf +0 -0
- package/resources/ios/icon/icon-1024.png +0 -0
- package/resources/ios/icon/icon-108@2x.png +0 -0
- package/resources/ios/icon/icon-20.png +0 -0
- package/resources/ios/icon/icon-20@2x.png +0 -0
- package/resources/ios/icon/icon-20@3x.png +0 -0
- package/resources/ios/icon/icon-24@2x.png +0 -0
- package/resources/ios/icon/icon-27.5@2x.png +0 -0
- package/resources/ios/icon/icon-29.png +0 -0
- package/resources/ios/icon/icon-29@2x.png +0 -0
- package/resources/ios/icon/icon-29@3x.png +0 -0
- package/resources/ios/icon/icon-40.png +0 -0
- package/resources/ios/icon/icon-40@2x.png +0 -0
- package/resources/ios/icon/icon-40@3x.png +0 -0
- package/resources/ios/icon/icon-44@2x.png +0 -0
- package/resources/ios/icon/icon-50.png +0 -0
- package/resources/ios/icon/icon-50@2x.png +0 -0
- package/resources/ios/icon/icon-60.png +0 -0
- package/resources/ios/icon/icon-60@2x.png +0 -0
- package/resources/ios/icon/icon-60@3x.png +0 -0
- package/resources/ios/icon/icon-72.png +0 -0
- package/resources/ios/icon/icon-72@2x.png +0 -0
- package/resources/ios/icon/icon-76.png +0 -0
- package/resources/ios/icon/icon-76@2x.png +0 -0
- package/resources/ios/icon/icon-83.5@2x.png +0 -0
- package/resources/ios/icon/icon-86@2x.png +0 -0
- package/resources/ios/icon/icon-98@2x.png +0 -0
- package/resources/ios/icon/icon-small.png +0 -0
- package/resources/ios/icon/icon-small@2x.png +0 -0
- package/resources/ios/icon/icon-small@3x.png +0 -0
- package/resources/ios/icon/icon.png +0 -0
- package/resources/ios/icon/icon@2x.png +0 -0
- package/resources/ios/splash/Default-1792h~iphone.png +0 -0
- package/resources/ios/splash/Default-2436h.png +0 -0
- package/resources/ios/splash/Default-2688h~iphone.png +0 -0
- package/resources/ios/splash/Default-568h@2x~iphone.png +0 -0
- package/resources/ios/splash/Default-667h.png +0 -0
- package/resources/ios/splash/Default-736h.png +0 -0
- package/resources/ios/splash/Default-Landscape-1792h~iphone.png +0 -0
- package/resources/ios/splash/Default-Landscape-2436h.png +0 -0
- package/resources/ios/splash/Default-Landscape-2688h~iphone.png +0 -0
- package/resources/ios/splash/Default-Landscape-736h.png +0 -0
- package/resources/ios/splash/Default-Landscape@2x~ipad.png +0 -0
- package/resources/ios/splash/Default-Landscape@~ipadpro.png +0 -0
- package/resources/ios/splash/Default-Landscape~ipad.png +0 -0
- package/resources/ios/splash/Default-Portrait@2x~ipad.png +0 -0
- package/resources/ios/splash/Default-Portrait@~ipadpro.png +0 -0
- package/resources/ios/splash/Default-Portrait~ipad.png +0 -0
- package/resources/ios/splash/Default@2x~iphone.png +0 -0
- package/resources/ios/splash/Default@2x~universal~anyany.png +0 -0
- package/resources/ios/splash/Default~iphone.png +0 -0
- package/resources/splash.png +0 -0
- package/resources/splash.png.md5 +1 -0
- package/scripts/build-android.sh +18 -0
- package/scripts/build-i18n.js +24 -0
- package/scripts/docker-start.sh +6 -0
- package/scripts/emulate-android.sh +17 -0
- package/scripts/env-android.sh +83 -0
- package/scripts/env-clean.sh +23 -0
- package/scripts/env-global.sh +156 -0
- package/scripts/install-android-sdk-tools.sh +73 -0
- package/scripts/ionic-update.sh +24 -0
- package/scripts/node/playground.ts +9 -0
- package/scripts/node/resources.js +90 -0
- package/scripts/release.sh +149 -0
- package/scripts/run-android.sh +59 -0
- package/scripts/test.sh +19 -0
- package/src/app/admin/admin-routing.module.ts +30 -0
- package/src/app/admin/admin.module.ts +23 -0
- package/src/app/admin/services/filter/person.filter.ts +77 -0
- package/src/app/admin/services/person.service.ts +212 -0
- package/src/app/admin/services/validator/person.validator.ts +37 -0
- package/src/app/admin/users/users.html +427 -0
- package/src/app/admin/users/users.module.ts +34 -0
- package/src/app/admin/users/users.scss +59 -0
- package/src/app/admin/users/users.ts +257 -0
- package/src/app/app-routing.module.ts +126 -0
- package/src/app/app.component.html +12 -0
- package/src/app/app.component.scss +4 -0
- package/src/app/app.component.ts +205 -0
- package/src/app/app.module.ts +326 -0
- package/src/app/core/about/about.modal.html +140 -0
- package/src/app/core/about/about.modal.scss +23 -0
- package/src/app/core/about/about.modal.ts +71 -0
- package/src/app/core/about/about.module.ts +24 -0
- package/src/app/core/account/account.module.ts +38 -0
- package/src/app/core/account/account.page.html +241 -0
- package/src/app/core/account/account.page.scss +21 -0
- package/src/app/core/account/account.page.ts +366 -0
- package/src/app/core/account/new-token.modal.html +120 -0
- package/src/app/core/account/new-token.modal.ts +138 -0
- package/src/app/core/account/token.table.html +177 -0
- package/src/app/core/account/token.table.scss +7 -0
- package/src/app/core/account/token.table.ts +141 -0
- package/src/app/core/auth/auth.form.html +77 -0
- package/src/app/core/auth/auth.form.scss +1 -0
- package/src/app/core/auth/auth.form.ts +145 -0
- package/src/app/core/auth/auth.modal.html +57 -0
- package/src/app/core/auth/auth.modal.scss +1 -0
- package/src/app/core/auth/auth.modal.ts +80 -0
- package/src/app/core/auth/auth.module.ts +33 -0
- package/src/app/core/core.module.ts +100 -0
- package/src/app/core/core.testing.module.ts +64 -0
- package/src/app/core/form/buttons/form-buttons-bar.component.html +59 -0
- package/src/app/core/form/buttons/form-buttons-bar.component.scss +14 -0
- package/src/app/core/form/buttons/form-buttons-bar.component.ts +70 -0
- package/src/app/core/form/buttons/form-buttons-bar.module.ts +24 -0
- package/src/app/core/form/entity/editor.class.ts +803 -0
- package/src/app/core/form/entity/entity-editor-modal.class.ts +537 -0
- package/src/app/core/form/entity/entity-editor.class.ts +885 -0
- package/src/app/core/form/entity/entity-metadata.component.html +53 -0
- package/src/app/core/form/entity/entity-metadata.component.scss +28 -0
- package/src/app/core/form/entity/entity-metadata.component.ts +19 -0
- package/src/app/core/form/entity/entity.module.ts +25 -0
- package/src/app/core/form/form.class.ts +401 -0
- package/src/app/core/form/form.module.ts +37 -0
- package/src/app/core/form/form.utils.ts +639 -0
- package/src/app/core/form/list/list.form.html +67 -0
- package/src/app/core/form/list/list.form.scss +40 -0
- package/src/app/core/form/list/list.form.ts +278 -0
- package/src/app/core/form/list/list.module.ts +25 -0
- package/src/app/core/form/properties/properties.form.html +129 -0
- package/src/app/core/form/properties/properties.form.ts +147 -0
- package/src/app/core/form/properties/properties.module.ts +30 -0
- package/src/app/core/form/properties/properties.table.html +219 -0
- package/src/app/core/form/properties/properties.table.scss +0 -0
- package/src/app/core/form/properties/properties.table.ts +291 -0
- package/src/app/core/form/properties/property.validator.ts +22 -0
- package/src/app/core/form/properties/testing/properties-form.test.html +21 -0
- package/src/app/core/form/properties/testing/properties-form.test.ts +102 -0
- package/src/app/core/form/properties/testing/properties-form.testing.module.ts +25 -0
- package/src/app/core/form/text-popover/testing/text-popover.testing.html +45 -0
- package/src/app/core/form/text-popover/testing/text-popover.testing.module.ts +32 -0
- package/src/app/core/form/text-popover/testing/text-popover.testing.ts +77 -0
- package/src/app/core/form/text-popover/text-form.component.html +44 -0
- package/src/app/core/form/text-popover/text-form.component.scss +8 -0
- package/src/app/core/form/text-popover/text-form.component.ts +65 -0
- package/src/app/core/form/text-popover/text-popover.component.html +86 -0
- package/src/app/core/form/text-popover/text-popover.component.scss +7 -0
- package/src/app/core/form/text-popover/text-popover.component.ts +165 -0
- package/src/app/core/form/text-popover/text-popover.module.ts +27 -0
- package/src/app/core/graphql/graphql.module.ts +17 -0
- package/src/app/core/graphql/graphql.service.ts +969 -0
- package/src/app/core/graphql/graphql.utils.ts +167 -0
- package/src/app/core/home/home.html +211 -0
- package/src/app/core/home/home.module.ts +32 -0
- package/src/app/core/home/home.scss +242 -0
- package/src/app/core/home/home.ts +298 -0
- package/src/app/core/icon/icon.component.html +15 -0
- package/src/app/core/icon/icon.component.ts +23 -0
- package/src/app/core/icon/icon.module.ts +22 -0
- package/src/app/core/install/install-upgrade-card.component.html +144 -0
- package/src/app/core/install/install-upgrade-card.component.scss +4 -0
- package/src/app/core/install/install-upgrade-card.component.ts +412 -0
- package/src/app/core/install/install-upgrade-card.module.ts +23 -0
- package/src/app/core/menu/menu.component.html +135 -0
- package/src/app/core/menu/menu.component.scss +225 -0
- package/src/app/core/menu/menu.component.ts +352 -0
- package/src/app/core/menu/menu.model.ts +64 -0
- package/src/app/core/menu/menu.module.ts +27 -0
- package/src/app/core/menu/menu.service.ts +62 -0
- package/src/app/core/offline/update-offline-mode-card.component.html +45 -0
- package/src/app/core/offline/update-offline-mode-card.component.scss +4 -0
- package/src/app/core/offline/update-offline-mode-card.component.ts +28 -0
- package/src/app/core/offline/update-offline-mode-card.module.ts +24 -0
- package/src/app/core/peer/select-peer.modal.html +123 -0
- package/src/app/core/peer/select-peer.modal.scss +20 -0
- package/src/app/core/peer/select-peer.modal.ts +197 -0
- package/src/app/core/peer/select-peer.module.ts +28 -0
- package/src/app/core/register/register-confirm.page.html +55 -0
- package/src/app/core/register/register-confirm.page.scss +121 -0
- package/src/app/core/register/register-confirm.page.ts +94 -0
- package/src/app/core/register/register.form.html +125 -0
- package/src/app/core/register/register.form.scss +10 -0
- package/src/app/core/register/register.form.ts +213 -0
- package/src/app/core/register/register.modal.html +70 -0
- package/src/app/core/register/register.modal.ts +52 -0
- package/src/app/core/register/register.module.ts +31 -0
- package/src/app/core/services/account.service.ts +1431 -0
- package/src/app/core/services/auth-guard.service.ts +70 -0
- package/src/app/core/services/base-entity-service.class.ts +598 -0
- package/src/app/core/services/base-graphql-service.class.ts +298 -0
- package/src/app/core/services/base58.ts +83 -0
- package/src/app/core/services/config/account.config.ts +35 -0
- package/src/app/core/services/config/core.config.ts +180 -0
- package/src/app/core/services/config.service.ts +414 -0
- package/src/app/core/services/crypto.service.ts +126 -0
- package/src/app/core/services/errors.ts +67 -0
- package/src/app/core/services/local-settings.service.spec.ts +32 -0
- package/src/app/core/services/local-settings.service.ts +548 -0
- package/src/app/core/services/model/account.model.ts +141 -0
- package/src/app/core/services/model/config.model.ts +122 -0
- package/src/app/core/services/model/department.model.ts +34 -0
- package/src/app/core/services/model/entity.decorators.ts +112 -0
- package/src/app/core/services/model/entity.model.ts +326 -0
- package/src/app/core/services/model/filter.model.ts +139 -0
- package/src/app/core/services/model/history.model.ts +25 -0
- package/src/app/core/services/model/model.enum.ts +11 -0
- package/src/app/core/services/model/peer.model.ts +86 -0
- package/src/app/core/services/model/person.model.ts +112 -0
- package/src/app/core/services/model/referential.model.ts +244 -0
- package/src/app/core/services/model/settings.model.ts +32 -0
- package/src/app/core/services/model/token.model.ts +54 -0
- package/src/app/core/services/network.service.spec.ts +49 -0
- package/src/app/core/services/network.service.ts +729 -0
- package/src/app/core/services/network.types.ts +26 -0
- package/src/app/core/services/network.utils.ts +57 -0
- package/src/app/core/services/pipes/account.pipes.ts +25 -0
- package/src/app/core/services/pipes/department-to-string.pipe.ts +15 -0
- package/src/app/core/services/pipes/person-to-string.pipe.ts +15 -0
- package/src/app/core/services/pipes/usage-mode.pipes.ts +26 -0
- package/src/app/core/services/platform.service.spec.ts +56 -0
- package/src/app/core/services/platform.service.ts +605 -0
- package/src/app/core/services/storage/entities-storage.service.ts +542 -0
- package/src/app/core/services/storage/entity-store.class.ts +598 -0
- package/src/app/core/services/testing/referential-filter.model.ts +28 -0
- package/src/app/core/services/testing/referential.validator.ts +57 -0
- package/src/app/core/services/validator/account.validator.ts +58 -0
- package/src/app/core/services/validator/base.validator.class.ts +54 -0
- package/src/app/core/services/validator/local-settings.validator.ts +72 -0
- package/src/app/core/services/validator/user-settings.validator.ts +25 -0
- package/src/app/core/services/validator/user-token.validator.ts +55 -0
- package/src/app/core/settings/settings.module.ts +24 -0
- package/src/app/core/settings/settings.page.html +264 -0
- package/src/app/core/settings/settings.page.ts +365 -0
- package/src/app/core/table/actions-column.component.html +91 -0
- package/src/app/core/table/actions-column.component.ts +70 -0
- package/src/app/core/table/async-table.class.ts +1934 -0
- package/src/app/core/table/entities-async-table-datasource.class.ts +482 -0
- package/src/app/core/table/entities-table-datasource.class.ts +496 -0
- package/src/app/core/table/memory-table.class.ts +65 -0
- package/src/app/core/table/table-select-columns.component.html +58 -0
- package/src/app/core/table/table-select-columns.component.ts +50 -0
- package/src/app/core/table/table.class.ts +1973 -0
- package/src/app/core/table/table.model.ts +35 -0
- package/src/app/core/table/table.module.ts +26 -0
- package/src/app/core/table/table.utils.ts +38 -0
- package/src/app/core/table/testing/multi-table.testing.ts +261 -0
- package/src/app/core/table/testing/table-validator.service.ts +25 -0
- package/src/app/core/table/testing/table.testing.html +396 -0
- package/src/app/core/table/testing/table.testing.module.ts +25 -0
- package/src/app/core/table/testing/table.testing.scss +23 -0
- package/src/app/core/table/testing/table.testing.ts +292 -0
- package/src/app/shared/alerts.ts +292 -0
- package/src/app/shared/audio/audio.testing.html +33 -0
- package/src/app/shared/audio/audio.testing.module.ts +32 -0
- package/src/app/shared/audio/audio.testing.ts +31 -0
- package/src/app/shared/audio/audio.ts +278 -0
- package/src/app/shared/base64.utils.ts +66 -0
- package/src/app/shared/capacitor/keyboard.ts +40 -0
- package/src/app/shared/capacitor/plugins.ts +12 -0
- package/src/app/shared/constants.ts +12 -0
- package/src/app/shared/dates.ts +163 -0
- package/src/app/shared/debug/debug-service.class.ts +8 -0
- package/src/app/shared/debug/debug.component.html +13 -0
- package/src/app/shared/debug/debug.component.scss +24 -0
- package/src/app/shared/debug/debug.component.spec.ts +25 -0
- package/src/app/shared/debug/debug.component.ts +27 -0
- package/src/app/shared/debug/debug.module.ts +28 -0
- package/src/app/shared/directives/autofocus.directive.ts +109 -0
- package/src/app/shared/directives/autotitle.directive.ts +24 -0
- package/src/app/shared/directives/directives.module.ts +29 -0
- package/src/app/shared/directives/drag-and-drop.directive.ts +47 -0
- package/src/app/shared/directives/ng-var.directive.ts +32 -0
- package/src/app/shared/directives/resizable/resizable.component.ts +47 -0
- package/src/app/shared/directives/resizable/resizable.directive.ts +43 -0
- package/src/app/shared/directives/resizable/resizable.module.ts +9 -0
- package/src/app/shared/directives/resizable/resizable.style.scss +44 -0
- package/src/app/shared/directives/resizable/resizable.template.html +6 -0
- package/src/app/shared/events.ts +96 -0
- package/src/app/shared/file/csv.utils.ts +94 -0
- package/src/app/shared/file/file.service.ts +132 -0
- package/src/app/shared/file/file.utils.ts +138 -0
- package/src/app/shared/file/images.utils.ts +198 -0
- package/src/app/shared/file/json.utils.ts +73 -0
- package/src/app/shared/file/uri.utils.ts +25 -0
- package/src/app/shared/focusable.ts +10 -0
- package/src/app/shared/form/field.component.html +261 -0
- package/src/app/shared/form/field.component.scss +7 -0
- package/src/app/shared/form/field.component.ts +318 -0
- package/src/app/shared/form/field.model.ts +64 -0
- package/src/app/shared/form/loading-spinner.ts +16 -0
- package/src/app/shared/forms.ts +458 -0
- package/src/app/shared/functions.ts +492 -0
- package/src/app/shared/geolocation/geolocation.utils.ts +101 -0
- package/src/app/shared/gesture/gesture-config.ts +45 -0
- package/src/app/shared/gesture/hammer.utils.ts +14 -0
- package/src/app/shared/graph/colors.utils.ts +74 -0
- package/src/app/shared/graph/graph-colors.ts +295 -0
- package/src/app/shared/guard/component-dirty.guard.ts +70 -0
- package/src/app/shared/help/help.modal.html +42 -0
- package/src/app/shared/help/help.modal.ts +61 -0
- package/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.html +11 -0
- package/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.scss +39 -0
- package/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.ts +16 -0
- package/src/app/shared/hotkeys/hotkeys.service.ts +89 -0
- package/src/app/shared/hotkeys/shared-hotkeys.module.ts +27 -0
- package/src/app/shared/http/http.utils.ts +89 -0
- package/src/app/shared/image/gallery/image-gallery.component.html +231 -0
- package/src/app/shared/image/gallery/image-gallery.component.scss +196 -0
- package/src/app/shared/image/gallery/image-gallery.component.ts +389 -0
- package/src/app/shared/image/gallery/image-gallery.module.ts +34 -0
- package/src/app/shared/image/gallery/testing/gallegry.model.testing.ts +27 -0
- package/src/app/shared/image/gallery/testing/gallery.service.testing.ts +102 -0
- package/src/app/shared/image/gallery/testing/gallery.testing.html +15 -0
- package/src/app/shared/image/gallery/testing/gallery.testing.module.ts +39 -0
- package/src/app/shared/image/gallery/testing/gallery.testing.ts +38 -0
- package/src/app/shared/image/image.model.ts +6 -0
- package/src/app/shared/image/image.module.ts +16 -0
- package/src/app/shared/image/image.service.ts +94 -0
- package/src/app/shared/image/image.testing.module.ts +23 -0
- package/src/app/shared/inputs.ts +282 -0
- package/src/app/shared/interceptors/progess.interceptor.ts +25 -0
- package/src/app/shared/logging/log-level.model.ts +53 -0
- package/src/app/shared/logging/logger.model.ts +120 -0
- package/src/app/shared/logging/logging-service.class.ts +134 -0
- package/src/app/shared/logging/logging-service.config.ts +29 -0
- package/src/app/shared/logging/logging-service.module.ts +22 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.config.ts +83 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.html +262 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.module.ts +45 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.scss +21 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.ts +1022 -0
- package/src/app/shared/material/autocomplete/material.autocomplete.utils.ts +20 -0
- package/src/app/shared/material/autocomplete/testing/autocomplete.test.html +876 -0
- package/src/app/shared/material/autocomplete/testing/autocomplete.test.spec.ts +38 -0
- package/src/app/shared/material/autocomplete/testing/autocomplete.test.ts +247 -0
- package/src/app/shared/material/badge/badge.directive.ts +164 -0
- package/src/app/shared/material/badge/badge.module.ts +22 -0
- package/src/app/shared/material/badge/badge.test.html +261 -0
- package/src/app/shared/material/badge/badge.test.ts +36 -0
- package/src/app/shared/material/boolean/boolean.module.ts +40 -0
- package/src/app/shared/material/boolean/material.boolean.html +155 -0
- package/src/app/shared/material/boolean/material.boolean.scss +34 -0
- package/src/app/shared/material/boolean/material.boolean.ts +239 -0
- package/src/app/shared/material/chips/chips.module.ts +44 -0
- package/src/app/shared/material/chips/material.chips.html +146 -0
- package/src/app/shared/material/chips/material.chips.scss +65 -0
- package/src/app/shared/material/chips/material.chips.ts +768 -0
- package/src/app/shared/material/chips/testing/chips.test.html +137 -0
- package/src/app/shared/material/chips/testing/chips.test.ts +175 -0
- package/src/app/shared/material/datetime/datetime.module.ts +52 -0
- package/src/app/shared/material/datetime/material.date.html +132 -0
- package/src/app/shared/material/datetime/material.date.scss +17 -0
- package/src/app/shared/material/datetime/material.date.ts +408 -0
- package/src/app/shared/material/datetime/material.dateshort.html +134 -0
- package/src/app/shared/material/datetime/material.dateshort.scss +23 -0
- package/src/app/shared/material/datetime/material.dateshort.ts +422 -0
- package/src/app/shared/material/datetime/material.datetime.html +224 -0
- package/src/app/shared/material/datetime/material.datetime.scss +90 -0
- package/src/app/shared/material/datetime/material.datetime.ts +575 -0
- package/src/app/shared/material/datetime/testing/mat-date-time.test.html +354 -0
- package/src/app/shared/material/datetime/testing/mat-date-time.test.ts +134 -0
- package/src/app/shared/material/datetime/testing/mat-date.test.html +418 -0
- package/src/app/shared/material/datetime/testing/mat-date.test.ts +135 -0
- package/src/app/shared/material/datetime/testing/mat-dateshort.test.html +370 -0
- package/src/app/shared/material/datetime/testing/mat-dateshort.test.ts +127 -0
- package/src/app/shared/material/duration/duration.module.ts +39 -0
- package/src/app/shared/material/duration/duration.utils.ts +41 -0
- package/src/app/shared/material/duration/material.duration.html +44 -0
- package/src/app/shared/material/duration/material.duration.scss +28 -0
- package/src/app/shared/material/duration/material.duration.ts +294 -0
- package/src/app/shared/material/latlong/latlong.utils.ts +300 -0
- package/src/app/shared/material/latlong/material.latlong.html +127 -0
- package/src/app/shared/material/latlong/material.latlong.module.ts +40 -0
- package/src/app/shared/material/latlong/material.latlong.scss +48 -0
- package/src/app/shared/material/latlong/material.latlong.ts +421 -0
- package/src/app/shared/material/latlong/testing/latlong.test.html +341 -0
- package/src/app/shared/material/latlong/testing/latlong.test.ts +121 -0
- package/src/app/shared/material/material.animations.ts +129 -0
- package/src/app/shared/material/material.module.ts +94 -0
- package/src/app/shared/material/material.testing.module.ts +135 -0
- package/src/app/shared/material/memory/memory.utils.ts +54 -0
- package/src/app/shared/material/numpad/numpad.animation.ts +1 -0
- package/src/app/shared/material/numpad/numpad.append-to-input.directive.ts +109 -0
- package/src/app/shared/material/numpad/numpad.component.ts +78 -0
- package/src/app/shared/material/numpad/numpad.container.html +32 -0
- package/src/app/shared/material/numpad/numpad.container.scss +50 -0
- package/src/app/shared/material/numpad/numpad.container.ts +176 -0
- package/src/app/shared/material/numpad/numpad.content.html +13 -0
- package/src/app/shared/material/numpad/numpad.content.ts +10 -0
- package/src/app/shared/material/numpad/numpad.directive.ts +173 -0
- package/src/app/shared/material/numpad/numpad.dom-service.ts +46 -0
- package/src/app/shared/material/numpad/numpad.model.ts +55 -0
- package/src/app/shared/material/numpad/numpad.module.ts +38 -0
- package/src/app/shared/material/numpad/testing/numpad.test.html +146 -0
- package/src/app/shared/material/numpad/testing/numpad.test.ts +55 -0
- package/src/app/shared/material/paginator/material.paginator-i18n.ts +49 -0
- package/src/app/shared/material/stepper/material.stepper-i18n.ts +18 -0
- package/src/app/shared/material/swipe/material.swipe.html +63 -0
- package/src/app/shared/material/swipe/material.swipe.scss +39 -0
- package/src/app/shared/material/swipe/material.swipe.ts +350 -0
- package/src/app/shared/material/swipe/swipe.module.ts +33 -0
- package/src/app/shared/material/swipe/testing/swipe.test.html +128 -0
- package/src/app/shared/material/swipe/testing/swipe.test.ts +81 -0
- package/src/app/shared/modules.ts +11 -0
- package/src/app/shared/observables.ts +132 -0
- package/src/app/shared/pipes/arrays.pipe.ts +111 -0
- package/src/app/shared/pipes/colors.pipe.ts +19 -0
- package/src/app/shared/pipes/date-diff-duration.pipe.ts +48 -0
- package/src/app/shared/pipes/date-format.pipe.ts +78 -0
- package/src/app/shared/pipes/date-from-now.pipe.ts +20 -0
- package/src/app/shared/pipes/duration.pipe.spec.ts +51 -0
- package/src/app/shared/pipes/duration.pipe.ts +34 -0
- package/src/app/shared/pipes/file-size.pipe.ts +58 -0
- package/src/app/shared/pipes/form.pipes.ts +204 -0
- package/src/app/shared/pipes/highlight.pipe.ts +37 -0
- package/src/app/shared/pipes/latlong-format.pipe.ts +30 -0
- package/src/app/shared/pipes/maps.pipe.ts +39 -0
- package/src/app/shared/pipes/math.pipes.ts +39 -0
- package/src/app/shared/pipes/ng-init.pipe.ts +14 -0
- package/src/app/shared/pipes/number-format.pipe.ts +21 -0
- package/src/app/shared/pipes/pipes.module.ts +134 -0
- package/src/app/shared/pipes/property.pipes.ts +87 -0
- package/src/app/shared/pipes/string.pipes.ts +85 -0
- package/src/app/shared/pipes/translate-context.pipe.ts +33 -0
- package/src/app/shared/pipes/types.pipes.ts +31 -0
- package/src/app/shared/platforms.ts +58 -0
- package/src/app/shared/services/entity-service.class.ts +127 -0
- package/src/app/shared/services/job.utils.ts +121 -0
- package/src/app/shared/services/memory-entity-service.class.ts +447 -0
- package/src/app/shared/services/progress-bar.service.ts +42 -0
- package/src/app/shared/services/startable-observable-service.class.ts +137 -0
- package/src/app/shared/services/startable-service.class.ts +131 -0
- package/src/app/shared/services/storage.utils.ts +47 -0
- package/src/app/shared/services/translate-context.service.ts +116 -0
- package/src/app/shared/services/validator-service.class.ts +14 -0
- package/src/app/shared/services.ts +91 -0
- package/src/app/shared/shared-routing.module.ts +66 -0
- package/src/app/shared/shared.module.spec.ts +13 -0
- package/src/app/shared/shared.module.ts +146 -0
- package/src/app/shared/shared.testing.module.ts +50 -0
- package/src/app/shared/storage/storage-explorer.component.html +175 -0
- package/src/app/shared/storage/storage-explorer.component.scss +39 -0
- package/src/app/shared/storage/storage-explorer.component.spec.ts +24 -0
- package/src/app/shared/storage/storage-explorer.component.ts +292 -0
- package/src/app/shared/storage/storage-explorer.module.ts +44 -0
- package/src/app/shared/storage/storage.service.ts +133 -0
- package/src/app/shared/storage/storage.utils.ts +25 -0
- package/src/app/shared/testing/observable.test.html +53 -0
- package/src/app/shared/testing/observable.test.scss +3 -0
- package/src/app/shared/testing/observable.test.ts +117 -0
- package/src/app/shared/testing/tests.page.html +30 -0
- package/src/app/shared/testing/tests.page.ts +34 -0
- package/src/app/shared/toast/toast.testing.html +42 -0
- package/src/app/shared/toast/toast.testing.module.ts +32 -0
- package/src/app/shared/toast/toast.testing.ts +58 -0
- package/src/app/shared/toast/toasts.ts +183 -0
- package/src/app/shared/toolbar/modal-toolbar.html +32 -0
- package/src/app/shared/toolbar/modal-toolbar.scss +0 -0
- package/src/app/shared/toolbar/modal-toolbar.ts +63 -0
- package/src/app/shared/toolbar/toolbar.html +71 -0
- package/src/app/shared/toolbar/toolbar.module.ts +35 -0
- package/src/app/shared/toolbar/toolbar.scss +0 -0
- package/src/app/shared/toolbar/toolbar.ts +254 -0
- package/src/app/shared/types.ts +31 -0
- package/src/app/shared/upload-file/testing/upload-file.testing.html +25 -0
- package/src/app/shared/upload-file/testing/upload-file.testing.module.ts +32 -0
- package/src/app/shared/upload-file/testing/upload-file.testing.ts +68 -0
- package/src/app/shared/upload-file/upload-file-popover.component.html +43 -0
- package/src/app/shared/upload-file/upload-file-popover.component.scss +6 -0
- package/src/app/shared/upload-file/upload-file-popover.component.ts +115 -0
- package/src/app/shared/upload-file/upload-file.component.html +46 -0
- package/src/app/shared/upload-file/upload-file.component.scss +130 -0
- package/src/app/shared/upload-file/upload-file.component.ts +218 -0
- package/src/app/shared/upload-file/upload-file.model.ts +41 -0
- package/src/app/shared/validator/form-error-adapter.class.ts +123 -0
- package/src/app/shared/validator/validators.ts +639 -0
- package/src/app/shared/version/versions.ts +91 -0
- package/src/app/social/job/job.module.ts +26 -0
- package/src/app/social/job/progression/job-progression.component.html +22 -0
- package/src/app/social/job/progression/job-progression.component.scss +15 -0
- package/src/app/social/job/progression/job-progression.component.ts +17 -0
- package/src/app/social/job/progression/job-progression.icon.html +28 -0
- package/src/app/social/job/progression/job-progression.icon.scss +5 -0
- package/src/app/social/job/progression/job-progression.icon.ts +238 -0
- package/src/app/social/job/progression/job-progression.list.html +21 -0
- package/src/app/social/job/progression/job-progression.list.scss +17 -0
- package/src/app/social/job/progression/job-progression.list.ts +49 -0
- package/src/app/social/job/progression/job-progression.model.ts +28 -0
- package/src/app/social/job/progression/job-progression.service.ts +86 -0
- package/src/app/social/job/testing/job-progression.testing.html +20 -0
- package/src/app/social/job/testing/job-progression.testing.service.ts +60 -0
- package/src/app/social/job/testing/job-progression.testing.ts +51 -0
- package/src/app/social/job/testing/job.testing.module.ts +22 -0
- package/src/app/social/message/message.form.html +60 -0
- package/src/app/social/message/message.form.scss +6 -0
- package/src/app/social/message/message.form.ts +79 -0
- package/src/app/social/message/message.modal.html +65 -0
- package/src/app/social/message/message.modal.ts +118 -0
- package/src/app/social/message/message.model.ts +81 -0
- package/src/app/social/message/message.module.ts +22 -0
- package/src/app/social/message/message.service.ts +88 -0
- package/src/app/social/social.errors.ts +11 -0
- package/src/app/social/social.module.ts +36 -0
- package/src/app/social/social.testing.module.ts +40 -0
- package/src/app/social/user-event/notification/user-event-notification.icon.html +16 -0
- package/src/app/social/user-event/notification/user-event-notification.icon.ts +108 -0
- package/src/app/social/user-event/notification/user-event-notification.list.html +135 -0
- package/src/app/social/user-event/notification/user-event-notification.list.scss +73 -0
- package/src/app/social/user-event/notification/user-event-notification.list.ts +287 -0
- package/src/app/social/user-event/testing/user-event.testing.html +27 -0
- package/src/app/social/user-event/testing/user-event.testing.model.ts +146 -0
- package/src/app/social/user-event/testing/user-event.testing.module.ts +22 -0
- package/src/app/social/user-event/testing/user-event.testing.service.ts +141 -0
- package/src/app/social/user-event/testing/user-event.testing.ts +253 -0
- package/src/app/social/user-event/user-event.model.ts +73 -0
- package/src/app/social/user-event/user-event.module.ts +25 -0
- package/src/app/social/user-event/user-event.service.ts +679 -0
- package/src/browserslist +9 -0
- package/src/environments/environment.class.ts +83 -0
- package/src/environments/environment.prod.ts +47 -0
- package/src/environments/environment.test.ts +90 -0
- package/src/environments/environment.ts +108 -0
- package/src/favicon.ico +0 -0
- package/src/global.scss +27 -0
- package/src/index.html +80 -0
- package/src/main.ts +17 -0
- package/src/polyfills.ts +68 -0
- package/src/schema.graphql +3112 -0
- package/src/service-worker.js +31 -0
- package/src/zone-flags.ts +31 -0
- package/tsconfig.app.json +15 -0
- package/tsconfig.json +47 -0
- package/tsconfig.spec.json +19 -0
- package/esm2020/public_api.mjs +0 -313
- package/esm2020/src/app/admin/admin-routing.module.mjs +0 -41
- package/esm2020/src/app/admin/admin.module.mjs +0 -34
- package/esm2020/src/app/admin/services/filter/person.filter.mjs +0 -59
- package/esm2020/src/app/admin/services/person.service.mjs +0 -161
- package/esm2020/src/app/admin/services/validator/person.validator.mjs +0 -34
- package/esm2020/src/app/admin/users/users.mjs +0 -234
- package/esm2020/src/app/admin/users/users.module.mjs +0 -54
- package/esm2020/src/app/core/about/about.modal.mjs +0 -71
- package/esm2020/src/app/core/about/about.module.mjs +0 -34
- package/esm2020/src/app/core/account/account.module.mjs +0 -61
- package/esm2020/src/app/core/account/account.page.mjs +0 -316
- package/esm2020/src/app/core/account/new-token.modal.mjs +0 -115
- package/esm2020/src/app/core/account/token.table.mjs +0 -137
- package/esm2020/src/app/core/auth/auth.form.mjs +0 -131
- package/esm2020/src/app/core/auth/auth.modal.mjs +0 -72
- package/esm2020/src/app/core/auth/auth.module.mjs +0 -47
- package/esm2020/src/app/core/core.module.mjs +0 -184
- package/esm2020/src/app/core/core.testing.module.mjs +0 -86
- package/esm2020/src/app/core/form/buttons/form-buttons-bar.component.mjs +0 -71
- package/esm2020/src/app/core/form/buttons/form-buttons-bar.module.mjs +0 -35
- package/esm2020/src/app/core/form/entity/editor.class.mjs +0 -679
- package/esm2020/src/app/core/form/entity/entity-editor-modal.class.mjs +0 -421
- package/esm2020/src/app/core/form/entity/entity-editor.class.mjs +0 -687
- package/esm2020/src/app/core/form/entity/entity-metadata.component.mjs +0 -25
- package/esm2020/src/app/core/form/entity/entity.module.mjs +0 -38
- package/esm2020/src/app/core/form/form.class.mjs +0 -340
- package/esm2020/src/app/core/form/form.module.mjs +0 -66
- package/esm2020/src/app/core/form/form.utils.mjs +0 -473
- package/esm2020/src/app/core/form/list/list.form.mjs +0 -222
- package/esm2020/src/app/core/form/list/list.module.mjs +0 -35
- package/esm2020/src/app/core/form/properties/properties.form.mjs +0 -132
- package/esm2020/src/app/core/form/properties/properties.module.mjs +0 -43
- package/esm2020/src/app/core/form/properties/properties.table.mjs +0 -264
- package/esm2020/src/app/core/form/properties/property.validator.mjs +0 -23
- package/esm2020/src/app/core/form/properties/testing/properties-form.test.mjs +0 -90
- package/esm2020/src/app/core/form/properties/testing/properties-form.testing.module.mjs +0 -39
- package/esm2020/src/app/core/form/text-popover/testing/text-popover.testing.mjs +0 -70
- package/esm2020/src/app/core/form/text-popover/testing/text-popover.testing.module.mjs +0 -45
- package/esm2020/src/app/core/form/text-popover/text-form.component.mjs +0 -89
- package/esm2020/src/app/core/form/text-popover/text-popover.component.mjs +0 -146
- package/esm2020/src/app/core/form/text-popover/text-popover.module.mjs +0 -40
- package/esm2020/src/app/core/graphql/graphql.module.mjs +0 -22
- package/esm2020/src/app/core/graphql/graphql.service.mjs +0 -762
- package/esm2020/src/app/core/graphql/graphql.utils.mjs +0 -117
- package/esm2020/src/app/core/home/home.mjs +0 -257
- package/esm2020/src/app/core/home/home.module.mjs +0 -48
- package/esm2020/src/app/core/icon/icon.component.mjs +0 -41
- package/esm2020/src/app/core/icon/icon.module.mjs +0 -29
- package/esm2020/src/app/core/install/install-upgrade-card.component.mjs +0 -343
- package/esm2020/src/app/core/install/install-upgrade-card.module.mjs +0 -35
- package/esm2020/src/app/core/menu/menu.component.mjs +0 -329
- package/esm2020/src/app/core/menu/menu.model.mjs +0 -35
- package/esm2020/src/app/core/menu/menu.module.mjs +0 -44
- package/esm2020/src/app/core/menu/menu.service.mjs +0 -55
- package/esm2020/src/app/core/offline/update-offline-mode-card.component.mjs +0 -27
- package/esm2020/src/app/core/offline/update-offline-mode-card.module.mjs +0 -35
- package/esm2020/src/app/core/peer/select-peer.modal.mjs +0 -182
- package/esm2020/src/app/core/peer/select-peer.module.mjs +0 -42
- package/esm2020/src/app/core/register/register-confirm.page.mjs +0 -81
- package/esm2020/src/app/core/register/register.form.mjs +0 -181
- package/esm2020/src/app/core/register/register.modal.mjs +0 -52
- package/esm2020/src/app/core/register/register.module.mjs +0 -44
- package/esm2020/src/app/core/services/account.service.mjs +0 -1212
- package/esm2020/src/app/core/services/auth-guard.service.mjs +0 -71
- package/esm2020/src/app/core/services/base-entity-service.class.mjs +0 -444
- package/esm2020/src/app/core/services/base-graphql-service.class.mjs +0 -219
- package/esm2020/src/app/core/services/base58.mjs +0 -78
- package/esm2020/src/app/core/services/config/core.config.mjs +0 -175
- package/esm2020/src/app/core/services/config.service.mjs +0 -354
- package/esm2020/src/app/core/services/crypto.service.mjs +0 -114
- package/esm2020/src/app/core/services/errors.mjs +0 -50
- package/esm2020/src/app/core/services/local-settings.service.mjs +0 -449
- package/esm2020/src/app/core/services/model/account.model.mjs +0 -122
- package/esm2020/src/app/core/services/model/config.model.mjs +0 -92
- package/esm2020/src/app/core/services/model/department.model.mjs +0 -30
- package/esm2020/src/app/core/services/model/entity.decorators.mjs +0 -97
- package/esm2020/src/app/core/services/model/entity.model.mjs +0 -240
- package/esm2020/src/app/core/services/model/filter.model.mjs +0 -94
- package/esm2020/src/app/core/services/model/history.model.mjs +0 -2
- package/esm2020/src/app/core/services/model/model.enum.mjs +0 -11
- package/esm2020/src/app/core/services/model/peer.model.mjs +0 -68
- package/esm2020/src/app/core/services/model/person.model.mjs +0 -83
- package/esm2020/src/app/core/services/model/referential.model.mjs +0 -164
- package/esm2020/src/app/core/services/model/settings.model.mjs +0 -3
- package/esm2020/src/app/core/services/model/token.model.mjs +0 -48
- package/esm2020/src/app/core/services/network.service.mjs +0 -589
- package/esm2020/src/app/core/services/network.types.mjs +0 -20
- package/esm2020/src/app/core/services/network.utils.mjs +0 -15
- package/esm2020/src/app/core/services/pipes/account.pipes.mjs +0 -38
- package/esm2020/src/app/core/services/pipes/department-to-string.pipe.mjs +0 -23
- package/esm2020/src/app/core/services/pipes/person-to-string.pipe.mjs +0 -23
- package/esm2020/src/app/core/services/pipes/usage-mode.pipes.mjs +0 -37
- package/esm2020/src/app/core/services/platform.service.mjs +0 -525
- package/esm2020/src/app/core/services/storage/entities-storage.service.mjs +0 -428
- package/esm2020/src/app/core/services/storage/entity-store.class.mjs +0 -449
- package/esm2020/src/app/core/services/testing/referential-filter.model.mjs +0 -23
- package/esm2020/src/app/core/services/testing/referential.validator.mjs +0 -45
- package/esm2020/src/app/core/services/validator/account.validator.mjs +0 -56
- package/esm2020/src/app/core/services/validator/base.validator.class.mjs +0 -47
- package/esm2020/src/app/core/services/validator/local-settings.validator.mjs +0 -66
- package/esm2020/src/app/core/services/validator/user-settings.validator.mjs +0 -27
- package/esm2020/src/app/core/services/validator/user-token.validator.mjs +0 -52
- package/esm2020/src/app/core/settings/settings.module.mjs +0 -34
- package/esm2020/src/app/core/settings/settings.page.mjs +0 -312
- package/esm2020/src/app/core/table/actions-column.component.mjs +0 -102
- package/esm2020/src/app/core/table/async-table.class.mjs +0 -1697
- package/esm2020/src/app/core/table/entities-async-table-datasource.class.mjs +0 -384
- package/esm2020/src/app/core/table/entities-table-datasource.class.mjs +0 -399
- package/esm2020/src/app/core/table/memory-table.class.mjs +0 -53
- package/esm2020/src/app/core/table/table-select-columns.component.mjs +0 -43
- package/esm2020/src/app/core/table/table.class.mjs +0 -1728
- package/esm2020/src/app/core/table/table.model.mjs +0 -12
- package/esm2020/src/app/core/table/table.module.mjs +0 -40
- package/esm2020/src/app/core/table/table.utils.mjs +0 -30
- package/esm2020/src/app/core/table/testing/table-validator.service.mjs +0 -27
- package/esm2020/src/app/core/table/testing/table.testing.mjs +0 -280
- package/esm2020/src/app/core/table/testing/table.testing.module.mjs +0 -38
- package/esm2020/src/app/shared/alerts.mjs +0 -239
- package/esm2020/src/app/shared/audio/audio.mjs +0 -248
- package/esm2020/src/app/shared/audio/audio.testing.mjs +0 -31
- package/esm2020/src/app/shared/audio/audio.testing.module.mjs +0 -45
- package/esm2020/src/app/shared/capacitor/keyboard.mjs +0 -40
- package/esm2020/src/app/shared/capacitor/plugins.mjs +0 -9
- package/esm2020/src/app/shared/constants.mjs +0 -10
- package/esm2020/src/app/shared/dates.mjs +0 -148
- package/esm2020/src/app/shared/debug/debug-service.class.mjs +0 -3
- package/esm2020/src/app/shared/debug/debug.component.mjs +0 -39
- package/esm2020/src/app/shared/debug/debug.module.mjs +0 -44
- package/esm2020/src/app/shared/directives/autofocus.directive.mjs +0 -92
- package/esm2020/src/app/shared/directives/autotitle.directive.mjs +0 -30
- package/esm2020/src/app/shared/directives/directives.module.mjs +0 -43
- package/esm2020/src/app/shared/directives/drag-and-drop.directive.mjs +0 -53
- package/esm2020/src/app/shared/directives/ng-var.directive.mjs +0 -31
- package/esm2020/src/app/shared/directives/resizable/resizable.component.mjs +0 -59
- package/esm2020/src/app/shared/directives/resizable/resizable.directive.mjs +0 -40
- package/esm2020/src/app/shared/directives/resizable/resizable.module.mjs +0 -17
- package/esm2020/src/app/shared/events.mjs +0 -64
- package/esm2020/src/app/shared/file/csv.utils.mjs +0 -74
- package/esm2020/src/app/shared/file/file.service.mjs +0 -117
- package/esm2020/src/app/shared/file/file.utils.mjs +0 -113
- package/esm2020/src/app/shared/file/images.utils.mjs +0 -161
- package/esm2020/src/app/shared/file/json.utils.mjs +0 -51
- package/esm2020/src/app/shared/file/uri.utils.mjs +0 -23
- package/esm2020/src/app/shared/focusable.mjs +0 -6
- package/esm2020/src/app/shared/form/field.component.mjs +0 -307
- package/esm2020/src/app/shared/form/field.model.mjs +0 -25
- package/esm2020/src/app/shared/form/loading-spinner.mjs +0 -36
- package/esm2020/src/app/shared/forms.mjs +0 -391
- package/esm2020/src/app/shared/functions.mjs +0 -477
- package/esm2020/src/app/shared/geolocation/geolocation.utils.mjs +0 -80
- package/esm2020/src/app/shared/gesture/gesture-config.mjs +0 -49
- package/esm2020/src/app/shared/gesture/hammer.utils.mjs +0 -2
- package/esm2020/src/app/shared/graph/colors.utils.mjs +0 -64
- package/esm2020/src/app/shared/graph/graph-colors.mjs +0 -212
- package/esm2020/src/app/shared/guard/component-dirty.guard.mjs +0 -57
- package/esm2020/src/app/shared/help/help.modal.mjs +0 -53
- package/esm2020/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.mjs +0 -23
- package/esm2020/src/app/shared/hotkeys/hotkeys.service.mjs +0 -84
- package/esm2020/src/app/shared/hotkeys/shared-hotkeys.module.mjs +0 -42
- package/esm2020/src/app/shared/http/http.utils.mjs +0 -52
- package/esm2020/src/app/shared/image/gallery/image-gallery.component.mjs +0 -365
- package/esm2020/src/app/shared/image/gallery/image-gallery.module.mjs +0 -59
- package/esm2020/src/app/shared/image/gallery/testing/gallegry.model.testing.mjs +0 -27
- package/esm2020/src/app/shared/image/gallery/testing/gallery.service.testing.mjs +0 -90
- package/esm2020/src/app/shared/image/gallery/testing/gallery.testing.mjs +0 -39
- package/esm2020/src/app/shared/image/gallery/testing/gallery.testing.module.mjs +0 -56
- package/esm2020/src/app/shared/image/image.model.mjs +0 -2
- package/esm2020/src/app/shared/image/image.module.mjs +0 -29
- package/esm2020/src/app/shared/image/image.service.mjs +0 -98
- package/esm2020/src/app/shared/inputs.mjs +0 -231
- package/esm2020/src/app/shared/interceptors/progess.interceptor.mjs +0 -27
- package/esm2020/src/app/shared/logging/log-level.model.mjs +0 -48
- package/esm2020/src/app/shared/logging/logger.model.mjs +0 -47
- package/esm2020/src/app/shared/logging/logging-service.class.mjs +0 -121
- package/esm2020/src/app/shared/logging/logging-service.config.mjs +0 -2
- package/esm2020/src/app/shared/logging/logging-service.module.mjs +0 -30
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.config.mjs +0 -47
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.mjs +0 -916
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.module.mjs +0 -78
- package/esm2020/src/app/shared/material/autocomplete/material.autocomplete.utils.mjs +0 -19
- package/esm2020/src/app/shared/material/autocomplete/testing/autocomplete.test.mjs +0 -209
- package/esm2020/src/app/shared/material/badge/badge.directive.mjs +0 -194
- package/esm2020/src/app/shared/material/badge/badge.module.mjs +0 -32
- package/esm2020/src/app/shared/material/badge/badge.test.mjs +0 -41
- package/esm2020/src/app/shared/material/boolean/boolean.module.mjs +0 -68
- package/esm2020/src/app/shared/material/boolean/material.boolean.mjs +0 -253
- package/esm2020/src/app/shared/material/chips/chips.module.mjs +0 -76
- package/esm2020/src/app/shared/material/chips/material.chips.mjs +0 -697
- package/esm2020/src/app/shared/material/chips/testing/chips.test.mjs +0 -143
- package/esm2020/src/app/shared/material/datetime/datetime.module.mjs +0 -91
- package/esm2020/src/app/shared/material/datetime/material.date.mjs +0 -376
- package/esm2020/src/app/shared/material/datetime/material.dateshort.mjs +0 -385
- package/esm2020/src/app/shared/material/datetime/material.datetime.mjs +0 -499
- package/esm2020/src/app/shared/material/datetime/testing/mat-date-time.test.mjs +0 -108
- package/esm2020/src/app/shared/material/datetime/testing/mat-date.test.mjs +0 -110
- package/esm2020/src/app/shared/material/datetime/testing/mat-dateshort.test.mjs +0 -103
- package/esm2020/src/app/shared/material/duration/duration.module.mjs +0 -67
- package/esm2020/src/app/shared/material/duration/duration.utils.mjs +0 -36
- package/esm2020/src/app/shared/material/duration/material.duration.mjs +0 -257
- package/esm2020/src/app/shared/material/latlong/latlong.utils.mjs +0 -266
- package/esm2020/src/app/shared/material/latlong/material.latlong.mjs +0 -381
- package/esm2020/src/app/shared/material/latlong/material.latlong.module.mjs +0 -67
- package/esm2020/src/app/shared/material/latlong/testing/latlong.test.mjs +0 -102
- package/esm2020/src/app/shared/material/material.animations.mjs +0 -104
- package/esm2020/src/app/shared/material/material.module.mjs +0 -224
- package/esm2020/src/app/shared/material/material.testing.module.mjs +0 -168
- package/esm2020/src/app/shared/material/numpad/numpad.append-to-input.directive.mjs +0 -98
- package/esm2020/src/app/shared/material/numpad/numpad.component.mjs +0 -80
- package/esm2020/src/app/shared/material/numpad/numpad.container.mjs +0 -190
- package/esm2020/src/app/shared/material/numpad/numpad.content.mjs +0 -17
- package/esm2020/src/app/shared/material/numpad/numpad.directive.mjs +0 -162
- package/esm2020/src/app/shared/material/numpad/numpad.dom-service.mjs +0 -37
- package/esm2020/src/app/shared/material/numpad/numpad.model.mjs +0 -15
- package/esm2020/src/app/shared/material/numpad/numpad.module.mjs +0 -60
- package/esm2020/src/app/shared/material/numpad/testing/numpad.test.mjs +0 -46
- package/esm2020/src/app/shared/material/paginator/material.paginator-i18n.mjs +0 -46
- package/esm2020/src/app/shared/material/stepper/material.stepper-i18n.mjs +0 -22
- package/esm2020/src/app/shared/material/swipe/material.swipe.mjs +0 -344
- package/esm2020/src/app/shared/material/swipe/swipe.module.mjs +0 -52
- package/esm2020/src/app/shared/material/swipe/testing/swipe.test.mjs +0 -64
- package/esm2020/src/app/shared/modules.mjs +0 -11
- package/esm2020/src/app/shared/observables.mjs +0 -103
- package/esm2020/src/app/shared/pipes/arrays.pipe.mjs +0 -141
- package/esm2020/src/app/shared/pipes/colors.pipe.mjs +0 -23
- package/esm2020/src/app/shared/pipes/date-diff-duration.pipe.mjs +0 -48
- package/esm2020/src/app/shared/pipes/date-format.pipe.mjs +0 -66
- package/esm2020/src/app/shared/pipes/date-from-now.pipe.mjs +0 -27
- package/esm2020/src/app/shared/pipes/duration.pipe.mjs +0 -34
- package/esm2020/src/app/shared/pipes/file-size.pipe.mjs +0 -62
- package/esm2020/src/app/shared/pipes/form.pipes.mjs +0 -187
- package/esm2020/src/app/shared/pipes/highlight.pipe.mjs +0 -48
- package/esm2020/src/app/shared/pipes/latlong-format.pipe.mjs +0 -46
- package/esm2020/src/app/shared/pipes/maps.pipe.mjs +0 -63
- package/esm2020/src/app/shared/pipes/math.pipes.mjs +0 -59
- package/esm2020/src/app/shared/pipes/ng-init.pipe.mjs +0 -21
- package/esm2020/src/app/shared/pipes/number-format.pipe.mjs +0 -30
- package/esm2020/src/app/shared/pipes/pipes.module.mjs +0 -239
- package/esm2020/src/app/shared/pipes/property.pipes.mjs +0 -93
- package/esm2020/src/app/shared/pipes/string.pipes.mjs +0 -121
- package/esm2020/src/app/shared/pipes/translate-context.pipe.mjs +0 -43
- package/esm2020/src/app/shared/pipes/types.pipes.mjs +0 -45
- package/esm2020/src/app/shared/platforms.mjs +0 -43
- package/esm2020/src/app/shared/services/entity-service.class.mjs +0 -7
- package/esm2020/src/app/shared/services/job.utils.mjs +0 -92
- package/esm2020/src/app/shared/services/memory-entity-service.class.mjs +0 -337
- package/esm2020/src/app/shared/services/progress-bar.service.mjs +0 -33
- package/esm2020/src/app/shared/services/startable-observable-service.class.mjs +0 -119
- package/esm2020/src/app/shared/services/startable-service.class.mjs +0 -110
- package/esm2020/src/app/shared/services/translate-context.service.mjs +0 -105
- package/esm2020/src/app/shared/services/validator-service.class.mjs +0 -2
- package/esm2020/src/app/shared/services.mjs +0 -62
- package/esm2020/src/app/shared/shared-routing.module.mjs +0 -70
- package/esm2020/src/app/shared/shared.module.mjs +0 -208
- package/esm2020/src/app/shared/shared.testing.module.mjs +0 -84
- package/esm2020/src/app/shared/storage/storage-explorer.component.mjs +0 -268
- package/esm2020/src/app/shared/storage/storage-explorer.module.mjs +0 -60
- package/esm2020/src/app/shared/storage/storage.service.mjs +0 -132
- package/esm2020/src/app/shared/storage/storage.utils.mjs +0 -13
- package/esm2020/src/app/shared/testing/observable.test.mjs +0 -95
- package/esm2020/src/app/shared/testing/tests.page.mjs +0 -33
- package/esm2020/src/app/shared/toast/toast.testing.mjs +0 -51
- package/esm2020/src/app/shared/toast/toast.testing.module.mjs +0 -45
- package/esm2020/src/app/shared/toast/toasts.mjs +0 -144
- package/esm2020/src/app/shared/toolbar/modal-toolbar.mjs +0 -58
- package/esm2020/src/app/shared/toolbar/toolbar.mjs +0 -251
- package/esm2020/src/app/shared/toolbar/toolbar.module.mjs +0 -53
- package/esm2020/src/app/shared/types.mjs +0 -2
- package/esm2020/src/app/shared/upload-file/testing/upload-file.testing.mjs +0 -57
- package/esm2020/src/app/shared/upload-file/testing/upload-file.testing.module.mjs +0 -45
- package/esm2020/src/app/shared/upload-file/upload-file-popover.component.mjs +0 -97
- package/esm2020/src/app/shared/upload-file/upload-file.component.mjs +0 -204
- package/esm2020/src/app/shared/upload-file/upload-file.model.mjs +0 -20
- package/esm2020/src/app/shared/validator/form-error-adapter.class.mjs +0 -104
- package/esm2020/src/app/shared/validator/validators.mjs +0 -573
- package/esm2020/src/app/shared/version/versions.mjs +0 -81
- package/esm2020/src/app/social/job/job.module.mjs +0 -42
- package/esm2020/src/app/social/job/progression/job-progression.component.mjs +0 -20
- package/esm2020/src/app/social/job/progression/job-progression.icon.mjs +0 -216
- package/esm2020/src/app/social/job/progression/job-progression.list.mjs +0 -43
- package/esm2020/src/app/social/job/progression/job-progression.model.mjs +0 -23
- package/esm2020/src/app/social/job/progression/job-progression.service.mjs +0 -71
- package/esm2020/src/app/social/job/testing/job-progression.testing.mjs +0 -52
- package/esm2020/src/app/social/job/testing/job-progression.testing.service.mjs +0 -55
- package/esm2020/src/app/social/job/testing/job.testing.module.mjs +0 -35
- package/esm2020/src/app/social/message/message.form.mjs +0 -81
- package/esm2020/src/app/social/message/message.modal.mjs +0 -93
- package/esm2020/src/app/social/message/message.model.mjs +0 -65
- package/esm2020/src/app/social/message/message.module.mjs +0 -35
- package/esm2020/src/app/social/message/message.service.mjs +0 -84
- package/esm2020/src/app/social/social.errors.mjs +0 -10
- package/esm2020/src/app/social/social.module.mjs +0 -47
- package/esm2020/src/app/social/social.testing.module.mjs +0 -51
- package/esm2020/src/app/social/user-event/notification/user-event-notification.icon.mjs +0 -114
- package/esm2020/src/app/social/user-event/notification/user-event-notification.list.mjs +0 -246
- package/esm2020/src/app/social/user-event/testing/user-event.testing.mjs +0 -227
- package/esm2020/src/app/social/user-event/testing/user-event.testing.model.mjs +0 -112
- package/esm2020/src/app/social/user-event/testing/user-event.testing.module.mjs +0 -35
- package/esm2020/src/app/social/user-event/testing/user-event.testing.service.mjs +0 -111
- package/esm2020/src/app/social/user-event/user-event.model.mjs +0 -2
- package/esm2020/src/app/social/user-event/user-event.module.mjs +0 -39
- package/esm2020/src/app/social/user-event/user-event.service.mjs +0 -487
- package/esm2020/src/environments/environment.class.mjs +0 -5
- package/esm2020/src/environments/environment.mjs +0 -94
- package/esm2020/sumaris-net.ngx-components.mjs +0 -5
- package/fesm2015/sumaris-net.ngx-components.mjs +0 -38843
- package/fesm2015/sumaris-net.ngx-components.mjs.map +0 -1
- package/fesm2020/sumaris-net.ngx-components.mjs +0 -37942
- package/fesm2020/sumaris-net.ngx-components.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/public_api.d.ts +0 -286
- package/src/app/admin/admin-routing.module.d.ts +0 -9
- package/src/app/admin/admin.module.d.ts +0 -10
- package/src/app/admin/services/filter/person.filter.d.ts +0 -21
- package/src/app/admin/services/person.service.d.ts +0 -44
- package/src/app/admin/services/validator/person.validator.d.ts +0 -14
- package/src/app/admin/users/users.d.ts +0 -44
- package/src/app/admin/users/users.module.d.ts +0 -13
- package/src/app/core/about/about.modal.d.ts +0 -32
- package/src/app/core/about/about.module.d.ts +0 -10
- package/src/app/core/account/account.module.d.ts +0 -15
- package/src/app/core/account/account.page.d.ts +0 -68
- package/src/app/core/account/new-token.modal.d.ts +0 -41
- package/src/app/core/account/token.table.d.ts +0 -25
- package/src/app/core/auth/auth.form.d.ts +0 -36
- package/src/app/core/auth/auth.modal.d.ts +0 -24
- package/src/app/core/auth/auth.module.d.ts +0 -11
- package/src/app/core/core.module.d.ts +0 -31
- package/src/app/core/core.testing.module.d.ts +0 -14
- package/src/app/core/form/buttons/form-buttons-bar.component.d.ts +0 -26
- package/src/app/core/form/buttons/form-buttons-bar.module.d.ts +0 -9
- package/src/app/core/form/entity/editor.class.d.ts +0 -243
- package/src/app/core/form/entity/entity-editor-modal.class.d.ts +0 -128
- package/src/app/core/form/entity/entity-editor.class.d.ts +0 -205
- package/src/app/core/form/entity/entity-metadata.component.d.ts +0 -13
- package/src/app/core/form/entity/entity.module.d.ts +0 -10
- package/src/app/core/form/form.class.d.ts +0 -155
- package/src/app/core/form/form.module.d.ts +0 -13
- package/src/app/core/form/form.utils.d.ts +0 -336
- package/src/app/core/form/list/list.form.d.ts +0 -81
- package/src/app/core/form/list/list.module.d.ts +0 -9
- package/src/app/core/form/properties/properties.form.d.ts +0 -44
- package/src/app/core/form/properties/properties.module.d.ts +0 -11
- package/src/app/core/form/properties/properties.table.d.ts +0 -78
- package/src/app/core/form/properties/property.validator.d.ts +0 -13
- package/src/app/core/form/properties/testing/properties-form.test.d.ts +0 -19
- package/src/app/core/form/properties/testing/properties-form.testing.module.d.ts +0 -12
- package/src/app/core/form/text-popover/testing/text-popover.testing.d.ts +0 -14
- package/src/app/core/form/text-popover/testing/text-popover.testing.module.d.ts +0 -11
- package/src/app/core/form/text-popover/text-form.component.d.ts +0 -32
- package/src/app/core/form/text-popover/text-popover.component.d.ts +0 -70
- package/src/app/core/form/text-popover/text-popover.module.d.ts +0 -10
- package/src/app/core/graphql/graphql.module.d.ts +0 -8
- package/src/app/core/graphql/graphql.service.d.ts +0 -148
- package/src/app/core/graphql/graphql.utils.d.ts +0 -42
- package/src/app/core/home/home.d.ts +0 -74
- package/src/app/core/home/home.module.d.ts +0 -12
- package/src/app/core/icon/icon.component.d.ts +0 -13
- package/src/app/core/icon/icon.module.d.ts +0 -9
- package/src/app/core/install/install-upgrade-card.component.d.ts +0 -63
- package/src/app/core/install/install-upgrade-card.module.d.ts +0 -9
- package/src/app/core/menu/menu.component.d.ts +0 -62
- package/src/app/core/menu/menu.model.d.ts +0 -28
- package/src/app/core/menu/menu.module.d.ts +0 -10
- package/src/app/core/menu/menu.service.d.ts +0 -21
- package/src/app/core/offline/update-offline-mode-card.component.d.ts +0 -11
- package/src/app/core/offline/update-offline-mode-card.module.d.ts +0 -9
- package/src/app/core/peer/select-peer.modal.d.ts +0 -53
- package/src/app/core/peer/select-peer.module.d.ts +0 -11
- package/src/app/core/register/register-confirm.page.d.ts +0 -24
- package/src/app/core/register/register.form.d.ts +0 -48
- package/src/app/core/register/register.modal.d.ts +0 -14
- package/src/app/core/register/register.module.d.ts +0 -12
- package/src/app/core/services/account.service.d.ts +0 -191
- package/src/app/core/services/auth-guard.service.d.ts +0 -17
- package/src/app/core/services/base-entity-service.class.d.ts +0 -104
- package/src/app/core/services/base-graphql-service.class.d.ts +0 -77
- package/src/app/core/services/base58.d.ts +0 -7
- package/src/app/core/services/config/core.config.d.ts +0 -29
- package/src/app/core/services/config.service.d.ts +0 -60
- package/src/app/core/services/crypto.service.d.ts +0 -44
- package/src/app/core/services/errors.d.ts +0 -51
- package/src/app/core/services/local-settings.service.d.ts +0 -90
- package/src/app/core/services/model/account.model.d.ts +0 -35
- package/src/app/core/services/model/config.model.d.ts +0 -36
- package/src/app/core/services/model/department.model.d.ts +0 -11
- package/src/app/core/services/model/entity.decorators.d.ts +0 -17
- package/src/app/core/services/model/entity.model.d.ts +0 -89
- package/src/app/core/services/model/filter.model.d.ts +0 -45
- package/src/app/core/services/model/history.model.d.ts +0 -20
- package/src/app/core/services/model/model.enum.d.ts +0 -7
- package/src/app/core/services/model/peer.model.d.ts +0 -29
- package/src/app/core/services/model/person.model.d.ts +0 -31
- package/src/app/core/services/model/referential.model.d.ts +0 -77
- package/src/app/core/services/model/settings.model.d.ts +0 -26
- package/src/app/core/services/model/token.model.d.ts +0 -21
- package/src/app/core/services/network.service.d.ts +0 -149
- package/src/app/core/services/network.types.d.ts +0 -5
- package/src/app/core/services/network.utils.d.ts +0 -31
- package/src/app/core/services/pipes/account.pipes.d.ts +0 -15
- package/src/app/core/services/pipes/department-to-string.pipe.d.ts +0 -9
- package/src/app/core/services/pipes/person-to-string.pipe.d.ts +0 -9
- package/src/app/core/services/pipes/usage-mode.pipes.d.ts +0 -15
- package/src/app/core/services/platform.service.d.ts +0 -96
- package/src/app/core/services/storage/entities-storage.service.d.ts +0 -108
- package/src/app/core/services/storage/entity-store.class.d.ts +0 -113
- package/src/app/core/services/testing/referential-filter.model.d.ts +0 -9
- package/src/app/core/services/testing/referential.validator.d.ts +0 -22
- package/src/app/core/services/validator/account.validator.d.ts +0 -17
- package/src/app/core/services/validator/base.validator.class.d.ts +0 -21
- package/src/app/core/services/validator/local-settings.validator.d.ts +0 -18
- package/src/app/core/services/validator/user-settings.validator.d.ts +0 -10
- package/src/app/core/services/validator/user-token.validator.d.ts +0 -13
- package/src/app/core/settings/settings.module.d.ts +0 -10
- package/src/app/core/settings/settings.page.d.ts +0 -68
- package/src/app/core/table/actions-column.component.d.ts +0 -48
- package/src/app/core/table/async-table.class.d.ts +0 -383
- package/src/app/core/table/entities-async-table-datasource.class.d.ts +0 -80
- package/src/app/core/table/entities-table-datasource.class.d.ts +0 -94
- package/src/app/core/table/memory-table.class.d.ts +0 -25
- package/src/app/core/table/table-select-columns.component.d.ts +0 -22
- package/src/app/core/table/table.class.d.ts +0 -386
- package/src/app/core/table/table.model.d.ts +0 -26
- package/src/app/core/table/table.module.d.ts +0 -10
- package/src/app/core/table/table.utils.d.ts +0 -11
- package/src/app/core/table/testing/table-validator.service.d.ts +0 -17
- package/src/app/core/table/testing/table.testing.d.ts +0 -53
- package/src/app/core/table/testing/table.testing.module.d.ts +0 -11
- package/src/app/shared/alerts.d.ts +0 -53
- package/src/app/shared/audio/audio.d.ts +0 -44
- package/src/app/shared/audio/audio.testing.d.ts +0 -13
- package/src/app/shared/audio/audio.testing.module.d.ts +0 -11
- package/src/app/shared/capacitor/keyboard.d.ts +0 -16
- package/src/app/shared/capacitor/plugins.d.ts +0 -7
- package/src/app/shared/constants.d.ts +0 -7
- package/src/app/shared/dates.d.ts +0 -39
- package/src/app/shared/debug/debug-service.class.d.ts +0 -5
- package/src/app/shared/debug/debug.component.d.ts +0 -13
- package/src/app/shared/debug/debug.module.d.ts +0 -12
- package/src/app/shared/directives/autofocus.directive.d.ts +0 -19
- package/src/app/shared/directives/autotitle.directive.d.ts +0 -10
- package/src/app/shared/directives/directives.module.d.ts +0 -12
- package/src/app/shared/directives/drag-and-drop.directive.d.ts +0 -17
- package/src/app/shared/directives/ng-var.directive.d.ts +0 -12
- package/src/app/shared/directives/resizable/resizable.component.d.ts +0 -21
- package/src/app/shared/directives/resizable/resizable.directive.d.ts +0 -12
- package/src/app/shared/directives/resizable/resizable.module.d.ts +0 -8
- package/src/app/shared/events.d.ts +0 -27
- package/src/app/shared/file/csv.utils.d.ts +0 -19
- package/src/app/shared/file/file.service.d.ts +0 -23
- package/src/app/shared/file/file.utils.d.ts +0 -20
- package/src/app/shared/file/images.utils.d.ts +0 -19
- package/src/app/shared/file/json.utils.d.ts +0 -16
- package/src/app/shared/file/uri.utils.d.ts +0 -7
- package/src/app/shared/focusable.d.ts +0 -4
- package/src/app/shared/form/field.component.d.ts +0 -71
- package/src/app/shared/form/field.model.d.ts +0 -37
- package/src/app/shared/form/loading-spinner.d.ts +0 -8
- package/src/app/shared/forms.d.ts +0 -89
- package/src/app/shared/functions.d.ts +0 -132
- package/src/app/shared/geolocation/geolocation.utils.d.ts +0 -19
- package/src/app/shared/gesture/gesture-config.d.ts +0 -15
- package/src/app/shared/gesture/hammer.utils.d.ts +0 -16
- package/src/app/shared/graph/colors.utils.d.ts +0 -17
- package/src/app/shared/graph/graph-colors.d.ts +0 -63
- package/src/app/shared/guard/component-dirty.guard.d.ts +0 -19
- package/src/app/shared/help/help.modal.d.ts +0 -33
- package/src/app/shared/hotkeys/dialog/hotkeys-dialog.component.d.ts +0 -10
- package/src/app/shared/hotkeys/hotkeys.service.d.ts +0 -28
- package/src/app/shared/hotkeys/shared-hotkeys.module.d.ts +0 -11
- package/src/app/shared/http/http.utils.d.ts +0 -27
- package/src/app/shared/image/gallery/image-gallery.component.d.ts +0 -98
- package/src/app/shared/image/gallery/image-gallery.module.d.ts +0 -14
- package/src/app/shared/image/gallery/testing/gallegry.model.testing.d.ts +0 -12
- package/src/app/shared/image/gallery/testing/gallery.service.testing.d.ts +0 -33
- package/src/app/shared/image/gallery/testing/gallery.testing.d.ts +0 -16
- package/src/app/shared/image/gallery/testing/gallery.testing.module.d.ts +0 -12
- package/src/app/shared/image/image.model.d.ts +0 -5
- package/src/app/shared/image/image.module.d.ts +0 -8
- package/src/app/shared/image/image.service.d.ts +0 -32
- package/src/app/shared/inputs.d.ts +0 -32
- package/src/app/shared/interceptors/progess.interceptor.d.ts +0 -8
- package/src/app/shared/logging/log-level.model.d.ts +0 -38
- package/src/app/shared/logging/logger.model.d.ts +0 -68
- package/src/app/shared/logging/logging-service.class.d.ts +0 -39
- package/src/app/shared/logging/logging-service.config.d.ts +0 -25
- package/src/app/shared/logging/logging-service.module.d.ts +0 -9
- package/src/app/shared/material/autocomplete/material.autocomplete.config.d.ts +0 -36
- package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +0 -138
- package/src/app/shared/material/autocomplete/material.autocomplete.module.d.ts +0 -21
- package/src/app/shared/material/autocomplete/material.autocomplete.utils.d.ts +0 -4
- package/src/app/shared/material/autocomplete/testing/autocomplete.test.d.ts +0 -45
- package/src/app/shared/material/badge/badge.directive.d.ts +0 -37
- package/src/app/shared/material/badge/badge.module.d.ts +0 -10
- package/src/app/shared/material/badge/badge.test.d.ts +0 -21
- package/src/app/shared/material/boolean/boolean.module.d.ts +0 -19
- package/src/app/shared/material/boolean/material.boolean.d.ts +0 -66
- package/src/app/shared/material/chips/chips.module.d.ts +0 -21
- package/src/app/shared/material/chips/material.chips.d.ts +0 -126
- package/src/app/shared/material/chips/testing/chips.test.d.ts +0 -31
- package/src/app/shared/material/datetime/datetime.module.d.ts +0 -24
- package/src/app/shared/material/datetime/material.date.d.ts +0 -74
- package/src/app/shared/material/datetime/material.dateshort.d.ts +0 -75
- package/src/app/shared/material/datetime/material.datetime.d.ts +0 -100
- package/src/app/shared/material/datetime/testing/mat-date-time.test.d.ts +0 -31
- package/src/app/shared/material/datetime/testing/mat-date.test.d.ts +0 -30
- package/src/app/shared/material/datetime/testing/mat-dateshort.test.d.ts +0 -29
- package/src/app/shared/material/duration/duration.module.d.ts +0 -18
- package/src/app/shared/material/duration/duration.utils.d.ts +0 -3
- package/src/app/shared/material/duration/material.duration.d.ts +0 -57
- package/src/app/shared/material/latlong/latlong.utils.d.ts +0 -13
- package/src/app/shared/material/latlong/material.latlong.d.ts +0 -65
- package/src/app/shared/material/latlong/material.latlong.module.d.ts +0 -19
- package/src/app/shared/material/latlong/testing/latlong.test.d.ts +0 -21
- package/src/app/shared/material/material.animations.d.ts +0 -4
- package/src/app/shared/material/material.module.d.ts +0 -45
- package/src/app/shared/material/material.testing.module.d.ts +0 -25
- package/src/app/shared/material/numpad/numpad.append-to-input.directive.d.ts +0 -22
- package/src/app/shared/material/numpad/numpad.component.d.ts +0 -26
- package/src/app/shared/material/numpad/numpad.container.d.ts +0 -40
- package/src/app/shared/material/numpad/numpad.content.d.ts +0 -7
- package/src/app/shared/material/numpad/numpad.directive.d.ts +0 -35
- package/src/app/shared/material/numpad/numpad.dom-service.d.ts +0 -16
- package/src/app/shared/material/numpad/numpad.model.d.ts +0 -30
- package/src/app/shared/material/numpad/numpad.module.d.ts +0 -16
- package/src/app/shared/material/numpad/testing/numpad.test.d.ts +0 -13
- package/src/app/shared/material/paginator/material.paginator-i18n.d.ts +0 -15
- package/src/app/shared/material/stepper/material.stepper-i18n.d.ts +0 -10
- package/src/app/shared/material/swipe/material.swipe.d.ts +0 -89
- package/src/app/shared/material/swipe/swipe.module.d.ts +0 -15
- package/src/app/shared/material/swipe/testing/swipe.test.d.ts +0 -22
- package/src/app/shared/modules.d.ts +0 -8
- package/src/app/shared/observables.d.ts +0 -29
- package/src/app/shared/pipes/arrays.pipe.d.ts +0 -54
- package/src/app/shared/pipes/colors.pipe.d.ts +0 -9
- package/src/app/shared/pipes/date-diff-duration.pipe.d.ts +0 -23
- package/src/app/shared/pipes/date-format.pipe.d.ts +0 -34
- package/src/app/shared/pipes/date-from-now.pipe.d.ts +0 -12
- package/src/app/shared/pipes/duration.pipe.d.ts +0 -13
- package/src/app/shared/pipes/file-size.pipe.d.ts +0 -30
- package/src/app/shared/pipes/form.pipes.d.ts +0 -59
- package/src/app/shared/pipes/highlight.pipe.d.ts +0 -11
- package/src/app/shared/pipes/latlong-format.pipe.d.ts +0 -20
- package/src/app/shared/pipes/maps.pipe.d.ts +0 -22
- package/src/app/shared/pipes/math.pipes.d.ts +0 -20
- package/src/app/shared/pipes/ng-init.pipe.d.ts +0 -8
- package/src/app/shared/pipes/number-format.pipe.d.ts +0 -10
- package/src/app/shared/pipes/pipes.module.d.ts +0 -27
- package/src/app/shared/pipes/property.pipes.d.ts +0 -26
- package/src/app/shared/pipes/string.pipes.d.ts +0 -47
- package/src/app/shared/pipes/translate-context.pipe.d.ts +0 -17
- package/src/app/shared/pipes/types.pipes.d.ts +0 -18
- package/src/app/shared/platforms.d.ts +0 -8
- package/src/app/shared/services/entity-service.class.d.ts +0 -73
- package/src/app/shared/services/job.utils.d.ts +0 -20
- package/src/app/shared/services/memory-entity-service.class.d.ts +0 -71
- package/src/app/shared/services/progress-bar.service.d.ts +0 -20
- package/src/app/shared/services/startable-observable-service.class.d.ts +0 -33
- package/src/app/shared/services/startable-service.class.d.ts +0 -34
- package/src/app/shared/services/translate-context.service.d.ts +0 -29
- package/src/app/shared/services/validator-service.class.d.ts +0 -10
- package/src/app/shared/services.d.ts +0 -9
- package/src/app/shared/shared-routing.module.d.ts +0 -22
- package/src/app/shared/shared.module.d.ts +0 -31
- package/src/app/shared/shared.testing.module.d.ts +0 -17
- package/src/app/shared/storage/storage-explorer.component.d.ts +0 -58
- package/src/app/shared/storage/storage-explorer.module.d.ts +0 -16
- package/src/app/shared/storage/storage.service.d.ts +0 -23
- package/src/app/shared/storage/storage.utils.d.ts +0 -19
- package/src/app/shared/testing/observable.test.d.ts +0 -25
- package/src/app/shared/testing/tests.page.d.ts +0 -20
- package/src/app/shared/toast/toast.testing.d.ts +0 -15
- package/src/app/shared/toast/toast.testing.module.d.ts +0 -11
- package/src/app/shared/toast/toasts.d.ts +0 -17
- package/src/app/shared/toolbar/modal-toolbar.d.ts +0 -21
- package/src/app/shared/toolbar/toolbar.d.ts +0 -63
- package/src/app/shared/toolbar/toolbar.module.d.ts +0 -15
- package/src/app/shared/types.d.ts +0 -26
- package/src/app/shared/upload-file/testing/upload-file.testing.d.ts +0 -20
- package/src/app/shared/upload-file/testing/upload-file.testing.module.d.ts +0 -11
- package/src/app/shared/upload-file/upload-file-popover.component.d.ts +0 -39
- package/src/app/shared/upload-file/upload-file.component.d.ts +0 -48
- package/src/app/shared/upload-file/upload-file.model.d.ts +0 -30
- package/src/app/shared/validator/form-error-adapter.class.d.ts +0 -27
- package/src/app/shared/validator/validators.d.ts +0 -115
- package/src/app/shared/version/versions.d.ts +0 -26
- package/src/app/social/job/job.module.d.ts +0 -12
- package/src/app/social/job/progression/job-progression.component.d.ts +0 -9
- package/src/app/social/job/progression/job-progression.icon.d.ts +0 -49
- package/src/app/social/job/progression/job-progression.list.d.ts +0 -21
- package/src/app/social/job/progression/job-progression.model.d.ts +0 -11
- package/src/app/social/job/progression/job-progression.service.d.ts +0 -34
- package/src/app/social/job/testing/job-progression.testing.d.ts +0 -17
- package/src/app/social/job/testing/job-progression.testing.service.d.ts +0 -17
- package/src/app/social/job/testing/job.testing.module.d.ts +0 -11
- package/src/app/social/message/message.form.d.ts +0 -30
- package/src/app/social/message/message.modal.d.ts +0 -39
- package/src/app/social/message/message.model.d.ts +0 -31
- package/src/app/social/message/message.module.d.ts +0 -11
- package/src/app/social/message/message.service.d.ts +0 -27
- package/src/app/social/social.errors.d.ts +0 -9
- package/src/app/social/social.module.d.ts +0 -20
- package/src/app/social/social.testing.module.d.ts +0 -13
- package/src/app/social/user-event/notification/user-event-notification.icon.d.ts +0 -31
- package/src/app/social/user-event/notification/user-event-notification.list.d.ts +0 -71
- package/src/app/social/user-event/testing/user-event.testing.d.ts +0 -34
- package/src/app/social/user-event/testing/user-event.testing.model.d.ts +0 -44
- package/src/app/social/user-event/testing/user-event.testing.module.d.ts +0 -11
- package/src/app/social/user-event/testing/user-event.testing.service.d.ts +0 -41
- package/src/app/social/user-event/user-event.model.d.ts +0 -45
- package/src/app/social/user-event/user-event.module.d.ts +0 -12
- package/src/app/social/user-event/user-event.service.d.ts +0 -124
- package/src/environments/environment.class.d.ts +0 -57
- package/src/environments/environment.d.ts +0 -3
|
@@ -0,0 +1,1934 @@
|
|
|
1
|
+
import { AfterViewInit, Directive, EventEmitter, Injector, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
|
|
2
|
+
import { MatPaginator } from '@angular/material/paginator';
|
|
3
|
+
import { MatSort, MatSortable, SortDirection } from '@angular/material/sort';
|
|
4
|
+
import { MatTable } from '@angular/material/table';
|
|
5
|
+
import { BehaviorSubject, EMPTY, merge, Observable, of, Subject, Subscription } from 'rxjs';
|
|
6
|
+
import { catchError, debounceTime, distinctUntilChanged, filter, first, mergeMap, startWith, switchMap, takeUntil, tap } from 'rxjs/operators';
|
|
7
|
+
import { SelectionModel } from '@angular/cdk/collections';
|
|
8
|
+
import { EntityUtils, IEntity } from '../services/model/entity.model';
|
|
9
|
+
import { AlertController, ModalController, ToastController } from '@ionic/angular';
|
|
10
|
+
import { ActivatedRoute, Router } from '@angular/router';
|
|
11
|
+
import { ColumnItem, TableSelectColumnsComponent } from './table-select-columns.component';
|
|
12
|
+
import { Location } from '@angular/common';
|
|
13
|
+
import { ErrorCodes } from '../services/errors';
|
|
14
|
+
import { AppFormUtils, IAppForm, OnReady } from '../form/form.utils';
|
|
15
|
+
import { LocalSettingsService } from '../services/local-settings.service';
|
|
16
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
17
|
+
import { MatAutocompleteConfigHolder, MatAutocompleteFieldAddOptions, MatAutocompleteFieldConfig } from '../../shared/material/autocomplete/material.autocomplete.config';
|
|
18
|
+
import { CompletableEvent, createPromiseEventEmitter, emitPromiseEvent } from '../../shared/events';
|
|
19
|
+
import { changeCaseToUnderscore, isEmptyArray, isNil, isNotNil, toBoolean } from '../../shared/functions';
|
|
20
|
+
import { waitFor, waitForFalse, WaitForOptions, waitForTrue } from '../../shared/observables';
|
|
21
|
+
import { ShowToastOptions, Toasts } from '../../shared/toast/toasts';
|
|
22
|
+
import { Alerts } from '../../shared/alerts';
|
|
23
|
+
import { CdkColumnDef } from '@angular/cdk/table';
|
|
24
|
+
import { LoadResult } from '../../shared/services/entity-service.class';
|
|
25
|
+
import { FormErrorTranslator, FormErrorTranslatorOptions, IFormControlPathTranslator } from '../../shared/validator/form-error-adapter.class';
|
|
26
|
+
import {
|
|
27
|
+
CellValueChangeListener,
|
|
28
|
+
DEFAULT_PAGE_SIZE,
|
|
29
|
+
DEFAULT_PAGE_SIZE_OPTIONS,
|
|
30
|
+
DEFAULT_REQUIRED_COLUMNS,
|
|
31
|
+
RESERVED_END_COLUMNS,
|
|
32
|
+
RESERVED_START_COLUMNS,
|
|
33
|
+
SaveActionType,
|
|
34
|
+
SETTINGS_DISPLAY_COLUMNS,
|
|
35
|
+
SETTINGS_PAGE_SIZE,
|
|
36
|
+
SETTINGS_SORTED_COLUMN
|
|
37
|
+
} from './table.model';
|
|
38
|
+
import { AsyncTableElement } from '@e-is/ngx-material-table';
|
|
39
|
+
import { EntitiesAsyncTableDataSource } from './entities-async-table-datasource.class';
|
|
40
|
+
import {AppTableUtils} from './table.utils';
|
|
41
|
+
|
|
42
|
+
// @dynamic
|
|
43
|
+
// noinspection DuplicatedCode
|
|
44
|
+
@Directive()
|
|
45
|
+
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
|
46
|
+
export abstract class AppAsyncTable<T extends IEntity<T, ID>,
|
|
47
|
+
F = any,
|
|
48
|
+
ID = number>
|
|
49
|
+
implements OnInit, OnDestroy, AfterViewInit, IAppForm, IFormControlPathTranslator {
|
|
50
|
+
|
|
51
|
+
private _initialized = false;
|
|
52
|
+
private _subscription = new Subscription();
|
|
53
|
+
private _dataSourceLoadingSubscription: Subscription;
|
|
54
|
+
|
|
55
|
+
private _cellValueChangesDefs: {
|
|
56
|
+
[key: string]: CellValueChangeListener;
|
|
57
|
+
} = {};
|
|
58
|
+
|
|
59
|
+
protected _enabled = true;
|
|
60
|
+
protected _autocompleteConfigHolder: MatAutocompleteConfigHolder;
|
|
61
|
+
protected allowRowDetail = true;
|
|
62
|
+
protected route: ActivatedRoute;
|
|
63
|
+
protected router: Router;
|
|
64
|
+
protected location: Location;
|
|
65
|
+
protected settings: LocalSettingsService;
|
|
66
|
+
protected translate: TranslateService;
|
|
67
|
+
protected modalCtrl: ModalController;
|
|
68
|
+
protected alertCtrl: AlertController;
|
|
69
|
+
protected toastController: ToastController;
|
|
70
|
+
protected previouslyEditedRowId: number;
|
|
71
|
+
protected formErrorAdapter: FormErrorTranslator;
|
|
72
|
+
protected readonly destroySubject = new Subject<void>();
|
|
73
|
+
|
|
74
|
+
excludesColumns: string[] = [];
|
|
75
|
+
displayedColumns: string[];
|
|
76
|
+
totalRowCount: number | null = null;
|
|
77
|
+
visibleRowCount: number;
|
|
78
|
+
errorTranslatorOptions: FormErrorTranslatorOptions;
|
|
79
|
+
|
|
80
|
+
readonly readySubject = new BehaviorSubject<boolean>(false);
|
|
81
|
+
readonly loadingSubject = new BehaviorSubject<boolean>(true);
|
|
82
|
+
readonly savingSubject = new BehaviorSubject<boolean>(false);
|
|
83
|
+
readonly touchedSubject = new BehaviorSubject<boolean>(false);
|
|
84
|
+
readonly dirtySubject = new BehaviorSubject<boolean>(false);
|
|
85
|
+
readonly errorSubject = new BehaviorSubject<string>(undefined);
|
|
86
|
+
|
|
87
|
+
get error(): string {
|
|
88
|
+
return this.errorSubject.value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
set error(error: string) {
|
|
92
|
+
this.setError(error);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
selection = new SelectionModel<AsyncTableElement<T>>(true, []);
|
|
96
|
+
permanentSelection: SelectionModel<T> = null;
|
|
97
|
+
permanentSelectionChangedPrevented = false;
|
|
98
|
+
autocompleteFields: { [key: string]: MatAutocompleteFieldConfig };
|
|
99
|
+
readonly mobile: boolean;
|
|
100
|
+
|
|
101
|
+
// Table options
|
|
102
|
+
@Input() settingsId: string;
|
|
103
|
+
@Input() debug: boolean;
|
|
104
|
+
@Input() i18nColumnPrefix = 'COMMON.';
|
|
105
|
+
@Input() i18nColumnSuffix: string;
|
|
106
|
+
@Input() autoLoad = true;
|
|
107
|
+
@Input() readOnly: boolean;
|
|
108
|
+
@Input() inlineEdition: boolean;
|
|
109
|
+
@Input() focusFirstColumn = false;
|
|
110
|
+
@Input() confirmBeforeDelete = false;
|
|
111
|
+
@Input() confirmBeforeCancel = false;
|
|
112
|
+
@Input() undoableDeletion = false;
|
|
113
|
+
@Input() saveBeforeDelete: boolean;
|
|
114
|
+
@Input() keepEditedRowOnSave: boolean;
|
|
115
|
+
@Input() saveBeforeSort: boolean;
|
|
116
|
+
@Input() saveBeforeFilter: boolean;
|
|
117
|
+
@Input() propagateRowError = false;
|
|
118
|
+
@Input() permanentSelectionAllowed = false; // Allow keep selected rows over page change or sort change
|
|
119
|
+
|
|
120
|
+
@Input() defaultSortBy: string;
|
|
121
|
+
@Input() defaultSortDirection: SortDirection;
|
|
122
|
+
@Input() defaultPageSize = DEFAULT_PAGE_SIZE;
|
|
123
|
+
@Input() defaultPageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS;
|
|
124
|
+
|
|
125
|
+
// Focus manager
|
|
126
|
+
@Input() focusColumn: string;
|
|
127
|
+
|
|
128
|
+
get firstUserColumn(): string {
|
|
129
|
+
return this.displayedColumns[RESERVED_START_COLUMNS.length];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
get lastUserColumn(): string {
|
|
133
|
+
return this.displayedColumns[this.displayedColumns.length - RESERVED_END_COLUMNS.length - 1];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@Input() set dataSource(value: EntitiesAsyncTableDataSource<T, F, ID>) {
|
|
137
|
+
this.setDatasource(value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
get dataSource(): EntitiesAsyncTableDataSource<T, F, ID> {
|
|
141
|
+
return this._dataSource;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Input() set filter(value: F) {
|
|
145
|
+
this.setFilter(value);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
get filter(): F {
|
|
149
|
+
return this._filter;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get empty(): boolean {
|
|
153
|
+
return this.loading || this.totalRowCount === 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get selectedEntities(): T[] {
|
|
157
|
+
return this.permanentSelection?.selected
|
|
158
|
+
|| AppTableUtils.getEntities(this.selection.selected);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@Output() onRefresh = new EventEmitter<any>();
|
|
162
|
+
@Output() onOpenRow = new EventEmitter<AsyncTableElement<T>>();
|
|
163
|
+
@Output() onNewRow = new EventEmitter<any>();
|
|
164
|
+
@Output() onStartEditingRow = new EventEmitter<AsyncTableElement<T>>();
|
|
165
|
+
@Output() onConfirmEditCreateRow = new EventEmitter<AsyncTableElement<T>>();
|
|
166
|
+
@Output() onCancelOrDeleteRow = new EventEmitter<AsyncTableElement<T>>();
|
|
167
|
+
@Output() onBeforeDeleteRows = createPromiseEventEmitter<boolean, { rows: AsyncTableElement<T>[] }>();
|
|
168
|
+
@Output() onBeforeCancelRows = createPromiseEventEmitter<boolean, { rows: AsyncTableElement<T>[] }>();
|
|
169
|
+
@Output() onBeforeSave = createPromiseEventEmitter<{ confirmed: boolean; save: boolean }, { action: SaveActionType; valid: boolean }>();
|
|
170
|
+
@Output() onAfterDeletedRows = new EventEmitter<AsyncTableElement<T>[]>();
|
|
171
|
+
@Output() onSort = new EventEmitter<any>();
|
|
172
|
+
@Output() onDirty = new EventEmitter<boolean>();
|
|
173
|
+
@Output() onError = new EventEmitter<string>();
|
|
174
|
+
|
|
175
|
+
get dirty(): boolean {
|
|
176
|
+
return this.dirtySubject.value;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
get valid(): boolean {
|
|
180
|
+
return this.dataSource.getRows().every(row => row.editing ? row.valid : true);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
get invalid(): boolean {
|
|
184
|
+
return this.dataSource.getRows().some(row => row.editing ? row.invalid : false);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
get pending(): boolean {
|
|
188
|
+
return this.dataSource.getRows().some(row => row.editing ? row.pending : false);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
get touched(): boolean {
|
|
192
|
+
return this.touchedSubject.value;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
get untouched(): boolean {
|
|
196
|
+
return !this.touchedSubject.value;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
disable(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
200
|
+
if (this.sort) this.sort.disabled = true;
|
|
201
|
+
this._enabled = false;
|
|
202
|
+
if (!opts || opts.emitEvent != false) this.markForCheck();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
enable(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
206
|
+
if (this.sort) this.sort.disabled = false;
|
|
207
|
+
this._enabled = true;
|
|
208
|
+
if (!opts || opts.emitEvent != false) this.markForCheck();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
get enabled(): boolean {
|
|
212
|
+
return this._enabled;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// FIXME: need to hidden buttons (in HTML), etc. when disabled
|
|
216
|
+
@Input() set disabled(value: boolean) {
|
|
217
|
+
if (value !== !this._enabled) {
|
|
218
|
+
if (value) this.disable({ emitEvent: false });
|
|
219
|
+
else this.enable({ emitEvent: false });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
get disabled(): boolean {
|
|
224
|
+
return !this._enabled;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
markAsDirty(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
228
|
+
if (this.dirtySubject.value !== true) {
|
|
229
|
+
this.dirtySubject.next(true);
|
|
230
|
+
if (!opts || opts.emitEvent !== false) {
|
|
231
|
+
this.markForCheck();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
markAsPristine(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
237
|
+
if (this.dirtySubject.value !== false) {
|
|
238
|
+
this.dirtySubject.next(false);
|
|
239
|
+
if (!opts || opts.emitEvent !== false) {
|
|
240
|
+
this.markForCheck();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async markAsUntouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
246
|
+
let needEmitEvent = false;
|
|
247
|
+
if (this.touchedSubject.value) {
|
|
248
|
+
this.touchedSubject.next(false);
|
|
249
|
+
needEmitEvent = true;
|
|
250
|
+
}
|
|
251
|
+
if (this.dirty || this.dataSource.hasSomeEditingRow()) {
|
|
252
|
+
for (const row of this.dataSource.getEditingRows()) {
|
|
253
|
+
|
|
254
|
+
// Cancel the current editing row only if editing and if it was not previously saved
|
|
255
|
+
await this.dataSource.cancelOrDelete(row);
|
|
256
|
+
|
|
257
|
+
// Check if row as pristine
|
|
258
|
+
await this.checkIfRowPristine(row, {onlySelf: true /* avoid propagation to table - done just after */});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Check if the table is pristine
|
|
262
|
+
await this.checkIfPristine({emitEvent: false /*will be done just after*/});
|
|
263
|
+
|
|
264
|
+
needEmitEvent = true;
|
|
265
|
+
}
|
|
266
|
+
this.previouslyEditedRowId = undefined;
|
|
267
|
+
if (needEmitEvent && (!opts || opts.emitEvent !== false)) this.markForCheck();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @deprecated prefer to use markAllAsTouched()
|
|
272
|
+
* @param opts
|
|
273
|
+
*/
|
|
274
|
+
markAsTouched(opts?: { onlySelf?: boolean; emitEvent?: boolean }) {
|
|
275
|
+
console.warn('TODO: Replace this call by markAllAsTouched() - because of changes in ngx-components >= 0.16.0');
|
|
276
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
277
|
+
this.dataSource.getEditingRows().forEach(row => row.validator?.markAllAsTouched());
|
|
278
|
+
if (!opts || opts.emitEvent !== false) {
|
|
279
|
+
this.markForCheck();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
markAllAsTouched(opts?: { emitEvent?: boolean }) {
|
|
285
|
+
if (this.touchedSubject.value !== true) {
|
|
286
|
+
this.touchedSubject.next(true);
|
|
287
|
+
if (!opts || opts.emitEvent !== false) this.markForCheck();
|
|
288
|
+
}
|
|
289
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
290
|
+
this.dataSource.getEditingRows().forEach(row => row.validator?.markAllAsTouched());
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
markAsSaving(opts?: { emitEvent?: boolean }) {
|
|
295
|
+
if (this.savingSubject.value !== true) {
|
|
296
|
+
this.focusColumn = undefined; // unselect focus column
|
|
297
|
+
this.savingSubject.next(true);
|
|
298
|
+
if (!opts || opts.emitEvent !== false) this.markForCheck();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
markAsSaved(opts?: { emitEvent?: boolean }) {
|
|
303
|
+
if (this.savingSubject.value !== false) {
|
|
304
|
+
this.savingSubject.next(false);
|
|
305
|
+
if (!opts || opts.emitEvent !== false) this.markForCheck();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
markAsLoading(opts?: { emitEvent?: boolean }) {
|
|
310
|
+
this.setLoading(true, opts);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
markAsLoaded(opts?: { emitEvent?: boolean }) {
|
|
314
|
+
this.setLoading(false, opts);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
markAsReady(opts?: { emitEvent?: boolean }) {
|
|
318
|
+
if (this.readySubject.value !== true) {
|
|
319
|
+
this.readySubject.next(true);
|
|
320
|
+
|
|
321
|
+
// If subclasses implements OnReady
|
|
322
|
+
if (typeof this['ngOnReady'] === 'function') {
|
|
323
|
+
(this as any as OnReady).ngOnReady();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
get loading(): boolean {
|
|
329
|
+
return this.loadingSubject.value;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
get loaded(): boolean {
|
|
333
|
+
return !this.loadingSubject.value;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
enableSort() {
|
|
337
|
+
if (this.sort) this.sort.disabled = false;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
disableSort() {
|
|
341
|
+
if (this.sort) this.sort.disabled = true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
set pageSize(value: number) {
|
|
345
|
+
this.defaultPageSize = value;
|
|
346
|
+
if (this.paginator) {
|
|
347
|
+
this.paginator.pageSize = value;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
get pageSize(): number {
|
|
352
|
+
return this.paginator && this.paginator.pageSize || this.defaultPageSize || DEFAULT_PAGE_SIZE;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
get pageOffset(): number {
|
|
356
|
+
return this.paginator && this.paginator.pageIndex * this.paginator.pageSize || 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
get sortActive(): string {
|
|
360
|
+
return this.sort && this.sort.active;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
get sortDirection(): 'asc' | 'desc' {
|
|
364
|
+
return this.sort && this.sort.direction && (this.sort.direction === 'desc' ? 'desc' : 'asc') || undefined;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private _paginator: MatPaginator | null = null;
|
|
368
|
+
|
|
369
|
+
@Input() set paginator(value: MatPaginator) {
|
|
370
|
+
this._paginator = value;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
get paginator(): MatPaginator {
|
|
374
|
+
return this._paginator || this.childPaginator;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
get destroyed(): boolean {
|
|
378
|
+
return this.destroySubject?.closed !== false;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
@ViewChild(MatTable, { static: false }) table: MatTable<T>;
|
|
382
|
+
@ViewChild(MatPaginator, { static: false }) childPaginator: MatPaginator;
|
|
383
|
+
@ViewChild(MatSort, { static: false }) sort: MatSort;
|
|
384
|
+
|
|
385
|
+
protected constructor(
|
|
386
|
+
injector: Injector,
|
|
387
|
+
protected columns: string[],
|
|
388
|
+
protected _dataSource?: EntitiesAsyncTableDataSource<T, F, ID>,
|
|
389
|
+
private _filter?: F
|
|
390
|
+
) {
|
|
391
|
+
this.route = injector.get(ActivatedRoute);
|
|
392
|
+
this.router = injector.get(Router);
|
|
393
|
+
this.location = injector.get(Location);
|
|
394
|
+
this.settings = injector.get(LocalSettingsService);
|
|
395
|
+
this.translate = injector.get(TranslateService);
|
|
396
|
+
this.modalCtrl = injector.get(ModalController);
|
|
397
|
+
this.alertCtrl = injector.get(AlertController);
|
|
398
|
+
this.toastController = injector.get(ToastController);
|
|
399
|
+
this.formErrorAdapter = injector.get(FormErrorTranslator);
|
|
400
|
+
this.mobile = this.settings.mobile;
|
|
401
|
+
|
|
402
|
+
// Autocomplete fields
|
|
403
|
+
this._autocompleteConfigHolder = new MatAutocompleteConfigHolder({
|
|
404
|
+
getUserAttributes: (a, b) => this.settings.getFieldDisplayAttributes(a, b)
|
|
405
|
+
});
|
|
406
|
+
this.autocompleteFields = this._autocompleteConfigHolder.fields;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
ngOnInit() {
|
|
410
|
+
if (this._initialized) return; // Init only once
|
|
411
|
+
this._initialized = true;
|
|
412
|
+
|
|
413
|
+
// Set defaults
|
|
414
|
+
this.readOnly = toBoolean(this.readOnly, this.dataSource?.config.readOnly || false); // read/write by default
|
|
415
|
+
this.inlineEdition = !this.readOnly && toBoolean(this.inlineEdition, false); // force to false when readonly
|
|
416
|
+
this.saveBeforeDelete = toBoolean(this.saveBeforeDelete, !this.readOnly); // force to false when readonly
|
|
417
|
+
this.saveBeforeSort = toBoolean(this.saveBeforeSort, !this.readOnly); // force to false when readonly
|
|
418
|
+
this.saveBeforeFilter = toBoolean(this.saveBeforeFilter, !this.readOnly); // force to false when readonly
|
|
419
|
+
this.keepEditedRowOnSave = toBoolean(this.keepEditedRowOnSave, this.inlineEdition);
|
|
420
|
+
this.errorTranslatorOptions = this.errorTranslatorOptions || { separator: ', ', controlPathTranslator: this }; // Can be override in subclasses constructors
|
|
421
|
+
|
|
422
|
+
// Check ask user confirmation is possible
|
|
423
|
+
if (this.confirmBeforeDelete && !this.alertCtrl) throw Error('Missing \'alertCtrl\' or \'injector\' in component\'s constructor.');
|
|
424
|
+
|
|
425
|
+
// Defined unique id for settings for the page
|
|
426
|
+
this.settingsId = this.settingsId || this.generateTableId();
|
|
427
|
+
|
|
428
|
+
this.displayedColumns = this.getDisplayColumns();
|
|
429
|
+
|
|
430
|
+
// Load the sorted columns, from settings
|
|
431
|
+
{
|
|
432
|
+
const sortedColumn = this.getSortedColumn();
|
|
433
|
+
this.defaultSortBy = sortedColumn.id;
|
|
434
|
+
this.defaultSortDirection = sortedColumn.start;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
this.defaultPageSize = this.getPageSize();
|
|
438
|
+
|
|
439
|
+
// Propagate error to event emitter
|
|
440
|
+
this.registerSubscription(this.errorSubject
|
|
441
|
+
.subscribe(value => this.onError.emit(value)));
|
|
442
|
+
|
|
443
|
+
// Propagate dirty to event emitter
|
|
444
|
+
this.registerSubscription(this.dirtySubject
|
|
445
|
+
.subscribe(value => this.onDirty.emit(value)));
|
|
446
|
+
|
|
447
|
+
// Propagate row dirty state to table
|
|
448
|
+
this.registerSubscription(
|
|
449
|
+
this.onStartEditingRow
|
|
450
|
+
.pipe(
|
|
451
|
+
filter(row => row?.validator && true),
|
|
452
|
+
mergeMap(row => row.validator.valueChanges
|
|
453
|
+
.pipe(
|
|
454
|
+
filter(row => row.dirty),
|
|
455
|
+
first(),
|
|
456
|
+
// DEBUG
|
|
457
|
+
//tap(() => console.debug("Propagate row's dirty to table..."))
|
|
458
|
+
|
|
459
|
+
// Stop if next another row, or destroying
|
|
460
|
+
takeUntil(this.onStartEditingRow),
|
|
461
|
+
takeUntil(this.destroySubject)
|
|
462
|
+
))
|
|
463
|
+
)
|
|
464
|
+
.subscribe(() => this.markAsDirty())
|
|
465
|
+
);
|
|
466
|
+
|
|
467
|
+
// Call datasource refresh, on each refresh events
|
|
468
|
+
this.registerSubscription(
|
|
469
|
+
this.onRefresh
|
|
470
|
+
.pipe(
|
|
471
|
+
startWith<any, any>((this.autoLoad ? {} : 'skip') as any),
|
|
472
|
+
switchMap(
|
|
473
|
+
(event: any) => {
|
|
474
|
+
this.dirtySubject.next(false);
|
|
475
|
+
this.selection.clear();
|
|
476
|
+
if (event === 'skip') {
|
|
477
|
+
return of(undefined);
|
|
478
|
+
}
|
|
479
|
+
if (!this._dataSource) {
|
|
480
|
+
if (this.debug) console.debug('[table] Skipping data load: no dataSource defined');
|
|
481
|
+
return of(undefined);
|
|
482
|
+
}
|
|
483
|
+
if (this.debug) console.debug('[table] Calling dataSource.watchAll()...');
|
|
484
|
+
return this._dataSource.watchAll(
|
|
485
|
+
this.pageOffset,
|
|
486
|
+
this.pageSize,
|
|
487
|
+
this.sortActive,
|
|
488
|
+
this.sortDirection,
|
|
489
|
+
this._filter
|
|
490
|
+
);
|
|
491
|
+
}),
|
|
492
|
+
catchError(err => {
|
|
493
|
+
if (this.debug) console.error(err);
|
|
494
|
+
this.setError(err && err.message || err);
|
|
495
|
+
return of(undefined); // Continue
|
|
496
|
+
})
|
|
497
|
+
)
|
|
498
|
+
.subscribe(res => this.updateView(res as LoadResult<T> | undefined)));
|
|
499
|
+
|
|
500
|
+
// Listen dataSource loading events
|
|
501
|
+
if (this._dataSource) this.listenDatasourceLoading(this._dataSource);
|
|
502
|
+
|
|
503
|
+
// Permanent selection behavior
|
|
504
|
+
if (this.permanentSelectionAllowed) this.initPermanentSelection();}
|
|
505
|
+
|
|
506
|
+
ngAfterViewInit() {
|
|
507
|
+
// Detect when parent ngOnInit() not call
|
|
508
|
+
if (this.debug && !this.displayedColumns) console.warn(`[table] Missing 'displayedColumns'. Did you call parent ngOnInit() in component ${this.constructor.name} ?`);
|
|
509
|
+
|
|
510
|
+
// Start listening sort and paginator events
|
|
511
|
+
// noinspection JSIgnoredPromiseFromCall
|
|
512
|
+
this.listenSortAndPaginationEvents();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
ngOnDestroy() {
|
|
516
|
+
this._subscription.unsubscribe();
|
|
517
|
+
|
|
518
|
+
// Unsubscribe column value changes
|
|
519
|
+
Object.keys(this._cellValueChangesDefs).forEach(col => this.stopCellValueChanges(col, true));
|
|
520
|
+
this._cellValueChangesDefs = {};
|
|
521
|
+
|
|
522
|
+
this.readySubject.unsubscribe();
|
|
523
|
+
this.loadingSubject.unsubscribe();
|
|
524
|
+
this.savingSubject.unsubscribe();
|
|
525
|
+
this.errorSubject.unsubscribe();
|
|
526
|
+
this.dirtySubject.unsubscribe();
|
|
527
|
+
|
|
528
|
+
this.onRefresh.unsubscribe();
|
|
529
|
+
this.onOpenRow.unsubscribe();
|
|
530
|
+
this.onNewRow.unsubscribe();
|
|
531
|
+
this.onStartEditingRow.unsubscribe();
|
|
532
|
+
this.onConfirmEditCreateRow.unsubscribe();
|
|
533
|
+
this.onCancelOrDeleteRow.unsubscribe();
|
|
534
|
+
this.onBeforeDeleteRows.unsubscribe();
|
|
535
|
+
this.onBeforeCancelRows.unsubscribe();
|
|
536
|
+
this.onBeforeSave.unsubscribe();
|
|
537
|
+
this.onAfterDeletedRows.unsubscribe();
|
|
538
|
+
this.onSort.unsubscribe();
|
|
539
|
+
this.onDirty.unsubscribe();
|
|
540
|
+
this.onError.unsubscribe();
|
|
541
|
+
|
|
542
|
+
this.destroySubject.next();
|
|
543
|
+
this.destroySubject.unsubscribe();
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
async updateView(res: LoadResult<T> | undefined, opts?: {
|
|
547
|
+
emitEvent?: boolean;
|
|
548
|
+
}): Promise<void> {
|
|
549
|
+
if (!res) return; // Skip (e.g error)
|
|
550
|
+
if (res && res.data) {
|
|
551
|
+
this.visibleRowCount = res.data.length;
|
|
552
|
+
this.totalRowCount = isNotNil(res.total) ? res.total : ((this.paginator && this.paginator.pageIndex * (this.paginator.pageSize || DEFAULT_PAGE_SIZE) || 0) + this.visibleRowCount);
|
|
553
|
+
if (this.debug) console.debug(`[table] ${res.data.length} rows loaded`);
|
|
554
|
+
} else {
|
|
555
|
+
//if (this.debug) console.debug('[table] NO rows loaded');
|
|
556
|
+
this.totalRowCount = 0;
|
|
557
|
+
this.visibleRowCount = 0;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
if (!opts || opts.emitEvent !== false) {
|
|
561
|
+
await this.markAsUntouched({ emitEvent: false });
|
|
562
|
+
this.markAsPristine({ emitEvent: false });
|
|
563
|
+
this.markAsLoaded({ emitEvent: false });
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
this.markForCheck();
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
setDatasource(datasource: EntitiesAsyncTableDataSource<T, F, ID>) {
|
|
570
|
+
if (this._dataSource) throw new Error('[table] dataSource already set !');
|
|
571
|
+
if (datasource && this._dataSource !== datasource) {
|
|
572
|
+
this._dataSource = datasource;
|
|
573
|
+
if (this._initialized) this.listenDatasourceLoading(datasource);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
resetDataSource() {
|
|
578
|
+
if (this._dataSourceLoadingSubscription) {
|
|
579
|
+
this._dataSourceLoadingSubscription.unsubscribe();
|
|
580
|
+
this._subscription.remove(this._dataSourceLoadingSubscription);
|
|
581
|
+
}
|
|
582
|
+
//this._dataSource?.close();
|
|
583
|
+
this._dataSource = null;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
addColumnDef(column: CdkColumnDef) {
|
|
587
|
+
this.table.addColumnDef(column);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
removeColumnDef(column: CdkColumnDef) {
|
|
591
|
+
this.table.removeColumnDef(column);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
setFilter(filter: F, opts?: { emitEvent?: boolean; permanentSelectionChangedPrevented?: boolean }) {
|
|
595
|
+
opts = opts || { emitEvent: true };
|
|
596
|
+
|
|
597
|
+
// Prevent permanent selection change events
|
|
598
|
+
this.permanentSelectionChangedPrevented = toBoolean(opts.permanentSelectionChangedPrevented, this.permanentSelectionChangedPrevented);
|
|
599
|
+
|
|
600
|
+
if (this.saveBeforeFilter) {
|
|
601
|
+
|
|
602
|
+
// if a dirty table is to be saved before filter
|
|
603
|
+
if (this.dirty) {
|
|
604
|
+
|
|
605
|
+
// Save
|
|
606
|
+
this.saveBeforeAction('filter').then(saved => {
|
|
607
|
+
// Apply filter only if user didn't cancel the save or the save is ok
|
|
608
|
+
if (saved) {
|
|
609
|
+
this.applyFilter(filter, opts);
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
} else {
|
|
614
|
+
// apply filter on non-dirty table
|
|
615
|
+
this.applyFilter(filter, opts);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
} else {
|
|
619
|
+
|
|
620
|
+
// apply filter directly
|
|
621
|
+
this.applyFilter(filter, opts);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
async confirmAndAdd(event?: Event, row?: AsyncTableElement<T>): Promise<boolean> {
|
|
626
|
+
if (!await this.confirmEditCreate(event, row)) {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
// Add row
|
|
630
|
+
return this.addRow(event);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
async confirmAndBackward(event?: Event, row?: AsyncTableElement<T>): Promise<boolean> {
|
|
634
|
+
|
|
635
|
+
// Deleting edited row, if empty and not dirty
|
|
636
|
+
if (this.dataSource.hasSomeEditingRow()) {
|
|
637
|
+
for (const editingRow of this.dataSource.getEditingRows().filter(row => row.id === -1 && row.invalid && !row.dirty)) {
|
|
638
|
+
await this.deleteNewRow(event, editingRow);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Wait deletion is done, then edit previous row (by id, because of reloading)
|
|
642
|
+
await this.waitIdle();
|
|
643
|
+
await this.editRowById(event, row.id, { focusColumn: this.lastUserColumn });
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Edit previous row
|
|
648
|
+
await this.editRow(event, row, { focusColumn: this.lastUserColumn });
|
|
649
|
+
return true;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
async confirmAndForward(event?: Event, row?: AsyncTableElement<T>): Promise<boolean> {
|
|
653
|
+
if (!this.inlineEdition) return false;
|
|
654
|
+
|
|
655
|
+
const confirmed = await this.confirmEditCreate(event, row);
|
|
656
|
+
if (!confirmed) return false; // Not confirmed
|
|
657
|
+
|
|
658
|
+
// Edit next row
|
|
659
|
+
await this.editRowById(event, row.id + 1, { focusColumn: this.firstUserColumn });
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Confirm the creation of the given row, or if not specified the currently edited row
|
|
665
|
+
*
|
|
666
|
+
* @param event
|
|
667
|
+
* @param row
|
|
668
|
+
*/
|
|
669
|
+
async confirmEditCreate(event?: Event, row?: AsyncTableElement<T>): Promise<boolean> {
|
|
670
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
671
|
+
if (!row || !row.editing) return true; // no row to confirm
|
|
672
|
+
|
|
673
|
+
// Stop event
|
|
674
|
+
event?.stopPropagation();
|
|
675
|
+
|
|
676
|
+
// Confirmation edition or creation
|
|
677
|
+
const confirmed = await row.confirmEditCreate();
|
|
678
|
+
|
|
679
|
+
if (confirmed) {
|
|
680
|
+
// Mark table as dirty (if row is dirty)
|
|
681
|
+
if (row.dirty) {
|
|
682
|
+
this.markAsDirty({ emitEvent: false /* because of resetError() */ });
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Clear error
|
|
686
|
+
this.resetError();
|
|
687
|
+
|
|
688
|
+
// Emit the confirm event
|
|
689
|
+
this.onConfirmEditCreateRow.next(row);
|
|
690
|
+
|
|
691
|
+
return true; // Continue
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (row.validator) {
|
|
695
|
+
// NOT confirmed = row has error
|
|
696
|
+
if (this.debug) {
|
|
697
|
+
console.warn('[table] Cannot confirm row, because invalid');
|
|
698
|
+
AppFormUtils.logFormErrors(row.validator, '[table] ');
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// fix: mark all controls as touched to show errors
|
|
702
|
+
row.validator.markAllAsTouched();
|
|
703
|
+
|
|
704
|
+
// Compute row error, and propagate to table's error
|
|
705
|
+
if (this.propagateRowError) {
|
|
706
|
+
const error = this.getRowError(row);
|
|
707
|
+
this.setError(error);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Not confirmed
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
async cancelOrDelete(event: Event, row: AsyncTableElement<T>, opts?: { interactive?: boolean; keepEditing?: boolean }) {
|
|
716
|
+
// Delete new row
|
|
717
|
+
if (row.id === -1) {
|
|
718
|
+
await this.deleteNewRow(event, row);
|
|
719
|
+
}
|
|
720
|
+
// Delete existing (but not editing) row
|
|
721
|
+
else if (!row.editing) {
|
|
722
|
+
await this.deleteExistingRow(event, row, opts);
|
|
723
|
+
}
|
|
724
|
+
// Cancel existing (and editing) row
|
|
725
|
+
else {
|
|
726
|
+
await this.cancelExistingRow(event, row, opts);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
async addRow(event?: Event, insertAt?: number, opts?: { focusColumn?: string; editing?: boolean }): Promise<boolean> {
|
|
731
|
+
if (this.debug) console.debug('[table] Asking for new row...');
|
|
732
|
+
if (!this._enabled) return false;
|
|
733
|
+
|
|
734
|
+
// Use modal if inline edition is disabled
|
|
735
|
+
if (!this.inlineEdition) {
|
|
736
|
+
await this.openNewRowDetail(event);
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Try to finish edited row first
|
|
741
|
+
if (!await this.confirmEditCreate()) {
|
|
742
|
+
return false;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// Add new row
|
|
746
|
+
const row = await this.addRowToTable(insertAt, opts);
|
|
747
|
+
return !!row;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
async save(opts?: { keepEditing?: boolean }): Promise<boolean> {
|
|
751
|
+
opts = {
|
|
752
|
+
keepEditing: this.keepEditedRowOnSave,
|
|
753
|
+
...opts
|
|
754
|
+
};
|
|
755
|
+
if (this.readOnly) {
|
|
756
|
+
throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
this.resetError();
|
|
760
|
+
|
|
761
|
+
// Keep edited row id (should be done BEFORE confirmEditCreate() )
|
|
762
|
+
const editedRow = this.dataSource.getSingleEditingRow();
|
|
763
|
+
this.previouslyEditedRowId = opts.keepEditing ? ((editedRow?.editing ? editedRow.id : undefined) || this.singleSelectedRow?.id) : undefined;
|
|
764
|
+
const previouslyEditedRowId = this.previouslyEditedRowId;
|
|
765
|
+
const previouslyEditedData = opts.keepEditing ? (isNotNil(previouslyEditedRowId) && editedRow?.currentData || this.singleSelectedRow?.currentData) : undefined;
|
|
766
|
+
|
|
767
|
+
if (!await this.confirmEditCreate()) {
|
|
768
|
+
throw { code: ErrorCodes.TABLE_INVALID_ROW_ERROR, message: 'ERROR.TABLE_INVALID_ROW_ERROR' };
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// Mark as saving
|
|
772
|
+
this.markAsSaving();
|
|
773
|
+
|
|
774
|
+
try {
|
|
775
|
+
|
|
776
|
+
// Calling service save()
|
|
777
|
+
if (this.debug) console.debug('[table] Calling dataSource.save()...');
|
|
778
|
+
const isOK = await this._dataSource.save();
|
|
779
|
+
|
|
780
|
+
if (isOK) this.markAsPristine();
|
|
781
|
+
|
|
782
|
+
return isOK;
|
|
783
|
+
} catch (err) {
|
|
784
|
+
this.setError(err && err.message || err);
|
|
785
|
+
throw err;
|
|
786
|
+
} finally {
|
|
787
|
+
this.markAsSaved();
|
|
788
|
+
|
|
789
|
+
// Restore previous row
|
|
790
|
+
if (isNotNil(previouslyEditedRowId)) {
|
|
791
|
+
await this.selectRowByIdOrData(previouslyEditedRowId, previouslyEditedData);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
async cancel(event?: Event, opts?: { interactive?: boolean }) {
|
|
797
|
+
|
|
798
|
+
// Check confirmation
|
|
799
|
+
if ((!opts || opts.interactive !== false) && this.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
|
|
800
|
+
event?.stopPropagation();
|
|
801
|
+
if (!await this.canCancelRows()) {
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
this.onRefresh.emit();
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
async duplicateRow(event?: Event, row?: AsyncTableElement<T>, opts?: {
|
|
810
|
+
skipProperties?: string[];
|
|
811
|
+
}) {
|
|
812
|
+
event?.stopPropagation();
|
|
813
|
+
|
|
814
|
+
row = row || this.singleSelectedRow;
|
|
815
|
+
if (!row || !await this.confirmEditCreate(event, row)) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const newRow = await this.addRowToTable(row.id + 1);
|
|
820
|
+
if (!newRow) throw new Error('Cannot add new row to table');
|
|
821
|
+
const json = { ...row.currentData, id: null };
|
|
822
|
+
|
|
823
|
+
// Reset some properties (e.g. rankOrder, etc)
|
|
824
|
+
if (opts && opts.skipProperties) {
|
|
825
|
+
const newData = newRow.currentData;
|
|
826
|
+
opts.skipProperties.forEach(key => json[key] = newData[key]);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
if (newRow.validator) {
|
|
830
|
+
newRow.validator.patchValue(json);
|
|
831
|
+
newRow.validator.markAsDirty();
|
|
832
|
+
} else {
|
|
833
|
+
if (newRow.currentData?.fromObject) {
|
|
834
|
+
newRow.currentData.fromObject(json);
|
|
835
|
+
} else {
|
|
836
|
+
newRow.currentData = json;
|
|
837
|
+
}
|
|
838
|
+
this.markAsDirty();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// select
|
|
842
|
+
await this.clickRow(undefined, newRow);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/** Whether the number of selected elements matches the total number of rows. */
|
|
846
|
+
isAllSelected() {
|
|
847
|
+
// DEBUG
|
|
848
|
+
//console.debug('isAllSelected. lengths', this.selection.selected.length, this.totalRowCount);
|
|
849
|
+
|
|
850
|
+
return this.selection.selected.length === this.totalRowCount ||
|
|
851
|
+
this.selection.selected.length === this.visibleRowCount;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/** Selects all rows if they are not all selected; otherwise clear selection. */
|
|
855
|
+
async masterToggle() {
|
|
856
|
+
|
|
857
|
+
if (this.loading) return;
|
|
858
|
+
if (this.isAllSelected()) {
|
|
859
|
+
this.selection.clear();
|
|
860
|
+
} else {
|
|
861
|
+
const rows = this._dataSource.getRows();
|
|
862
|
+
rows.forEach(row => this.selection.select(row));
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
async deleteSelection(event: Event, opts?: {interactive?: boolean}): Promise<number> {
|
|
867
|
+
const deleteCount = await this.deleteRows(event, this.selection.selected, opts);
|
|
868
|
+
if (deleteCount > 0) this.selection.clear();
|
|
869
|
+
return deleteCount;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
*
|
|
874
|
+
* @param event
|
|
875
|
+
* @param row
|
|
876
|
+
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
877
|
+
* And to force deletion even if table is busy
|
|
878
|
+
*/
|
|
879
|
+
async deleteRow(event: Event | null, row: AsyncTableElement<T>, opts?: { interactive?: boolean }): Promise<boolean> {
|
|
880
|
+
const deleteCount = await this.deleteRows(event, [row], opts);
|
|
881
|
+
return deleteCount === 1;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
*
|
|
886
|
+
* @param event
|
|
887
|
+
* @param rows
|
|
888
|
+
* @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
|
|
889
|
+
* And to force deletion even if table is busy
|
|
890
|
+
*/
|
|
891
|
+
async deleteRows(event: Event | null, rows: AsyncTableElement<T>[], opts?: { interactive?: boolean }): Promise<number> {
|
|
892
|
+
if (this.readOnly) {
|
|
893
|
+
throw { code: ErrorCodes.TABLE_READ_ONLY, message: 'ERROR.TABLE_READ_ONLY' };
|
|
894
|
+
}
|
|
895
|
+
if (event?.defaultPrevented) return 0; // SKip
|
|
896
|
+
event?.preventDefault();
|
|
897
|
+
this.resetError();
|
|
898
|
+
|
|
899
|
+
if (!this._enabled || isEmptyArray(rows)) return 0; // Skip is disabled, or no rows to delete
|
|
900
|
+
|
|
901
|
+
if (this.loading && (!opts || opts.interactive !== false)) {
|
|
902
|
+
console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.interactive = false to force deletion');
|
|
903
|
+
return 0; // Skip if loading
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Make sure to keep newly created row
|
|
907
|
+
const editedRow = this.dataSource.getSingleEditingRow();
|
|
908
|
+
if (editedRow?.id === -1 && editedRow.editing && !rows.includes(editedRow)) {
|
|
909
|
+
const confirmed = await this.confirmEditCreate();
|
|
910
|
+
if (!confirmed) return 0; // Cannot delete (e.g. edited row is invalid)
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// Check if it can delete
|
|
914
|
+
const canDelete = await this.canDeleteRows(rows, opts);
|
|
915
|
+
if (!canDelete) return 0; // Cannot delete
|
|
916
|
+
|
|
917
|
+
// Reverse row order (on a copy)
|
|
918
|
+
// This is a workaround, need because row.delete() has async execution
|
|
919
|
+
// and index cache is updated with a delay
|
|
920
|
+
let tempRows = rows.slice()
|
|
921
|
+
.sort((a, b) => a.id > b.id ? -1 : 1);
|
|
922
|
+
|
|
923
|
+
const deletedRows: AsyncTableElement<T>[] = [];
|
|
924
|
+
|
|
925
|
+
// If data need to be saved first
|
|
926
|
+
if (this.saveBeforeDelete) {
|
|
927
|
+
// Exclude invalid rows (because of save() will fail, when exists some invalid rows)
|
|
928
|
+
tempRows = tempRows.filter(row => {
|
|
929
|
+
// Delete the row :
|
|
930
|
+
// - if newly created row (id = -1),
|
|
931
|
+
// - or if invalid and not editing (= not cancellable)
|
|
932
|
+
if (row.id === -1 || (!row.editing && row.invalid /*do not use !valid because if row is disabled, it will be always !valid */)) {
|
|
933
|
+
if (this.debug) console.debug(`[table] Delete row #${row.id}`);
|
|
934
|
+
row.delete();
|
|
935
|
+
this.visibleRowCount--;
|
|
936
|
+
this.totalRowCount--;
|
|
937
|
+
deletedRows.push(row);
|
|
938
|
+
return false; // Exclude from the list to delete using the service
|
|
939
|
+
}
|
|
940
|
+
// Cancel the row (and mark as pristine), when not valid but in edition
|
|
941
|
+
else if (row.editing && !row.valid) {
|
|
942
|
+
row.cancel();
|
|
943
|
+
// Mark row as pristine (if possible)
|
|
944
|
+
this.checkIfRowPristine(row, { emitEvent: false, onlySelf: true /*avoid propagation to table*/ });
|
|
945
|
+
return true; // Keep the row. the row will be deleted after the save
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
return true;
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// Apply save, only if there is still some rows to delete
|
|
952
|
+
// WARN: If no more rows (e.g. because all has been cancelled) then continue anyway to clear editedRow and selection (issue IMAGINE-669)
|
|
953
|
+
if (deletedRows.length || tempRows.length) {
|
|
954
|
+
|
|
955
|
+
// Save data (e.g. when using memory service)
|
|
956
|
+
const saved = await this.saveBeforeAction('delete');
|
|
957
|
+
if (!saved) {
|
|
958
|
+
// Stop if save cancelled or save failed
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
try {
|
|
965
|
+
|
|
966
|
+
// Apply deletion on datasource
|
|
967
|
+
// If no more rows to delete, continue anyway to clear editedRow and selection (issue IMAGINE-669)
|
|
968
|
+
if (tempRows.length) {
|
|
969
|
+
if (this.debug) console.debug(`[table] Delete ${tempRows.length} rows...`);
|
|
970
|
+
await this._dataSource.deleteAll(tempRows);
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// DO not update manually, because watchALl().subscribe() will update this count
|
|
974
|
+
//this.totalRowCount -= deleteCount;
|
|
975
|
+
//this.visibleRowCount -= deleteCount;
|
|
976
|
+
|
|
977
|
+
this.selection.clear();
|
|
978
|
+
this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
|
|
979
|
+
this.markForCheck();
|
|
980
|
+
|
|
981
|
+
this.onAfterDeletedRows.next(rows);
|
|
982
|
+
|
|
983
|
+
return rows.length;
|
|
984
|
+
} catch (err) {
|
|
985
|
+
this.setError(err && err.message || err);
|
|
986
|
+
throw err;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
async selectRowById(id: number): Promise<boolean> {
|
|
991
|
+
if (id === undefined) return false;
|
|
992
|
+
await this.waitIdle();
|
|
993
|
+
const row = this.dataSource.getRow(id);
|
|
994
|
+
if (!row) return false;
|
|
995
|
+
return this.clickRow(null, row);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* Try to select row by data. Will use dataEquals() (that call EntityUtils.equals()) to find same row's data
|
|
1000
|
+
*
|
|
1001
|
+
* @param data
|
|
1002
|
+
*/
|
|
1003
|
+
async selectRowByData(data: T): Promise<boolean> {
|
|
1004
|
+
if (data === undefined) return Promise.resolve(false);
|
|
1005
|
+
await this.waitIdle();
|
|
1006
|
+
const row = this.dataSource.getRows()
|
|
1007
|
+
.find(row => this.equals(row.currentData, data));
|
|
1008
|
+
if (!row) return false;
|
|
1009
|
+
return this.clickRow(null, row);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
async clickRow(event: Event | undefined, row: AsyncTableElement<T>): Promise<boolean> {
|
|
1013
|
+
if (this.loading) {
|
|
1014
|
+
// Wait while loading, and loop
|
|
1015
|
+
if (this.debug) console.debug('[table] Waiting before apply clickRow() (datasource is busy)...');
|
|
1016
|
+
await this.waitIdle({ timeout: 2000 });
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// DEBUG
|
|
1020
|
+
//console.debug("[table] Detect click on row");
|
|
1021
|
+
|
|
1022
|
+
// Cancelled by event
|
|
1023
|
+
if (event?.defaultPrevented) {
|
|
1024
|
+
if (this.debug) console.debug('[table] clickRow event is defaultPrevented');
|
|
1025
|
+
return false;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Already in edition
|
|
1029
|
+
if (row.id === -1 || row.editing) {
|
|
1030
|
+
if (this.debug) console.debug('[table] Row already editing. Skip clickRow event');
|
|
1031
|
+
return true;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// Open the detail page (if not inline editing)
|
|
1035
|
+
if (!this.inlineEdition) {
|
|
1036
|
+
|
|
1037
|
+
if (event) {
|
|
1038
|
+
event.stopPropagation();
|
|
1039
|
+
event.preventDefault();
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
this.markAsLoading();
|
|
1043
|
+
this.selection.clear();
|
|
1044
|
+
|
|
1045
|
+
this.openRow(row.currentData.id, row)
|
|
1046
|
+
.then(() => this.markAsLoaded())
|
|
1047
|
+
.catch(() => this.markAsLoaded());
|
|
1048
|
+
|
|
1049
|
+
return true;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// Start editing row
|
|
1053
|
+
return this.editRow(event, row, { focusColumn: undefined /*force to use the click target*/ });
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
async moveRow(id: number, direction: number) {
|
|
1057
|
+
await this.dataSource.move(id, direction);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
ready(opts?: WaitForOptions): Promise<void> {
|
|
1061
|
+
return waitForTrue(this.readySubject, opts);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
waitIdle(opts?: WaitForOptions): Promise<void> {
|
|
1065
|
+
return waitForFalse(this.loadingSubject, opts);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
async openSelectColumnsModal(event?: Event): Promise<any> {
|
|
1069
|
+
event?.preventDefault();
|
|
1070
|
+
|
|
1071
|
+
// Copy current columns (deep copy)
|
|
1072
|
+
const columns = this.getCurrentColumns();
|
|
1073
|
+
|
|
1074
|
+
const hasTopModal = !!(await this.modalCtrl.getTop());
|
|
1075
|
+
const modal = await this.modalCtrl.create({
|
|
1076
|
+
component: TableSelectColumnsComponent,
|
|
1077
|
+
componentProps: { columns },
|
|
1078
|
+
cssClass: hasTopModal && 'stack-modal'
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
// Open the modal
|
|
1082
|
+
await modal.present();
|
|
1083
|
+
|
|
1084
|
+
// On dismiss
|
|
1085
|
+
const { data } = await modal.onDidDismiss();
|
|
1086
|
+
if (!data) return; // CANCELLED
|
|
1087
|
+
|
|
1088
|
+
// Apply columns
|
|
1089
|
+
const userColumns = (data || []).filter(c => c.canHide === false || c.visible).map(c => c.name) || [];
|
|
1090
|
+
this.displayedColumns = RESERVED_START_COLUMNS.concat(userColumns).concat(RESERVED_END_COLUMNS);
|
|
1091
|
+
this.markForCheck();
|
|
1092
|
+
|
|
1093
|
+
// Update user settings
|
|
1094
|
+
await this.savePageSettings(userColumns, SETTINGS_DISPLAY_COLUMNS);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
trackByFn(index: number, row: AsyncTableElement<T>) {
|
|
1098
|
+
return row.id;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
doRefresh(event?: CompletableEvent) {
|
|
1102
|
+
this.onRefresh.emit(event);
|
|
1103
|
+
|
|
1104
|
+
// When target wait for a complete (e.g. IonRefresher)
|
|
1105
|
+
if (event?.target && event.target.complete) {
|
|
1106
|
+
setTimeout(async () => {
|
|
1107
|
+
await this.waitIdle();
|
|
1108
|
+
event.target.complete();
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
getCurrentColumns(): ColumnItem[] {
|
|
1114
|
+
const hiddenColumns = this.columns.slice(RESERVED_START_COLUMNS.length)
|
|
1115
|
+
.filter(name => this.displayedColumns.indexOf(name) === -1);
|
|
1116
|
+
return this.displayedColumns
|
|
1117
|
+
.concat(hiddenColumns)
|
|
1118
|
+
.filter(name => !RESERVED_START_COLUMNS.includes(name) && !RESERVED_END_COLUMNS.includes(name)
|
|
1119
|
+
&& !this.excludesColumns.includes(name))
|
|
1120
|
+
.map(name => ({
|
|
1121
|
+
name,
|
|
1122
|
+
label: this.getI18nColumnName(name),
|
|
1123
|
+
visible: this.displayedColumns.indexOf(name) !== -1,
|
|
1124
|
+
canHide: this.getRequiredColumns().indexOf(name) === -1
|
|
1125
|
+
}));
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
async escapeEditingRow(event?: Event, row?: AsyncTableElement<T>) {
|
|
1129
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
1130
|
+
if (!row || !row.editing) return;
|
|
1131
|
+
|
|
1132
|
+
// DEBUG
|
|
1133
|
+
//console.debug('[app-table] Cancel the row (keydown.escape)');
|
|
1134
|
+
|
|
1135
|
+
if (event) {
|
|
1136
|
+
// Avoid to cancel the editor
|
|
1137
|
+
event.preventDefault();
|
|
1138
|
+
event.stopPropagation();
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
// If new row (no id)
|
|
1142
|
+
if (row.id === -1) {
|
|
1143
|
+
if (row.validator) {
|
|
1144
|
+
// If pending: Wait end of validation, then loop
|
|
1145
|
+
if (row.pending) {
|
|
1146
|
+
await AppFormUtils.waitWhilePending(row.validator);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// Row is invalid: delete the row
|
|
1150
|
+
if (row.invalid) {
|
|
1151
|
+
await this.deleteNewRow(event, row);
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
// If the row exists (has an id)
|
|
1157
|
+
else {
|
|
1158
|
+
// need to call cancel function (if confirmation will be called before)
|
|
1159
|
+
if (this.confirmBeforeCancel) {
|
|
1160
|
+
await this.cancelExistingRow(event, row, { keepEditing: false });
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
// By default, try to confirm the row
|
|
1166
|
+
await this.confirmEditCreate(event, row);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
translateControlPath(path: string): string {
|
|
1170
|
+
// Can be overridden by subclasses, to resolve all field name
|
|
1171
|
+
|
|
1172
|
+
// Use columns key, has default name
|
|
1173
|
+
const i18nColumnKey = this.getI18nColumnName(path);
|
|
1174
|
+
return this.translate?.instant(i18nColumnKey) || i18nColumnKey;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
/* -- protected method -- */
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
protected async editRow(event: Event | undefined, row: AsyncTableElement<T>, opts?: { focusColumn?: string }): Promise<boolean> {
|
|
1181
|
+
|
|
1182
|
+
if (!this._enabled || !this.inlineEdition) return false;
|
|
1183
|
+
if (this.dataSource.getEditingRows().includes(row)) return true; // Already the edited row
|
|
1184
|
+
if (event?.defaultPrevented) return false;
|
|
1185
|
+
|
|
1186
|
+
if (!await this.confirmEditCreate()) {
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
if (!row.editing && !this.loading) {
|
|
1191
|
+
this.focusColumn = opts && opts.focusColumn || this.focusColumn;
|
|
1192
|
+
await this._dataSource.startEdit(row);
|
|
1193
|
+
}
|
|
1194
|
+
this.onStartEditingRow.emit(row);
|
|
1195
|
+
return true;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* Try to select row, by row.id, or by data. WIll use EntityUtils.equals()
|
|
1200
|
+
*
|
|
1201
|
+
* @param id
|
|
1202
|
+
* @param data
|
|
1203
|
+
* @protected
|
|
1204
|
+
*/
|
|
1205
|
+
protected async selectRowByIdOrData(id: number, data?: T): Promise<boolean> {
|
|
1206
|
+
let done = false;
|
|
1207
|
+
try {
|
|
1208
|
+
|
|
1209
|
+
// Select by row id (if NOT a new row)
|
|
1210
|
+
if (isNotNil(id) || id !== -1) {
|
|
1211
|
+
done = await this.selectRowById(id);
|
|
1212
|
+
if (done) return true;
|
|
1213
|
+
console.warn('[app-table] Save: Cannot reselect row by row.id: ', id);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// Try by data
|
|
1217
|
+
if (data) {
|
|
1218
|
+
done = await this.selectRowByData(data);
|
|
1219
|
+
if (done) return true;
|
|
1220
|
+
console.warn('[app-table] Save: Cannot reselect row by data: ', data);
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
return false;
|
|
1224
|
+
} catch (err) {
|
|
1225
|
+
// Log, but continue
|
|
1226
|
+
console.error(err && err.message || err);
|
|
1227
|
+
return false;
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
/**
|
|
1232
|
+
* return the selected row if unique in selection
|
|
1233
|
+
*/
|
|
1234
|
+
protected get singleSelectedRow(): AsyncTableElement<T> {
|
|
1235
|
+
return this.selection.selected?.length === 1 ? this.selection.selected[0] : undefined;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
protected async canDeleteRows(rows: AsyncTableElement<T>[], opts?: { interactive?: boolean }): Promise<boolean> {
|
|
1239
|
+
|
|
1240
|
+
// Check using emitter
|
|
1241
|
+
if (this.onBeforeDeleteRows.observers.length > 0) {
|
|
1242
|
+
try {
|
|
1243
|
+
const canDelete = await emitPromiseEvent(this.onBeforeDeleteRows, 'canDelete', {
|
|
1244
|
+
detail: { rows }
|
|
1245
|
+
});
|
|
1246
|
+
if (!canDelete) return false;
|
|
1247
|
+
} catch (err) {
|
|
1248
|
+
if (err === 'CANCELLED') return false; // User cancel
|
|
1249
|
+
console.error('Error while checking if can delete rows', err);
|
|
1250
|
+
throw err;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// Ask user confirmation
|
|
1255
|
+
if (this.confirmBeforeDelete && (!opts || opts.interactive !== false)) {
|
|
1256
|
+
return this.askDeleteConfirmation(null, rows);
|
|
1257
|
+
}
|
|
1258
|
+
return true;
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
protected async canCancelRows(rows?: AsyncTableElement<T>[], opts?: { interactive?: boolean }): Promise<boolean> {
|
|
1262
|
+
|
|
1263
|
+
// Get dirty rows
|
|
1264
|
+
rows = rows || this.dataSource.getRows().filter(row => row.validator?.dirty);
|
|
1265
|
+
|
|
1266
|
+
if (isEmptyArray(rows)) return true; // No dirty: OK
|
|
1267
|
+
|
|
1268
|
+
// Check using emitter
|
|
1269
|
+
if (this.onBeforeCancelRows.observers.length > 0) {
|
|
1270
|
+
try {
|
|
1271
|
+
const isCancel = await emitPromiseEvent(this.onBeforeCancelRows, 'canCancel', {
|
|
1272
|
+
detail: { rows }
|
|
1273
|
+
});
|
|
1274
|
+
if (!isCancel) return false;
|
|
1275
|
+
} catch (err) {
|
|
1276
|
+
if (err === 'CANCELLED') return false; // User cancel
|
|
1277
|
+
console.error('Error while checking if can cancel rows', err);
|
|
1278
|
+
throw err;
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
// Ask user confirmation
|
|
1283
|
+
if (this.confirmBeforeCancel && (!opts || opts.interactive !== false)) {
|
|
1284
|
+
return this.askCancelConfirmation(null, rows);
|
|
1285
|
+
}
|
|
1286
|
+
return true;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
protected async saveBeforeAction(saveAction: SaveActionType): Promise<boolean> {
|
|
1290
|
+
|
|
1291
|
+
if (!this.dirty) {
|
|
1292
|
+
// Continue without save
|
|
1293
|
+
return true;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
let save: boolean;
|
|
1297
|
+
switch (saveAction) {
|
|
1298
|
+
case 'delete':
|
|
1299
|
+
save = this.saveBeforeDelete;
|
|
1300
|
+
break;
|
|
1301
|
+
case 'filter':
|
|
1302
|
+
save = this.saveBeforeFilter;
|
|
1303
|
+
break;
|
|
1304
|
+
case 'sort':
|
|
1305
|
+
save = this.saveBeforeSort;
|
|
1306
|
+
break;
|
|
1307
|
+
default:
|
|
1308
|
+
save = true;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// Default behavior
|
|
1312
|
+
let confirmed = true;
|
|
1313
|
+
|
|
1314
|
+
if (save) {
|
|
1315
|
+
if (this.onBeforeSave.observers.length > 0) {
|
|
1316
|
+
// Ask confirmation
|
|
1317
|
+
try {
|
|
1318
|
+
const res = await emitPromiseEvent(this.onBeforeSave, 'beforeSave', {
|
|
1319
|
+
detail: { action: saveAction, valid: this.valid }
|
|
1320
|
+
});
|
|
1321
|
+
confirmed = res.confirmed;
|
|
1322
|
+
save = res.save;
|
|
1323
|
+
} catch (err) {
|
|
1324
|
+
if (err === 'CANCELLED') return false; // User cancel
|
|
1325
|
+
console.error('Error while checking if can delete rows', err);
|
|
1326
|
+
throw err;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
if (confirmed) {
|
|
1333
|
+
if (save) {
|
|
1334
|
+
// User confirmed save
|
|
1335
|
+
const saved = await this.save();
|
|
1336
|
+
this.markAsDirty(); // Restore dirty flag
|
|
1337
|
+
return saved;
|
|
1338
|
+
}
|
|
1339
|
+
return true; // No save but continue action
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
return false; // User cancel the action
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Open a row detail view. By default, will to open row detail page.
|
|
1347
|
+
* Can be overridden by subclasses, BUT prefer to subscribe on onOpenRow
|
|
1348
|
+
*
|
|
1349
|
+
* @param id
|
|
1350
|
+
* @param row
|
|
1351
|
+
* @protected
|
|
1352
|
+
*/
|
|
1353
|
+
protected async openRow(id: ID, row: AsyncTableElement<T>): Promise<boolean> {
|
|
1354
|
+
if (this.allowRowDetail) {
|
|
1355
|
+
if (this.debug && this.dirty) {
|
|
1356
|
+
console.warn('[table] Opening row details, but table has unsaved changes!');
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
if (this.onOpenRow.observers.length) {
|
|
1360
|
+
this.onOpenRow.emit(row);
|
|
1361
|
+
return true;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
// No ID defined: unable to open details
|
|
1365
|
+
if (isNil(id)) {
|
|
1366
|
+
console.warn('[table] Opening row details, but data has no id!');
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
return this.router.navigate(['.', id.toString()], {
|
|
1371
|
+
relativeTo: this.route,
|
|
1372
|
+
queryParams: {}
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
return false;
|
|
1376
|
+
}
|
|
1377
|
+
|
|
1378
|
+
protected async openNewRowDetail(event?: any): Promise<boolean> {
|
|
1379
|
+
if (!this.allowRowDetail) return false;
|
|
1380
|
+
|
|
1381
|
+
if (this.onNewRow.observers.length > 0) {
|
|
1382
|
+
this.onNewRow.emit(event);
|
|
1383
|
+
return true;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
return await this.router.navigate(['new'], {
|
|
1387
|
+
relativeTo: this.route
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// can be overridden to add more required columns
|
|
1392
|
+
protected getRequiredColumns() {
|
|
1393
|
+
return DEFAULT_REQUIRED_COLUMNS;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
protected getUserColumns(): string[] {
|
|
1397
|
+
return this.getPageSettings(SETTINGS_DISPLAY_COLUMNS);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
protected getSortedColumn(): MatSortable {
|
|
1401
|
+
const data = this.getPageSettings(SETTINGS_SORTED_COLUMN);
|
|
1402
|
+
const parts = data && data.split(':');
|
|
1403
|
+
if (parts && parts.length === 2 && this.columns.includes(parts[0])) {
|
|
1404
|
+
return { id: parts[0], start: parts[1] === 'desc' ? 'desc' : 'asc', disableClear: false };
|
|
1405
|
+
}
|
|
1406
|
+
if (this.defaultSortBy) {
|
|
1407
|
+
return { id: this.defaultSortBy, start: this.defaultSortDirection || 'asc', disableClear: false };
|
|
1408
|
+
}
|
|
1409
|
+
return { id: 'id', start: 'asc', disableClear: false };
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
protected getPageSize(): number {
|
|
1413
|
+
const pageSize = this.getPageSettings<number>(SETTINGS_PAGE_SIZE);
|
|
1414
|
+
return pageSize || this.defaultPageSize;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
protected getDisplayColumns(): string[] {
|
|
1418
|
+
let userColumns = this.getUserColumns();
|
|
1419
|
+
|
|
1420
|
+
// No user override
|
|
1421
|
+
if (!userColumns) {
|
|
1422
|
+
// Return default, without columns to hide
|
|
1423
|
+
return this.columns.filter(column => !this.excludesColumns.includes(column));
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
// Get fixed start columns
|
|
1427
|
+
const fixedStartColumns = this.columns.filter(c => RESERVED_START_COLUMNS.includes(c));
|
|
1428
|
+
|
|
1429
|
+
// Remove end columns
|
|
1430
|
+
const fixedEndColumns = this.columns.filter(c => RESERVED_END_COLUMNS.includes(c));
|
|
1431
|
+
|
|
1432
|
+
// Remove fixed columns from user columns
|
|
1433
|
+
userColumns = userColumns.filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && this.columns.includes(c));
|
|
1434
|
+
|
|
1435
|
+
// Add required columns if missing
|
|
1436
|
+
userColumns.push(...this.getRequiredColumns().filter(c => !fixedStartColumns.includes(c) && !fixedEndColumns.includes(c) && !userColumns.includes(c)));
|
|
1437
|
+
|
|
1438
|
+
return fixedStartColumns
|
|
1439
|
+
.concat(userColumns)
|
|
1440
|
+
.concat(fixedEndColumns)
|
|
1441
|
+
// Remove columns to hide
|
|
1442
|
+
.filter(column => !this.excludesColumns.includes(column));
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* Recompute display columns
|
|
1447
|
+
*
|
|
1448
|
+
* @protected
|
|
1449
|
+
*/
|
|
1450
|
+
protected updateColumns() {
|
|
1451
|
+
this.displayedColumns = this.getDisplayColumns();
|
|
1452
|
+
if (!this.loading) this.markForCheck();
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
protected registerSubscription(sub: Subscription) {
|
|
1456
|
+
this._subscription.add(sub);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
protected unregisterSubscription(sub: Subscription) {
|
|
1460
|
+
this._subscription.remove(sub);
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
protected registerAutocompleteField<E = any, EF = any>(fieldName: string, options?: MatAutocompleteFieldAddOptions<E, EF>): MatAutocompleteFieldConfig<E, EF> {
|
|
1464
|
+
return this._autocompleteConfigHolder.add(fieldName, options);
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
protected getI18nColumnName(columnName: string) {
|
|
1468
|
+
return (this.i18nColumnPrefix || '') + changeCaseToUnderscore(columnName).toUpperCase();
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
protected generateTableId() {
|
|
1472
|
+
// noinspection JSNonASCIINames
|
|
1473
|
+
const id = this.location.path(true)
|
|
1474
|
+
.replace(/[?].*$/g, '')
|
|
1475
|
+
.replace(/\/\d+/g, '_id')
|
|
1476
|
+
+ '_'
|
|
1477
|
+
// Get a component unique name - See https://stackoverflow.com/questions/60114682/how-to-access-components-unique-encapsulation-id-in-angular-9
|
|
1478
|
+
+ (this.constructor['ɵcmp']?.id || this.constructor.name);
|
|
1479
|
+
//if (this.debug) console.debug("[table] id = " + id);
|
|
1480
|
+
return id;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
protected async addRowToTable(insertAt?: number, opts?: { focusColumn?: string; editing?: boolean; emitEvent?: boolean }): Promise<AsyncTableElement<T> | undefined> {
|
|
1484
|
+
// Try to finish edited row first
|
|
1485
|
+
if (!await this.confirmEditCreate()) {
|
|
1486
|
+
console.warn('[table] Cannot add new row, because the previous edited row cannot be confirmed');
|
|
1487
|
+
return undefined;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
const editing = this.inlineEdition && (!opts || opts.editing !== false); // true by default, if inlineEdition
|
|
1491
|
+
|
|
1492
|
+
const row = await this._dataSource.createNew(insertAt, { editing });
|
|
1493
|
+
if (!row) return undefined;
|
|
1494
|
+
|
|
1495
|
+
if (row.editing) {
|
|
1496
|
+
// Update focused column
|
|
1497
|
+
this.focusFirstColumn = true;
|
|
1498
|
+
this.focusColumn = opts?.focusColumn || this.firstUserColumn;
|
|
1499
|
+
|
|
1500
|
+
// Emit start editing event
|
|
1501
|
+
this.onStartEditingRow.emit(row);
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
this.totalRowCount++;
|
|
1505
|
+
this.visibleRowCount++;
|
|
1506
|
+
|
|
1507
|
+
this.markAsDirty({ emitEvent: false /*markForCheck() is called just after*/ });
|
|
1508
|
+
|
|
1509
|
+
// Emit event
|
|
1510
|
+
if (!opts || opts.emitEvent !== false) this.markForCheck();
|
|
1511
|
+
|
|
1512
|
+
return row;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
protected registerCellValueChanges(name: string, formPath?: string, emitInitialValue?: boolean): Observable<any> {
|
|
1516
|
+
formPath = formPath || name;
|
|
1517
|
+
emitInitialValue = emitInitialValue || false;
|
|
1518
|
+
let def = this._cellValueChangesDefs[name];
|
|
1519
|
+
if (def && (def.formPath !== formPath || def.emitInitialValue !== emitInitialValue)) {
|
|
1520
|
+
throw Error('Already register a cell value change for this name, with different \'formPath\' or \'emitInitialValue\'. Please use same arguments.');
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
// Not exists: register new definition
|
|
1524
|
+
if (!def) {
|
|
1525
|
+
if (this.debug) console.debug(`[table] New listener {${name}} for value changes on path ${formPath}`);
|
|
1526
|
+
def = {
|
|
1527
|
+
subject: new Subject<any>(),
|
|
1528
|
+
subscription: null,
|
|
1529
|
+
formPath,
|
|
1530
|
+
emitInitialValue
|
|
1531
|
+
};
|
|
1532
|
+
this._cellValueChangesDefs[name] = def;
|
|
1533
|
+
|
|
1534
|
+
// Start the listener, when editing starts
|
|
1535
|
+
this.registerSubscription(
|
|
1536
|
+
this.onStartEditingRow.subscribe(row => this.startCellValueChanges(name, row)));
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
return def.subject;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
protected setShowColumn(columnName: string, show: boolean, opts?: { emitEvent?: boolean }) {
|
|
1543
|
+
if (!this.excludesColumns.includes(columnName) !== show) {
|
|
1544
|
+
if (!show) {
|
|
1545
|
+
this.excludesColumns.push(columnName);
|
|
1546
|
+
} else {
|
|
1547
|
+
const index = this.excludesColumns.findIndex(value => value === columnName);
|
|
1548
|
+
if (index >= 0) this.excludesColumns.splice(index, 1);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
// Recompute display columns
|
|
1552
|
+
if (this.displayedColumns && (!opts || opts.emitEvent !== false)) {
|
|
1553
|
+
this.updateColumns();
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
protected getShowColumn(columnName: string): boolean {
|
|
1559
|
+
return !this.excludesColumns.includes(columnName);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
protected startsWithUpperCase(input: string, search: string): boolean {
|
|
1563
|
+
return input && input.toUpperCase().startsWith(search);
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
protected markForCheck() {
|
|
1567
|
+
// Should be overridden by subclasses, depending on ChangeDetectionStrategy
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
protected async askDeleteConfirmation(event?: Event, rows?: AsyncTableElement<T>[]): Promise<boolean> {
|
|
1571
|
+
if (this.undoableDeletion) {
|
|
1572
|
+
// Special message, for undoable deletion
|
|
1573
|
+
return Alerts.askConfirmation(rows?.length === 1 ? 'CONFIRM.DELETE_ROW' : 'CONFIRM.DELETE_ROWS', this.alertCtrl, this.translate, event);
|
|
1574
|
+
}
|
|
1575
|
+
// Immediate deletion action
|
|
1576
|
+
return Alerts.askActionConfirmation(this.alertCtrl, this.translate, true, event);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
protected async askCancelConfirmation(event?: Event, rows?: AsyncTableElement<T>[]): Promise<boolean> {
|
|
1580
|
+
return Alerts.askConfirmation(rows?.length === 1 ? 'CONFIRM.CANCEL_ROW' : 'CONFIRM.CANCEL_ROWS', this.alertCtrl, this.translate, event);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
protected async askRestoreConfirmation(event?: Event): Promise<boolean> {
|
|
1584
|
+
return Alerts.askActionConfirmation(this.alertCtrl, this.translate, false, event);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
protected async showToast(opts: ShowToastOptions) {
|
|
1588
|
+
if (!this.toastController) throw new Error('Missing toastController in component\'s constructor');
|
|
1589
|
+
return Toasts.show(this.toastController, this.translate, opts);
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
protected resetError(opts?: { emitEvent?: boolean }) {
|
|
1593
|
+
this.setError(undefined, opts);
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
protected getRowError(row?: AsyncTableElement<T>, opts?: FormErrorTranslatorOptions): string {
|
|
1597
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
1598
|
+
if (!row || !this.formErrorAdapter) return undefined;
|
|
1599
|
+
|
|
1600
|
+
return this.formErrorAdapter.translateFormErrors(row.validator, {
|
|
1601
|
+
...this.errorTranslatorOptions,
|
|
1602
|
+
...opts
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
protected setError(value: string, opts?: { emitEvent?: boolean }) {
|
|
1607
|
+
if (this.errorSubject.value !== value) {
|
|
1608
|
+
this.errorSubject.next(value);
|
|
1609
|
+
if (!opts || opts.emitEvent !== false) {
|
|
1610
|
+
this.markForCheck();
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
/**
|
|
1616
|
+
* Compare data equality (default by id)
|
|
1617
|
+
* Can be overridden to add additional properties to compare
|
|
1618
|
+
*
|
|
1619
|
+
* @param d1
|
|
1620
|
+
* @param d2
|
|
1621
|
+
* @protected
|
|
1622
|
+
*/
|
|
1623
|
+
protected equals(d1: T, d2: T): boolean {
|
|
1624
|
+
return EntityUtils.equals(d1, d2, 'id');
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
protected markRowAsDirty(row?: AsyncTableElement<T>, opts?: { onlySelf?: boolean; emitEVent?: boolean }) {
|
|
1628
|
+
row = row || this.dataSource.getSingleEditingRow();
|
|
1629
|
+
if (row) row.validator?.markAsDirty(opts);
|
|
1630
|
+
this.markAsDirty(opts);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
protected getPageSettings<T = any>(propertyName?: string): T {
|
|
1634
|
+
return this.settings.getPageSettings(this.settingsId, propertyName);
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
protected async savePageSettings(value: any, propertyName?: string) {
|
|
1638
|
+
await this.settings.savePageSetting(this.settingsId, value, propertyName);
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
/* -- private method -- */
|
|
1642
|
+
|
|
1643
|
+
private async listenSortAndPaginationEvents() {
|
|
1644
|
+
|
|
1645
|
+
if (!this.table) {
|
|
1646
|
+
|
|
1647
|
+
// DEBUG only -- alert user that table not found in template
|
|
1648
|
+
if (this.debug) {
|
|
1649
|
+
setTimeout(() => !this.table && console.warn(`[table] Missing <mat-table> in the HTML template (after waiting 500ms)! Component: ${this.constructor.name}`), 500);
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
// Make sure to wait the table
|
|
1653
|
+
await waitFor(() => !!this.table, { stop: this.destroySubject, stopError: false/*avoid error when destorying the table*/ });
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
this.registerSubscription(
|
|
1657
|
+
merge(
|
|
1658
|
+
// Listen sort events
|
|
1659
|
+
this.sort && this.sort.sortChange
|
|
1660
|
+
.pipe(
|
|
1661
|
+
filter(() => !this.sort.disabled),
|
|
1662
|
+
mergeMap(async () => this.saveBeforeAction('sort')),
|
|
1663
|
+
filter(res => res === true),
|
|
1664
|
+
// Save sort in settings
|
|
1665
|
+
tap(() => {
|
|
1666
|
+
const value = [this.sort.active, this.sort.direction || 'asc'].join(':');
|
|
1667
|
+
this.savePageSettings(value, SETTINGS_SORTED_COLUMN);
|
|
1668
|
+
})
|
|
1669
|
+
)
|
|
1670
|
+
|| EMPTY,
|
|
1671
|
+
|
|
1672
|
+
// Listen paginator events
|
|
1673
|
+
this.paginator && this.paginator.page
|
|
1674
|
+
.pipe(
|
|
1675
|
+
mergeMap((_) => this.saveBeforeAction('sort')),
|
|
1676
|
+
filter(saved => saved === true),
|
|
1677
|
+
// Save page size in settings
|
|
1678
|
+
tap(() => this.savePageSettings(this.paginator.pageSize, SETTINGS_PAGE_SIZE))
|
|
1679
|
+
) || EMPTY
|
|
1680
|
+
)
|
|
1681
|
+
// Refresh on any sort or paginator events
|
|
1682
|
+
.subscribe(value => {
|
|
1683
|
+
this.onSort.emit(value);
|
|
1684
|
+
this.onRefresh.emit(value);
|
|
1685
|
+
})
|
|
1686
|
+
);
|
|
1687
|
+
|
|
1688
|
+
// If the user changes the sort order, reset back to the first page.
|
|
1689
|
+
if (this.sort && this.paginator) {
|
|
1690
|
+
this.registerSubscription(
|
|
1691
|
+
this.sort.sortChange
|
|
1692
|
+
.pipe(
|
|
1693
|
+
filter(() => !this.sort.disabled)
|
|
1694
|
+
)
|
|
1695
|
+
.subscribe(() => this.paginator.pageIndex = 0)
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
private async editRowById(event: Event | undefined, id: number, opts?: { focusColumn?: string }) {
|
|
1701
|
+
if (id < 0) return;
|
|
1702
|
+
if (id >= this.visibleRowCount) {
|
|
1703
|
+
await this.addRow(event, undefined, { ...opts, editing: true });
|
|
1704
|
+
} else {
|
|
1705
|
+
const row = await this.dataSource.getRow(id);
|
|
1706
|
+
await this.editRow(event, row, opts);
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
private setLoading(value: boolean, opts?: { emitEvent?: boolean }) {
|
|
1711
|
+
if (this.loadingSubject.value !== value) {
|
|
1712
|
+
this.loadingSubject.next(value);
|
|
1713
|
+
|
|
1714
|
+
if (!opts || opts.emitEvent !== false) {
|
|
1715
|
+
this.markForCheck();
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
private async deleteNewRow(event: Event | undefined, row: AsyncTableElement<T>) {// Make sure row will be cancelled, and NOT deleted
|
|
1721
|
+
if (row.id !== -1) throw new Error('Row must have id = -1');
|
|
1722
|
+
event?.stopPropagation();
|
|
1723
|
+
|
|
1724
|
+
this.selection.clear();
|
|
1725
|
+
await this._dataSource.cancelOrDelete(row);
|
|
1726
|
+
this.onCancelOrDeleteRow.next(row);
|
|
1727
|
+
this.resetError();
|
|
1728
|
+
this.totalRowCount--;
|
|
1729
|
+
this.visibleRowCount--;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
private async deleteExistingRow(event: Event | null, row: AsyncTableElement<T>, opts?: { interactive?: boolean }) {
|
|
1733
|
+
// Make sure row will be cancelled, and NOT deleted
|
|
1734
|
+
if (row.id === -1) throw new Error('Row must have an id');
|
|
1735
|
+
|
|
1736
|
+
if (event?.defaultPrevented) return 0; // SKip
|
|
1737
|
+
event?.preventDefault();
|
|
1738
|
+
|
|
1739
|
+
await this.deleteRow(null, row, opts);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
private async cancelExistingRow(event: Event | undefined, row: AsyncTableElement<T>, opts?: { interactive?: boolean; keepEditing?: boolean }) {
|
|
1743
|
+
// Make sure row will be cancelled, and NOT deleted
|
|
1744
|
+
if (row.id === -1 || !row.editing) throw new Error('Row cannot be canceling, but only deleting');
|
|
1745
|
+
|
|
1746
|
+
const confirmed = (!opts || opts.interactive !== false);
|
|
1747
|
+
|
|
1748
|
+
// Ask user confirmation, if cancel
|
|
1749
|
+
if (!confirmed && row.dirty && (this.confirmBeforeCancel || this.onBeforeCancelRows.observers.length > 0)) {
|
|
1750
|
+
event?.stopPropagation();
|
|
1751
|
+
if (!await this.canCancelRows([row], opts)) {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
const keepEditing = row.editing && (!opts || opts.keepEditing !== false);
|
|
1757
|
+
await this._dataSource.cancelOrDelete(row);
|
|
1758
|
+
this.onCancelOrDeleteRow.next(row);
|
|
1759
|
+
|
|
1760
|
+
// Mark row as pristine
|
|
1761
|
+
await this.checkIfRowPristine(row);
|
|
1762
|
+
|
|
1763
|
+
// Restore editing state
|
|
1764
|
+
if (keepEditing) {
|
|
1765
|
+
await this.editRow(undefined, row);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
private async checkIfRowPristine(row: AsyncTableElement<T>, opts?: { emitEvent?: boolean; onlySelf?: boolean }) {
|
|
1770
|
+
// Mark row as pristine
|
|
1771
|
+
const markRowAsPristine = this.dataSource?.config.restoreOriginalDataOnCancel === true;
|
|
1772
|
+
if (markRowAsPristine) {
|
|
1773
|
+
row.validator?.markAsPristine();
|
|
1774
|
+
|
|
1775
|
+
// Check if table is now pristine
|
|
1776
|
+
if (!opts || opts.onlySelf !== true) {
|
|
1777
|
+
await this.checkIfPristine(opts);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
private async checkIfPristine(opts?: { emitEvent?: boolean }) {
|
|
1783
|
+
if (!this.dirty) return; // Already pristine
|
|
1784
|
+
|
|
1785
|
+
const rows = this._dataSource.getRows();
|
|
1786
|
+
const pristine = (rows || []).findIndex(row => row.dirty) === -1;
|
|
1787
|
+
if (pristine) this.markAsPristine(opts);
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
private applyFilter(filter: F, opts: { emitEvent?: boolean }) {
|
|
1791
|
+
if (this.debug) console.debug('[table] Applying filter', filter);
|
|
1792
|
+
this._filter = filter;
|
|
1793
|
+
if (opts && opts.emitEvent) {
|
|
1794
|
+
if (this.paginator && this.paginator.pageIndex > 0) {
|
|
1795
|
+
this.paginator.pageIndex = 0;
|
|
1796
|
+
}
|
|
1797
|
+
this.onRefresh.emit();
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
private listenDatasourceLoading(dataSource: EntitiesAsyncTableDataSource<T, F, ID>) {
|
|
1802
|
+
if (!dataSource) throw new Error('[table] dataSource not set !');
|
|
1803
|
+
|
|
1804
|
+
// Cleaning previous subscription on datasource
|
|
1805
|
+
if (isNotNil(this._dataSourceLoadingSubscription)) {
|
|
1806
|
+
if (this.debug) console.debug('[table] Many call to listenDatasource(): Cleaning previous subscriptions...');
|
|
1807
|
+
this._dataSourceLoadingSubscription.unsubscribe();
|
|
1808
|
+
this.unregisterSubscription(this._dataSourceLoadingSubscription);
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
// Propage loading to table
|
|
1812
|
+
this._dataSourceLoadingSubscription = this._dataSource.loadingSubject
|
|
1813
|
+
.pipe(
|
|
1814
|
+
distinctUntilChanged(),
|
|
1815
|
+
|
|
1816
|
+
// If changed to True: propagate as soon as possible
|
|
1817
|
+
tap((loading) => loading && this.setLoading(true)),
|
|
1818
|
+
|
|
1819
|
+
// If changed to False: wait 250ms before propagate (to make sure the spinner has been displayed)
|
|
1820
|
+
debounceTime(250),
|
|
1821
|
+
tap(loading => !loading && this.setLoading(false))
|
|
1822
|
+
)
|
|
1823
|
+
.subscribe();
|
|
1824
|
+
this.registerSubscription(this._dataSourceLoadingSubscription);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
|
|
1828
|
+
private startCellValueChanges(name: string, row: AsyncTableElement<T>) {
|
|
1829
|
+
const def = this._cellValueChangesDefs[name];
|
|
1830
|
+
if (!def) {
|
|
1831
|
+
console.warn('[table] Listener with name {' + name + '} not registered! Please call registerCellValueChanges() before;');
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1834
|
+
// Stop previous subscription
|
|
1835
|
+
if (def.subscription) {
|
|
1836
|
+
def.subscription.unsubscribe();
|
|
1837
|
+
def.subscription = null;
|
|
1838
|
+
} else {
|
|
1839
|
+
if (this.debug) console.debug(`[table] Start values changes on row path {${def.formPath}}`);
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
// Listen value changes, and redirect to event emitter
|
|
1843
|
+
const control = row.validator && AppFormUtils.getControlFromPath(row.validator, def.formPath);
|
|
1844
|
+
if (!control) {
|
|
1845
|
+
console.warn(`[table] Could not listen cell changes: no validator or invalid form path {${def.formPath}}`);
|
|
1846
|
+
} else {
|
|
1847
|
+
def.subscription = control.valueChanges
|
|
1848
|
+
.pipe(
|
|
1849
|
+
// don't emit if control is disabled
|
|
1850
|
+
filter(() => control.enabled)
|
|
1851
|
+
)
|
|
1852
|
+
.subscribe((value) => def.subject.next(value));
|
|
1853
|
+
|
|
1854
|
+
// Emit the actual value
|
|
1855
|
+
if (def.emitInitialValue !== false) {
|
|
1856
|
+
def.subject.next(control.value);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
private stopCellValueChanges(name: string, destroy?: boolean) {
|
|
1862
|
+
const def = this._cellValueChangesDefs[name];
|
|
1863
|
+
if (!def) return;
|
|
1864
|
+
if (def.subscription) {
|
|
1865
|
+
if (this.debug) console.debug('[table] Stop value changes on row path {' + def.formPath + '}');
|
|
1866
|
+
def.subscription.unsubscribe();
|
|
1867
|
+
def.subscription = null;
|
|
1868
|
+
}
|
|
1869
|
+
if (destroy && def.subject) {
|
|
1870
|
+
def.subject.complete();
|
|
1871
|
+
def.subject.unsubscribe();
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
/**
|
|
1876
|
+
* Initialize the permanent selection model
|
|
1877
|
+
* @protected
|
|
1878
|
+
*/
|
|
1879
|
+
private initPermanentSelection() {
|
|
1880
|
+
if (this.permanentSelection) throw new Error('initPermanentSelection() already called!');
|
|
1881
|
+
|
|
1882
|
+
this.permanentSelection = new SelectionModel<T>(true, []);
|
|
1883
|
+
|
|
1884
|
+
// Listen sort change
|
|
1885
|
+
this.registerSubscription(
|
|
1886
|
+
this.onSort.subscribe(() => (this.permanentSelectionChangedPrevented = true)) // prevent selection change on sort
|
|
1887
|
+
);
|
|
1888
|
+
|
|
1889
|
+
// Listen datasource update
|
|
1890
|
+
this.registerSubscription(
|
|
1891
|
+
this.dataSource.rowsSubject
|
|
1892
|
+
// restore the 'adding' selection (for example after a page or sort change)
|
|
1893
|
+
.subscribe((rows) => {
|
|
1894
|
+
this.permanentSelectionChangedPrevented = true;
|
|
1895
|
+
try {
|
|
1896
|
+
const permanentSelectionIds = (this.permanentSelection.selected || []).map(EntityUtils.getId);
|
|
1897
|
+
this.selection.setSelection(...rows.filter((row) => permanentSelectionIds.includes(AppTableUtils.getEntityId(row))));
|
|
1898
|
+
this.markForCheck();
|
|
1899
|
+
}
|
|
1900
|
+
finally {
|
|
1901
|
+
this.permanentSelectionChangedPrevented = false;
|
|
1902
|
+
}
|
|
1903
|
+
})
|
|
1904
|
+
);
|
|
1905
|
+
|
|
1906
|
+
// Listen selection change
|
|
1907
|
+
this.registerSubscription(
|
|
1908
|
+
this.selection.changed
|
|
1909
|
+
.pipe(filter(() => !this.permanentSelectionChangedPrevented))
|
|
1910
|
+
.subscribe((selectionChange) => {
|
|
1911
|
+
// add to selection
|
|
1912
|
+
if (selectionChange.added.length) {
|
|
1913
|
+
this.permanentSelection.setSelection(
|
|
1914
|
+
...(this.permanentSelection.selected || [])
|
|
1915
|
+
// Add new elements
|
|
1916
|
+
.concat(...AppTableUtils.getEntities(selectionChange.added))
|
|
1917
|
+
// Avoid duplicated entities (Mantis #55351)
|
|
1918
|
+
.filter(EntityUtils.arrayDistinctFilterFn)
|
|
1919
|
+
);
|
|
1920
|
+
}
|
|
1921
|
+
// remove from selection
|
|
1922
|
+
if (selectionChange.removed.length) {
|
|
1923
|
+
const removedIds = AppTableUtils.getEntityIds(selectionChange.removed);
|
|
1924
|
+
this.permanentSelection.setSelection(
|
|
1925
|
+
...(this.permanentSelection.selected || [])
|
|
1926
|
+
.filter((entity) => !removedIds.includes(entity.id))
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
this.markForCheck();
|
|
1930
|
+
})
|
|
1931
|
+
);
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
|