From 7b4fe0112273beb082ca5ecb80918804a6d61c0a Mon Sep 17 00:00:00 2001 From: akoulalis Date: Wed, 10 Mar 2021 16:17:49 +0000 Subject: [PATCH] --- _fonts.scss | 35 + _general.scss | 1263 +++++++++++++++++ _media.scss | 32 + _pallete.scss | 65 + app/app-routing.module.ts | 10 + app/app.component.html | 9 + app/app.component.scss | 1 + app/app.component.spec.ts | 35 + app/app.component.ts | 19 + app/app.module.ts | 61 + app/core/core.module.ts | 25 + .../error-handling/error-handling.module.ts | 15 + .../error-handling/global-error-handler.ts | 21 + .../error-handling/http-error.interceptor.ts | 34 + app/core/header/header.component.html | 14 + app/core/header/header.component.scss | 1 + app/core/header/header.component.spec.ts | 25 + app/core/header/header.component.ts | 28 + app/core/main-page/main-page.component.html | 1 + app/core/main-page/main-page.component.scss | 1 + .../main-page/main-page.component.spec.ts | 25 + app/core/main-page/main-page.component.ts | 22 + .../administration.component.html | 26 + .../administration.component.scss | 1 + .../administration.component.spec.ts | 25 + .../administration.component.ts | 103 ++ .../application-level-dialog.component.html | 18 + .../application-level-dialog.component.scss | 13 + ...application-level-dialog.component.spec.ts | 25 + .../application-level-dialog.component.ts | 24 + ...pplication-level-exceptions.component.html | 29 + ...pplication-level-exceptions.component.scss | 1 + ...ication-level-exceptions.component.spec.ts | 25 + .../application-level-exceptions.component.ts | 33 + ...plication-level-search-form.component.html | 14 + ...plication-level-search-form.component.scss | 1 + ...cation-level-search-form.component.spec.ts | 25 + ...application-level-search-form.component.ts | 59 + .../application-level-table.component.html | 54 + .../application-level-table.component.scss | 1 + .../application-level-table.component.spec.ts | 25 + .../application-level-table.component.ts | 64 + .../categories-management.component.html | 53 + .../categories-management.component.scss | 1 + .../categories-management.component.spec.ts | 25 + .../categories-management.component.ts | 59 + .../categories-search-results.component.html | 64 + .../categories-search-results.component.scss | 1 + ...ategories-search-results.component.spec.ts | 25 + .../categories-search-results.component.ts | 103 ++ .../categories-search.component.html | 15 + .../categories-search.component.scss | 1 + .../categories-search.component.spec.ts | 25 + .../categories-search.component.ts | 101 ++ .../create-category-dialog.component.html | 33 + .../create-category-dialog.component.scss | 1 + .../create-category-dialog.component.spec.ts | 25 + .../create-category-dialog.component.ts | 86 ++ .../configurator-edit-value.component.html | 3 + .../configurator-edit-value.component.scss | 1 + .../configurator-edit-value.component.spec.ts | 25 + .../configurator-edit-value.component.ts | 28 + ...igurator-list-of-parameters.component.html | 38 + ...igurator-list-of-parameters.component.scss | 1 + ...rator-list-of-parameters.component.spec.ts | 25 + ...nfigurator-list-of-parameters.component.ts | 40 + .../configurator/configurator.component.html | 27 + .../configurator/configurator.component.scss | 1 + .../configurator.component.spec.ts | 25 + .../configurator/configurator.component.ts | 51 + .../application-level-form.component.html | 101 ++ .../application-level-form.component.scss | 1 + .../application-level-form.component.spec.ts | 25 + .../application-level-form.component.ts | 111 ++ .../category-form.component.html | 72 + .../category-form.component.scss | 1 + .../category-form.component.spec.ts | 25 + .../category-form/category-form.component.ts | 183 +++ .../configurator-form.component.html | 60 + .../configurator-form.component.scss | 1 + .../configurator-form.component.spec.ts | 25 + .../configurator-form.component.ts | 69 + .../template-form.component.html | 138 ++ .../template-form.component.scss | 1 + .../template-form.component.spec.ts | 25 + .../template-form/template-form.component.ts | 369 +++++ ...-verification-rule-form-value.interface.ts | 16 + .../verification-rule-form.component.html | 200 +++ .../verification-rule-form.component.scss | 1 + .../verification-rule-form.component.spec.ts | 25 + .../verification-rule-form.component.ts | 527 +++++++ ...cation-rule-search-form-value.interface.ts | 6 + ...rification-rule-search-form.component.html | 93 ++ ...rification-rule-search-form.component.scss | 1 + ...ication-rule-search-form.component.spec.ts | 25 + ...verification-rule-search-form.component.ts | 358 +++++ .../create-template-dialog.component.html | 30 + .../create-template-dialog.component.scss | 1 + .../create-template-dialog.component.spec.ts | 25 + .../create-template-dialog.component.ts | 92 ++ .../templates-management.component.html | 50 + .../templates-management.component.scss | 1 + .../templates-management.component.spec.ts | 25 + .../templates-management.component.ts | 58 + .../templates-search-results.component.html | 62 + .../templates-search-results.component.scss | 1 + ...templates-search-results.component.spec.ts | 25 + .../templates-search-results.component.ts | 103 ++ .../templates-search.component.html | 15 + .../templates-search.component.scss | 2 + .../templates-search.component.spec.ts | 25 + .../templates-search.component.ts | 111 ++ ...te-verification-rule-dialog.component.html | 31 + ...te-verification-rule-dialog.component.scss | 1 + ...verification-rule-dialog.component.spec.ts | 25 + ...eate-verification-rule-dialog.component.ts | 87 ++ ...ication-rules-configuration.component.html | 50 + ...ication-rules-configuration.component.scss | 1 + ...tion-rules-configuration.component.spec.ts | 25 + ...ification-rules-configuration.component.ts | 62 + ...cation-rules-search-results.component.html | 79 ++ ...cation-rules-search-results.component.scss | 10 + ...ion-rules-search-results.component.spec.ts | 25 + ...fication-rules-search-results.component.ts | 151 ++ .../verification-rules-search.component.html | 15 + .../verification-rules-search.component.scss | 1 + ...erification-rules-search.component.spec.ts | 25 + .../verification-rules-search.component.ts | 106 ++ .../breadcrumb/breadcrumb.component.html | 3 + .../breadcrumb/breadcrumb.component.scss | 0 .../breadcrumb/breadcrumb.component.spec.ts | 25 + .../breadcrumb/breadcrumb.component.ts | 61 + app/features/card/card.component.html | 16 + app/features/card/card.component.scss | 95 ++ app/features/card/card.component.spec.ts | 25 + app/features/card/card.component.ts | 31 + .../dashboard-metrics.component.html | 23 + .../dashboard-metrics.component.scss | 13 + .../dashboard-metrics.component.spec.ts | 25 + .../dashboard-metrics.component.ts | 18 + ...hboard-processes-per-client.component.html | 55 + ...hboard-processes-per-client.component.scss | 1 + ...ard-processes-per-client.component.spec.ts | 25 + ...ashboard-processes-per-client.component.ts | 47 + .../dashboard/dashboard.component.html | 65 + .../dashboard/dashboard.component.scss | 7 + .../dashboard/dashboard.component.spec.ts | 25 + app/features/dashboard/dashboard.component.ts | 174 +++ .../dashboard/dashboard.configuration.ts | 41 + app/features/features-routing.module.ts | 59 + app/features/features.module.ts | 178 +++ ...ile-download-configurations.component.html | 16 + ...ile-download-configurations.component.scss | 1 + ...-download-configurations.component.spec.ts | 25 + .../file-download-configurations.component.ts | 42 + ...duler-configurations-dialog.component.html | 28 + ...duler-configurations-dialog.component.scss | 1 + ...er-configurations-dialog.component.spec.ts | 25 + ...heduler-configurations-dialog.component.ts | 46 + ...ile-download-execution-info.component.html | 54 + ...ile-download-execution-info.component.scss | 1 + ...-download-execution-info.component.spec.ts | 25 + .../file-download-execution-info.component.ts | 63 + ...-download-real-time-monitor.component.html | 53 + ...-download-real-time-monitor.component.scss | 1 + ...wnload-real-time-monitor.component.spec.ts | 25 + ...le-download-real-time-monitor.component.ts | 158 +++ .../file-table-dialog.component.html | 42 + .../file-table-dialog.component.scss | 1 + .../file-table-dialog.component.spec.ts | 25 + .../file-table-dialog.component.ts | 49 + .../file-download-scheduler.component.html | 48 + .../file-download-scheduler.component.scss | 1 + .../file-download-scheduler.component.spec.ts | 25 + .../file-download-scheduler.component.ts | 66 + .../file-download-search.component.html | 34 + .../file-download-search.component.scss | 1 + .../file-download-search.component.spec.ts | 25 + .../file-download-search.component.ts | 128 ++ .../horizontal-menu.component.html | 18 + .../horizontal-menu.component.scss | 208 +++ .../horizontal-menu.component.spec.ts | 25 + .../horizontal-menu.component.ts | 126 ++ ...abby-for-recognition-dialog.component.html | 93 ++ ...abby-for-recognition-dialog.component.scss | 18 + ...y-for-recognition-dialog.component.spec.ts | 25 + ...o-abby-for-recognition-dialog.component.ts | 103 ++ .../file-viewer-popup.component.html | 21 + .../file-viewer-popup.component.scss | 1 + .../file-viewer-popup.component.spec.ts | 25 + .../file-viewer-popup.component.ts | 46 + ...abby-for-recognition-dialog.component.html | 62 + ...abby-for-recognition-dialog.component.scss | 5 + ...y-for-recognition-dialog.component.spec.ts | 25 + ...o-abby-for-recognition-dialog.component.ts | 49 + .../ignore-file-dialog.component.html | 60 + .../ignore-file-dialog.component.scss | 5 + .../ignore-file-dialog.component.spec.ts | 25 + .../ignore-file-dialog.component.ts | 48 + .../inbox-documents-table.component.html | 45 + .../inbox-documents-table.component.scss | 1 + .../inbox-documents-table.component.spec.ts | 25 + .../inbox-documents-table.component.ts | 126 ++ .../inbox-management.component.html | 39 + .../inbox-management.component.scss | 6 + .../inbox-management.component.spec.ts | 25 + .../inbox-management.component.ts | 63 + .../inbox-search-form.component.html | 92 ++ .../inbox-search-form.component.scss | 1 + .../inbox-search-form.component.spec.ts | 25 + .../inbox-search-form.component.ts | 127 ++ .../invoice-process-management.component.html | 39 + .../invoice-process-management.component.scss | 5 + ...voice-process-management.component.spec.ts | 25 + .../invoice-process-management.component.ts | 121 ++ ...invoice-process-search-form.component.html | 126 ++ ...invoice-process-search-form.component.scss | 1 + ...oice-process-search-form.component.spec.ts | 25 + .../invoice-process-search-form.component.ts | 155 ++ .../invoice-process-table.component.html | 74 + .../invoice-process-table.component.scss | 1 + .../invoice-process-table.component.spec.ts | 25 + .../invoice-process-table.component.ts | 178 +++ ...-capturing-and-verification.component.html | 4 + ...-capturing-and-verification.component.scss | 1 + ...pturing-and-verification.component.spec.ts | 25 + ...ta-capturing-and-verification.component.ts | 82 ++ .../invoice-processing.component.html | 253 ++++ .../invoice-processing.component.scss | 1 + .../invoice-processing.component.spec.ts | 25 + .../invoice-processing.component.ts | 330 +++++ .../journal-edit-dialog.component.html | 6 + .../journal-edit-dialog.component.scss | 20 + .../journal-edit-dialog.component.spec.ts | 25 + .../journal-edit-dialog.component.ts | 36 + .../journal-preview-dialog.component.html | 210 +++ .../journal-preview-dialog.component.scss | 22 + .../journal-preview-dialog.component.spec.ts | 25 + .../journal-preview-dialog.component.ts | 68 + .../journal-view-dialog.component.html | 8 + .../journal-view-dialog.component.scss | 20 + .../journal-view-dialog.component.spec.ts | 25 + .../journal-view-dialog.component.ts | 36 + ...ournal-entries-verification.component.html | 63 + ...ournal-entries-verification.component.scss | 1 + ...nal-entries-verification.component.spec.ts | 25 + .../journal-entries-verification.component.ts | 76 + .../missing-records.component.html | 19 + .../missing-records.component.scss | 1 + .../missing-records.component.spec.ts | 25 + .../missing-records.component.ts | 19 + ...xception-data-preview-popup.component.html | 79 ++ ...xception-data-preview-popup.component.scss | 1 + ...ption-data-preview-popup.component.spec.ts | 25 + .../exception-data-preview-popup.component.ts | 35 + ...cess-exception-manipulation.component.html | 33 + ...cess-exception-manipulation.component.scss | 1 + ...s-exception-manipulation.component.spec.ts | 25 + ...rocess-exception-manipulation.component.ts | 35 + .../process-history.component.html | 31 + .../process-history.component.scss | 0 .../process-history.component.spec.ts | 25 + .../process-history.component.ts | 48 + ...review-unhandled-data-popup.component.html | 79 ++ ...review-unhandled-data-popup.component.scss | 1 + ...iew-unhandled-data-popup.component.spec.ts | 25 + .../preview-unhandled-data-popup.component.ts | 37 + .../process-unhandled-data.component.html | 43 + .../process-unhandled-data.component.scss | 1 + .../process-unhandled-data.component.spec.ts | 25 + .../process-unhandled-data.component.ts | 30 + ...ssify-unhandled-data-dialog.component.html | 84 ++ ...ssify-unhandled-data-dialog.component.scss | 1 + ...fy-unhandled-data-dialog.component.spec.ts | 25 + ...lassify-unhandled-data-dialog.component.ts | 82 ++ .../left-panel/left-panel.component.html | 3 + .../left-panel/left-panel.component.scss | 14 + .../left-panel/left-panel.component.spec.ts | 24 + .../left-panel/left-panel.component.ts | 14 + app/features/login/login.component.html | 16 + app/features/login/login.component.scss | 9 + app/features/login/login.component.spec.ts | 25 + app/features/login/login.component.ts | 20 + .../create-role/create-role.component.html | 49 + .../create-role/create-role.component.scss | 1 + .../create-role/create-role.component.spec.ts | 25 + .../create-role/create-role.component.ts | 54 + .../edit-role/edit-role.component.html | 29 + .../edit-role/edit-role.component.scss | 1 + .../edit-role/edit-role.component.spec.ts | 25 + .../edit-role/edit-role.component.ts | 45 + .../rights-per-role.component.html | 51 + .../rights-per-role.component.scss | 1 + .../rights-per-role.component.spec.ts | 25 + .../rights-per-role.component.ts | 90 ++ .../rights-processes.component.html | 8 + .../rights-processes.component.scss | 1 + .../rights-processes.component.spec.ts | 25 + .../rights-processes.component.ts | 18 + .../roles-management.component.html | 109 ++ .../roles-management.component.scss | 1 + .../roles-management.component.spec.ts | 25 + .../roles-management.component.ts | 163 +++ .../roles-per-user.component.html | 40 + .../roles-per-user.component.scss | 1 + .../roles-per-user.component.spec.ts | 25 + .../roles-per-user.component.ts | 80 ++ .../search-results.component.html | 38 + .../search-results.component.scss | 1 + .../search-results.component.spec.ts | 25 + .../search-results.component.ts | 61 + .../search-user/search-user.component.html | 51 + .../search-user/search-user.component.scss | 1 + .../search-user/search-user.component.spec.ts | 25 + .../search-user/search-user.component.ts | 104 ++ .../user-roles/user-roles.component.html | 101 ++ .../user-roles/user-roles.component.scss | 1 + .../user-roles/user-roles.component.spec.ts | 25 + .../user-roles/user-roles.component.ts | 133 ++ .../vertical-menu.component.html | 8 + .../vertical-menu.component.scss | 97 ++ .../vertical-menu.component.spec.ts | 25 + .../vertical-menu/vertical-menu.component.ts | 74 + app/features/welcome/welcome.component.html | 16 + app/features/welcome/welcome.component.scss | 1 + .../welcome/welcome.component.spec.ts | 25 + app/features/welcome/welcome.component.ts | 16 + app/shared/auth-codeflow-config.ts | 31 + .../search-list-state.service.spec.ts | 15 + .../back-button/search-list-state.service.ts | 65 + .../enums/CLASSIFICATION_STATUS.enum.ts | 5 + app/shared/enums/FILE_TYPE.enum.ts | 8 + app/shared/enums/USER_ACCESS_STATUS.enum.ts | 4 + app/shared/enums/USER_RIGHTS.enum.ts | 79 ++ app/shared/enums/rta-error-message.ts | 11 + app/shared/guards/auth.guard.spec.ts | 16 + app/shared/guards/auth.guard.ts | 24 + .../administration-section.interface.ts | 6 + .../models/alteryx-exception.interface.ts | 11 + .../alteryx-unhandled-data.interface.ts | 9 + .../capturing-verification.interface.ts | 4 + app/shared/models/card-item.interface.ts | 7 + app/shared/models/category.interface.ts | 8 + app/shared/models/chart.interface.ts | 10 + .../configurator-parameter.interface.ts | 8 + .../models/dashboard-section.interface.ts | 24 + .../document-classification.interface.ts | 4 + .../document-subclassification.interface.ts | 7 + .../models/download-process-temp.interafce.ts | 10 + ...ownloading-procedure-metadata.interface.ts | 11 + .../models/files-per-process.interface.ts | 7 + .../models/full-invoice-process.interface.ts | 20 + .../models/i-power-assignment.interface.ts | 6 + app/shared/models/inbox-batch.interface.ts | 12 + app/shared/models/inbox-document.interface.ts | 19 + .../models/inbox-search-criteria.interface.ts | 14 + app/shared/models/index.ts | 3 + .../models/invoice-master-data.interface.ts | 22 + ...voice-process-search-criteria.interface.ts | 15 + .../models/invoice-process.interface.ts | 11 + ...voice-processes-router-params.interface.ts | 4 + app/shared/models/ipower-client.interface.ts | 12 + app/shared/models/journal-entry.interface.ts | 48 + .../models/journal-verification.interface.ts | 4 + app/shared/models/language.interface.ts | 4 + app/shared/models/lookup-data.interface.ts | 4 + app/shared/models/paging/page.interface.ts | 10 + .../models/paging/pageable.interface.ts | 10 + app/shared/models/paging/sort.interface.ts | 5 + .../models/process-failed-record.interface.ts | 5 + .../models/process-history.interface.ts | 10 + app/shared/models/process-status.interface.ts | 5 + app/shared/models/pwc-user-interface.ts | 6 + .../models/real-time-execution.interface.ts | 4 + app/shared/models/receivedFiles.interface.ts | 17 + app/shared/models/record.interface.ts | 12 + .../request/assign-update-role.interface.ts | 11 + .../search-system-exceptions.interface.ts | 10 + .../models/request/search-user.interface.ts | 7 + .../response/user-autocomplete.interface.ts | 7 + app/shared/models/right.interface.ts | 13 + .../models/rights-by-client.interface.ts | 7 + .../models/rights-category.interface.ts | 6 + app/shared/models/role.interface.ts | 14 + app/shared/models/rta-user.interface.ts | 10 + .../models/scheduler-criteria.interface.ts | 6 + .../models/search-response.interface.ts | 5 + app/shared/models/sentString.interface.ts | 3 + .../models/status-per-document.interface.ts | 10 + .../models/system-exception.interface.ts | 11 + app/shared/models/template.interface.ts | 15 + app/shared/models/user-access.interface.ts | 12 + .../models/verification-rule.interface.ts | 17 + app/shared/models/vertical-menu.interface.ts | 6 + .../pipes/hour-minutes-secs.pipe.spec.ts | 8 + app/shared/pipes/hour-minutes-secs.pipe.ts | 23 + .../primeng-shared/primeng-shared.module.ts | 91 ++ .../application-level-exception.service.ts | 16 + .../application-level-exception.spec.ts | 16 + .../capturing-verifications.service.spec.ts | 16 + .../capturing-verifications.service.ts | 21 + .../administration/categories.service.spec.ts | 16 + .../administration/categories.service.ts | 60 + .../configurator.service.spec.ts | 16 + .../administration/configurator.service.ts | 35 + .../document-classifications.service.spec.ts | 16 + .../document-classifications.service.ts | 15 + ...ocument-subclassifications.service.spec.ts | 16 + .../document-subclassifications.service.ts | 20 + .../ipower-clients.service.spec.ts | 16 + .../administration/ipower-clients.service.ts | 68 + .../journal-verifications.service.spec.ts | 16 + .../journal-verifications.service.ts | 21 + .../administration/templates.service.spec.ts | 16 + .../administration/templates.service.ts | 53 + .../verification-rules.service.spec.ts | 16 + .../verification-rules.service.ts | 64 + app/shared/services/api.service.spec.ts | 16 + app/shared/services/api.service.ts | 36 + app/shared/services/auth.service.spec.ts | 16 + app/shared/services/auth.service.ts | 189 +++ .../dashboard/dashboard.service.spec.ts | 16 + .../services/dashboard/dashboard.service.ts | 34 + .../document-classification.service.spec.ts | 16 + .../document-classification.service.ts | 19 + ...document-subclassification.service.spec.ts | 16 + .../document-subclassification.service.ts | 16 + .../error-handling.service.spec.ts | 16 + .../error-handling/error-handling.service.ts | 41 + .../services/generic-rest.service.spec.ts | 16 + app/shared/services/generic-rest.service.ts | 107 ++ .../services/inbox-management.service.spec.ts | 16 + .../services/inbox-management.service.ts | 33 + .../invoice-download-scheduler.service.ts | 59 + .../invoice-processes.service.spec.ts | 16 + .../services/invoice-processes.service.ts | 149 ++ .../journal-dialog-edit.service.spec.ts | 16 + .../services/journal-dialog-edit.service.ts | 20 + .../journal-dialog-view.service.spec.ts | 16 + .../services/journal-dialog-view.service.ts | 18 + .../notifications-handling.service.spec.ts | 16 + .../notifications-handling.service.ts | 150 ++ app/shared/services/received-files.service.ts | 24 + .../services/record-per-process.interface.ts | 9 + .../role.service.spec.ts | 16 + .../roles-users-management/role.service.ts | 25 + .../user.service.spec.ts | 16 + .../roles-users-management/user.service.ts | 48 + app/shared/shared.module.ts | 22 + .../validation-message.component.html | 3 + .../validation-message.component.scss | 8 + .../validation-message.component.spec.ts | 25 + .../validation-message.component.ts | 35 + app/shared/utils/utils.service.spec.ts | 16 + app/shared/utils/utils.service.ts | 38 + assets/.gitkeep | 0 assets/fonts/CharterITCW05-Regular.woff | Bin 0 -> 68266 bytes assets/fonts/HelveticaNeue-Regular.ttf | Bin 0 -> 41180 bytes assets/fonts/PragmaticaMedium.otf | Bin 0 -> 94516 bytes assets/i18n/el.json | 123 ++ assets/i18n/en.json | 125 ++ .../images/favicons/android-icon-144x144.png | Bin 0 -> 4023 bytes .../images/favicons/android-icon-192x192.png | Bin 0 -> 3774 bytes assets/images/favicons/android-icon-36x36.png | Bin 0 -> 1496 bytes assets/images/favicons/android-icon-48x48.png | Bin 0 -> 1826 bytes assets/images/favicons/android-icon-72x72.png | Bin 0 -> 2325 bytes assets/images/favicons/android-icon-96x96.png | Bin 0 -> 2902 bytes assets/images/favicons/apple-icon-114x114.png | Bin 0 -> 3323 bytes assets/images/favicons/apple-icon-120x120.png | Bin 0 -> 3457 bytes assets/images/favicons/apple-icon-144x144.png | Bin 0 -> 4023 bytes assets/images/favicons/apple-icon-152x152.png | Bin 0 -> 4294 bytes assets/images/favicons/apple-icon-180x180.png | Bin 0 -> 5041 bytes assets/images/favicons/apple-icon-57x57.png | Bin 0 -> 2003 bytes assets/images/favicons/apple-icon-60x60.png | Bin 0 -> 2062 bytes assets/images/favicons/apple-icon-72x72.png | Bin 0 -> 2325 bytes assets/images/favicons/apple-icon-76x76.png | Bin 0 -> 2413 bytes .../favicons/apple-icon-precomposed.png | Bin 0 -> 4350 bytes assets/images/favicons/apple-icon.png | Bin 0 -> 4350 bytes assets/images/favicons/browserconfig.xml | 2 + assets/images/favicons/favicon-16x16.png | Bin 0 -> 1301 bytes assets/images/favicons/favicon-32x32.png | Bin 0 -> 1995 bytes assets/images/favicons/favicon-96x96.png | Bin 0 -> 2902 bytes assets/images/favicons/favicon.ico | Bin 0 -> 1150 bytes assets/images/favicons/manifest.json | 41 + assets/images/favicons/ms-icon-144x144.png | Bin 0 -> 4023 bytes assets/images/favicons/ms-icon-150x150.png | Bin 0 -> 4164 bytes assets/images/favicons/ms-icon-310x310.png | Bin 0 -> 10356 bytes assets/images/favicons/ms-icon-70x70.png | Bin 0 -> 2288 bytes assets/images/pwc-logo.svg | 352 +++++ environments/environment.dev-docker.ts | 41 + environments/environment.dev-pwc.ts | 42 + environments/environment.prod.ts | 37 + environments/environment.staging.ts | 45 + environments/environment.ts | 43 + favicon.ico | Bin 0 -> 948 bytes index.html | 33 + main.ts | 12 + polyfills.ts | 63 + styles.scss | 5 + test.ts | 25 + web.config | 19 + 501 files changed, 19243 insertions(+) create mode 100644 _fonts.scss create mode 100644 _general.scss create mode 100644 _media.scss create mode 100644 _pallete.scss create mode 100644 app/app-routing.module.ts create mode 100644 app/app.component.html create mode 100644 app/app.component.scss create mode 100644 app/app.component.spec.ts create mode 100644 app/app.component.ts create mode 100644 app/app.module.ts create mode 100644 app/core/core.module.ts create mode 100644 app/core/error-handling/error-handling.module.ts create mode 100644 app/core/error-handling/global-error-handler.ts create mode 100644 app/core/error-handling/http-error.interceptor.ts create mode 100644 app/core/header/header.component.html create mode 100644 app/core/header/header.component.scss create mode 100644 app/core/header/header.component.spec.ts create mode 100644 app/core/header/header.component.ts create mode 100644 app/core/main-page/main-page.component.html create mode 100644 app/core/main-page/main-page.component.scss create mode 100644 app/core/main-page/main-page.component.spec.ts create mode 100644 app/core/main-page/main-page.component.ts create mode 100644 app/features/administration/administration.component.html create mode 100644 app/features/administration/administration.component.scss create mode 100644 app/features/administration/administration.component.spec.ts create mode 100644 app/features/administration/administration.component.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.html create mode 100644 app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.scss create mode 100644 app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.spec.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-exceptions.component.html create mode 100644 app/features/administration/application-level-exceptions/application-level-exceptions.component.scss create mode 100644 app/features/administration/application-level-exceptions/application-level-exceptions.component.spec.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-exceptions.component.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.html create mode 100644 app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.scss create mode 100644 app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.spec.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.html create mode 100644 app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.scss create mode 100644 app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.spec.ts create mode 100644 app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.ts create mode 100644 app/features/administration/categories-management/categories-management.component.html create mode 100644 app/features/administration/categories-management/categories-management.component.scss create mode 100644 app/features/administration/categories-management/categories-management.component.spec.ts create mode 100644 app/features/administration/categories-management/categories-management.component.ts create mode 100644 app/features/administration/categories-management/categories-search-results/categories-search-results.component.html create mode 100644 app/features/administration/categories-management/categories-search-results/categories-search-results.component.scss create mode 100644 app/features/administration/categories-management/categories-search-results/categories-search-results.component.spec.ts create mode 100644 app/features/administration/categories-management/categories-search-results/categories-search-results.component.ts create mode 100644 app/features/administration/categories-management/categories-search/categories-search.component.html create mode 100644 app/features/administration/categories-management/categories-search/categories-search.component.scss create mode 100644 app/features/administration/categories-management/categories-search/categories-search.component.spec.ts create mode 100644 app/features/administration/categories-management/categories-search/categories-search.component.ts create mode 100644 app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.html create mode 100644 app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.scss create mode 100644 app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.spec.ts create mode 100644 app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.ts create mode 100644 app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.html create mode 100644 app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.scss create mode 100644 app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.spec.ts create mode 100644 app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.ts create mode 100644 app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.html create mode 100644 app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.scss create mode 100644 app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.spec.ts create mode 100644 app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.ts create mode 100644 app/features/administration/configurator/configurator.component.html create mode 100644 app/features/administration/configurator/configurator.component.scss create mode 100644 app/features/administration/configurator/configurator.component.spec.ts create mode 100644 app/features/administration/configurator/configurator.component.ts create mode 100644 app/features/administration/forms/application-level-form/application-level-form.component.html create mode 100644 app/features/administration/forms/application-level-form/application-level-form.component.scss create mode 100644 app/features/administration/forms/application-level-form/application-level-form.component.spec.ts create mode 100644 app/features/administration/forms/application-level-form/application-level-form.component.ts create mode 100644 app/features/administration/forms/category-form/category-form.component.html create mode 100644 app/features/administration/forms/category-form/category-form.component.scss create mode 100644 app/features/administration/forms/category-form/category-form.component.spec.ts create mode 100644 app/features/administration/forms/category-form/category-form.component.ts create mode 100644 app/features/administration/forms/configurator-form/configurator-form.component.html create mode 100644 app/features/administration/forms/configurator-form/configurator-form.component.scss create mode 100644 app/features/administration/forms/configurator-form/configurator-form.component.spec.ts create mode 100644 app/features/administration/forms/configurator-form/configurator-form.component.ts create mode 100644 app/features/administration/forms/template-form/template-form.component.html create mode 100644 app/features/administration/forms/template-form/template-form.component.scss create mode 100644 app/features/administration/forms/template-form/template-form.component.spec.ts create mode 100644 app/features/administration/forms/template-form/template-form.component.ts create mode 100644 app/features/administration/forms/verification-rule-form/create-verification-rule-form-value.interface.ts create mode 100644 app/features/administration/forms/verification-rule-form/verification-rule-form.component.html create mode 100644 app/features/administration/forms/verification-rule-form/verification-rule-form.component.scss create mode 100644 app/features/administration/forms/verification-rule-form/verification-rule-form.component.spec.ts create mode 100644 app/features/administration/forms/verification-rule-form/verification-rule-form.component.ts create mode 100644 app/features/administration/forms/verification-rule-search-form/verification-rule-search-form-value.interface.ts create mode 100644 app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.html create mode 100644 app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.scss create mode 100644 app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.spec.ts create mode 100644 app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.ts create mode 100644 app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.html create mode 100644 app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.scss create mode 100644 app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.spec.ts create mode 100644 app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.ts create mode 100644 app/features/administration/templates-management/templates-management.component.html create mode 100644 app/features/administration/templates-management/templates-management.component.scss create mode 100644 app/features/administration/templates-management/templates-management.component.spec.ts create mode 100644 app/features/administration/templates-management/templates-management.component.ts create mode 100644 app/features/administration/templates-management/templates-search-results/templates-search-results.component.html create mode 100644 app/features/administration/templates-management/templates-search-results/templates-search-results.component.scss create mode 100644 app/features/administration/templates-management/templates-search-results/templates-search-results.component.spec.ts create mode 100644 app/features/administration/templates-management/templates-search-results/templates-search-results.component.ts create mode 100644 app/features/administration/templates-management/templates-search/templates-search.component.html create mode 100644 app/features/administration/templates-management/templates-search/templates-search.component.scss create mode 100644 app/features/administration/templates-management/templates-search/templates-search.component.spec.ts create mode 100644 app/features/administration/templates-management/templates-search/templates-search.component.ts create mode 100644 app/features/administration/verification-rules-configuration/create-verification-rule-dialog/create-verification-rule-dialog.component.html create mode 100644 app/features/administration/verification-rules-configuration/create-verification-rule-dialog/create-verification-rule-dialog.component.scss create mode 100644 app/features/administration/verification-rules-configuration/create-verification-rule-dialog/create-verification-rule-dialog.component.spec.ts create mode 100644 app/features/administration/verification-rules-configuration/create-verification-rule-dialog/create-verification-rule-dialog.component.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-configuration.component.html create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-configuration.component.scss create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-configuration.component.spec.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-configuration.component.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search-results/verification-rules-search-results.component.html create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search-results/verification-rules-search-results.component.scss create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search-results/verification-rules-search-results.component.spec.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search-results/verification-rules-search-results.component.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search/verification-rules-search.component.html create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search/verification-rules-search.component.scss create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search/verification-rules-search.component.spec.ts create mode 100644 app/features/administration/verification-rules-configuration/verification-rules-search/verification-rules-search.component.ts create mode 100644 app/features/breadcrumb/breadcrumb.component.html create mode 100644 app/features/breadcrumb/breadcrumb.component.scss create mode 100644 app/features/breadcrumb/breadcrumb.component.spec.ts create mode 100644 app/features/breadcrumb/breadcrumb.component.ts create mode 100644 app/features/card/card.component.html create mode 100644 app/features/card/card.component.scss create mode 100644 app/features/card/card.component.spec.ts create mode 100644 app/features/card/card.component.ts create mode 100644 app/features/dashboard/dashboard-metrics/dashboard-metrics.component.html create mode 100644 app/features/dashboard/dashboard-metrics/dashboard-metrics.component.scss create mode 100644 app/features/dashboard/dashboard-metrics/dashboard-metrics.component.spec.ts create mode 100644 app/features/dashboard/dashboard-metrics/dashboard-metrics.component.ts create mode 100644 app/features/dashboard/dashboard-processes-per-client/dashboard-processes-per-client.component.html create mode 100644 app/features/dashboard/dashboard-processes-per-client/dashboard-processes-per-client.component.scss create mode 100644 app/features/dashboard/dashboard-processes-per-client/dashboard-processes-per-client.component.spec.ts create mode 100644 app/features/dashboard/dashboard-processes-per-client/dashboard-processes-per-client.component.ts create mode 100644 app/features/dashboard/dashboard.component.html create mode 100644 app/features/dashboard/dashboard.component.scss create mode 100644 app/features/dashboard/dashboard.component.spec.ts create mode 100644 app/features/dashboard/dashboard.component.ts create mode 100644 app/features/dashboard/dashboard.configuration.ts create mode 100644 app/features/features-routing.module.ts create mode 100644 app/features/features.module.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-configurations.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-configurations.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-configurations.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-configurations.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-scheduler-configurations-dialog/file-download-scheduler-configurations-dialog.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-scheduler-configurations-dialog/file-download-scheduler-configurations-dialog.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-scheduler-configurations-dialog/file-download-scheduler-configurations-dialog.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-configurations/file-download-scheduler-configurations-dialog/file-download-scheduler-configurations-dialog.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-execution-info/file-download-execution-info.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-execution-info/file-download-execution-info.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-execution-info/file-download-execution-info.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-execution-info/file-download-execution-info.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-download-real-time-monitor.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-download-real-time-monitor.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-download-real-time-monitor.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-download-real-time-monitor.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-table-dialog/file-table-dialog.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-table-dialog/file-table-dialog.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-table-dialog/file-table-dialog.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-real-time-monitor/file-table-dialog/file-table-dialog.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-scheduler.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-scheduler.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-scheduler.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-scheduler.component.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-search/file-download-search.component.html create mode 100644 app/features/file-download/file-download-scheduler/file-download-search/file-download-search.component.scss create mode 100644 app/features/file-download/file-download-scheduler/file-download-search/file-download-search.component.spec.ts create mode 100644 app/features/file-download/file-download-scheduler/file-download-search/file-download-search.component.ts create mode 100644 app/features/horizontal-menu/horizontal-menu.component.html create mode 100644 app/features/horizontal-menu/horizontal-menu.component.scss create mode 100644 app/features/horizontal-menu/horizontal-menu.component.spec.ts create mode 100644 app/features/horizontal-menu/horizontal-menu.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/edit-file-class-and-qeue-to-abby-for-recognition-dialog/edit-file-class-and-qeue-to-abby-for-recognition-dialog.component.html create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/edit-file-class-and-qeue-to-abby-for-recognition-dialog/edit-file-class-and-qeue-to-abby-for-recognition-dialog.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/edit-file-class-and-qeue-to-abby-for-recognition-dialog/edit-file-class-and-qeue-to-abby-for-recognition-dialog.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/edit-file-class-and-qeue-to-abby-for-recognition-dialog/edit-file-class-and-qeue-to-abby-for-recognition-dialog.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/file-viewer-popup/file-viewer-popup.component.html create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/file-viewer-popup/file-viewer-popup.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/file-viewer-popup/file-viewer-popup.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/file-viewer-popup/file-viewer-popup.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/forward-file-to-abby-for-recognition-dialog/forward-file-to-abby-for-recognition-dialog.component.html create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/forward-file-to-abby-for-recognition-dialog/forward-file-to-abby-for-recognition-dialog.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/forward-file-to-abby-for-recognition-dialog/forward-file-to-abby-for-recognition-dialog.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/forward-file-to-abby-for-recognition-dialog/forward-file-to-abby-for-recognition-dialog.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/ignore-file-dialog/ignore-file-dialog.component.html create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/ignore-file-dialog/ignore-file-dialog.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/ignore-file-dialog/ignore-file-dialog.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-dialogs/ignore-file-dialog/ignore-file-dialog.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-documents-table/inbox-documents-table.component.html create mode 100644 app/features/inbox/inbox-management/inbox-documents-table/inbox-documents-table.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-documents-table/inbox-documents-table.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-documents-table/inbox-documents-table.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-management.component.html create mode 100644 app/features/inbox/inbox-management/inbox-management.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-management.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-management.component.ts create mode 100644 app/features/inbox/inbox-management/inbox-search-form/inbox-search-form.component.html create mode 100644 app/features/inbox/inbox-management/inbox-search-form/inbox-search-form.component.scss create mode 100644 app/features/inbox/inbox-management/inbox-search-form/inbox-search-form.component.spec.ts create mode 100644 app/features/inbox/inbox-management/inbox-search-form/inbox-search-form.component.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-management.component.html create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-management.component.scss create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-management.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-management.component.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-search-form/invoice-process-search-form.component.html create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-search-form/invoice-process-search-form.component.scss create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-search-form/invoice-process-search-form.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-search-form/invoice-process-search-form.component.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-table/invoice-process-table.component.html create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-table/invoice-process-table.component.scss create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-table/invoice-process-table.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-process-management/invoice-process-table/invoice-process-table.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/data-capturing-and-verification/data-capturing-and-verification.component.html create mode 100644 app/features/invoice-processes/invoice-processing/data-capturing-and-verification/data-capturing-and-verification.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/data-capturing-and-verification/data-capturing-and-verification.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/data-capturing-and-verification/data-capturing-and-verification.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/invoice-processing.component.html create mode 100644 app/features/invoice-processes/invoice-processing/invoice-processing.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/invoice-processing.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/invoice-processing.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-edit-dialog/journal-edit-dialog.component.html create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-edit-dialog/journal-edit-dialog.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-edit-dialog/journal-edit-dialog.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-edit-dialog/journal-edit-dialog.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-preview-dialog/journal-preview-dialog.component.html create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-preview-dialog/journal-preview-dialog.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-preview-dialog/journal-preview-dialog.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-preview-dialog/journal-preview-dialog.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-view-dialog/journal-view-dialog.component.html create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-view-dialog/journal-view-dialog.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-view-dialog/journal-view-dialog.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification-dialogs/journal-view-dialog/journal-view-dialog.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification.component.html create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/journal-entries-verification/journal-entries-verification.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/missing-records/missing-records/missing-records.component.html create mode 100644 app/features/invoice-processes/invoice-processing/missing-records/missing-records/missing-records.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/missing-records/missing-records/missing-records.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/missing-records/missing-records/missing-records.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/exception-data-preview-popup/exception-data-preview-popup.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/exception-data-preview-popup/exception-data-preview-popup.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/exception-data-preview-popup/exception-data-preview-popup.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/exception-data-preview-popup/exception-data-preview-popup.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/process-exception-manipulation.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/process-exception-manipulation.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/process-exception-manipulation.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-exception-manipulation/process-exception-manipulation.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-history/process-history.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-history/process-history.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-history/process-history.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-history/process-history.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/preview-unhandled-data-popup/preview-unhandled-data-popup.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/preview-unhandled-data-popup/preview-unhandled-data-popup.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/preview-unhandled-data-popup/preview-unhandled-data-popup.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/preview-unhandled-data-popup/preview-unhandled-data-popup.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/process-unhandled-data.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/process-unhandled-data.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/process-unhandled-data.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/process-unhandled-data.component.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/reclassify-unhandled-data-dialog/reclassify-unhandled-data-dialog.component.html create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/reclassify-unhandled-data-dialog/reclassify-unhandled-data-dialog.component.scss create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/reclassify-unhandled-data-dialog/reclassify-unhandled-data-dialog.component.spec.ts create mode 100644 app/features/invoice-processes/invoice-processing/process-unhandled-data/reclassify-unhandled-data-dialog/reclassify-unhandled-data-dialog.component.ts create mode 100644 app/features/left-panel/left-panel.component.html create mode 100644 app/features/left-panel/left-panel.component.scss create mode 100644 app/features/left-panel/left-panel.component.spec.ts create mode 100644 app/features/left-panel/left-panel.component.ts create mode 100644 app/features/login/login.component.html create mode 100644 app/features/login/login.component.scss create mode 100644 app/features/login/login.component.spec.ts create mode 100644 app/features/login/login.component.ts create mode 100644 app/features/roles/roles-management/create-role/create-role.component.html create mode 100644 app/features/roles/roles-management/create-role/create-role.component.scss create mode 100644 app/features/roles/roles-management/create-role/create-role.component.spec.ts create mode 100644 app/features/roles/roles-management/create-role/create-role.component.ts create mode 100644 app/features/roles/roles-management/edit-role/edit-role.component.html create mode 100644 app/features/roles/roles-management/edit-role/edit-role.component.scss create mode 100644 app/features/roles/roles-management/edit-role/edit-role.component.spec.ts create mode 100644 app/features/roles/roles-management/edit-role/edit-role.component.ts create mode 100644 app/features/roles/roles-management/rights-per-role/rights-per-role.component.html create mode 100644 app/features/roles/roles-management/rights-per-role/rights-per-role.component.scss create mode 100644 app/features/roles/roles-management/rights-per-role/rights-per-role.component.spec.ts create mode 100644 app/features/roles/roles-management/rights-per-role/rights-per-role.component.ts create mode 100644 app/features/roles/roles-management/rights-per-role/rights-processes/rights-processes.component.html create mode 100644 app/features/roles/roles-management/rights-per-role/rights-processes/rights-processes.component.scss create mode 100644 app/features/roles/roles-management/rights-per-role/rights-processes/rights-processes.component.spec.ts create mode 100644 app/features/roles/roles-management/rights-per-role/rights-processes/rights-processes.component.ts create mode 100644 app/features/roles/roles-management/roles-management.component.html create mode 100644 app/features/roles/roles-management/roles-management.component.scss create mode 100644 app/features/roles/roles-management/roles-management.component.spec.ts create mode 100644 app/features/roles/roles-management/roles-management.component.ts create mode 100644 app/features/roles/roles-per-user/roles-per-user.component.html create mode 100644 app/features/roles/roles-per-user/roles-per-user.component.scss create mode 100644 app/features/roles/roles-per-user/roles-per-user.component.spec.ts create mode 100644 app/features/roles/roles-per-user/roles-per-user.component.ts create mode 100644 app/features/roles/roles-per-user/search-results/search-results.component.html create mode 100644 app/features/roles/roles-per-user/search-results/search-results.component.scss create mode 100644 app/features/roles/roles-per-user/search-results/search-results.component.spec.ts create mode 100644 app/features/roles/roles-per-user/search-results/search-results.component.ts create mode 100644 app/features/roles/roles-per-user/search-user/search-user.component.html create mode 100644 app/features/roles/roles-per-user/search-user/search-user.component.scss create mode 100644 app/features/roles/roles-per-user/search-user/search-user.component.spec.ts create mode 100644 app/features/roles/roles-per-user/search-user/search-user.component.ts create mode 100644 app/features/roles/roles-per-user/user-roles/user-roles.component.html create mode 100644 app/features/roles/roles-per-user/user-roles/user-roles.component.scss create mode 100644 app/features/roles/roles-per-user/user-roles/user-roles.component.spec.ts create mode 100644 app/features/roles/roles-per-user/user-roles/user-roles.component.ts create mode 100644 app/features/vertical-menu/vertical-menu.component.html create mode 100644 app/features/vertical-menu/vertical-menu.component.scss create mode 100644 app/features/vertical-menu/vertical-menu.component.spec.ts create mode 100644 app/features/vertical-menu/vertical-menu.component.ts create mode 100644 app/features/welcome/welcome.component.html create mode 100644 app/features/welcome/welcome.component.scss create mode 100644 app/features/welcome/welcome.component.spec.ts create mode 100644 app/features/welcome/welcome.component.ts create mode 100644 app/shared/auth-codeflow-config.ts create mode 100644 app/shared/back-button/search-list-state.service.spec.ts create mode 100644 app/shared/back-button/search-list-state.service.ts create mode 100644 app/shared/enums/CLASSIFICATION_STATUS.enum.ts create mode 100644 app/shared/enums/FILE_TYPE.enum.ts create mode 100644 app/shared/enums/USER_ACCESS_STATUS.enum.ts create mode 100644 app/shared/enums/USER_RIGHTS.enum.ts create mode 100644 app/shared/enums/rta-error-message.ts create mode 100644 app/shared/guards/auth.guard.spec.ts create mode 100644 app/shared/guards/auth.guard.ts create mode 100644 app/shared/models/administration-section.interface.ts create mode 100644 app/shared/models/alteryx-exception.interface.ts create mode 100644 app/shared/models/alteryx-unhandled-data.interface.ts create mode 100644 app/shared/models/capturing-verification.interface.ts create mode 100644 app/shared/models/card-item.interface.ts create mode 100644 app/shared/models/category.interface.ts create mode 100644 app/shared/models/chart.interface.ts create mode 100644 app/shared/models/configurator-parameter.interface.ts create mode 100644 app/shared/models/dashboard-section.interface.ts create mode 100644 app/shared/models/document-classification.interface.ts create mode 100644 app/shared/models/document-subclassification.interface.ts create mode 100644 app/shared/models/download-process-temp.interafce.ts create mode 100644 app/shared/models/downloading-procedure-metadata.interface.ts create mode 100644 app/shared/models/files-per-process.interface.ts create mode 100644 app/shared/models/full-invoice-process.interface.ts create mode 100644 app/shared/models/i-power-assignment.interface.ts create mode 100644 app/shared/models/inbox-batch.interface.ts create mode 100644 app/shared/models/inbox-document.interface.ts create mode 100644 app/shared/models/inbox-search-criteria.interface.ts create mode 100644 app/shared/models/index.ts create mode 100644 app/shared/models/invoice-master-data.interface.ts create mode 100644 app/shared/models/invoice-process-search-criteria.interface.ts create mode 100644 app/shared/models/invoice-process.interface.ts create mode 100644 app/shared/models/invoice-processes-router-params.interface.ts create mode 100644 app/shared/models/ipower-client.interface.ts create mode 100644 app/shared/models/journal-entry.interface.ts create mode 100644 app/shared/models/journal-verification.interface.ts create mode 100644 app/shared/models/language.interface.ts create mode 100644 app/shared/models/lookup-data.interface.ts create mode 100644 app/shared/models/paging/page.interface.ts create mode 100644 app/shared/models/paging/pageable.interface.ts create mode 100644 app/shared/models/paging/sort.interface.ts create mode 100644 app/shared/models/process-failed-record.interface.ts create mode 100644 app/shared/models/process-history.interface.ts create mode 100644 app/shared/models/process-status.interface.ts create mode 100644 app/shared/models/pwc-user-interface.ts create mode 100644 app/shared/models/real-time-execution.interface.ts create mode 100644 app/shared/models/receivedFiles.interface.ts create mode 100644 app/shared/models/record.interface.ts create mode 100644 app/shared/models/request/assign-update-role.interface.ts create mode 100644 app/shared/models/request/search-system-exceptions.interface.ts create mode 100644 app/shared/models/request/search-user.interface.ts create mode 100644 app/shared/models/response/user-autocomplete.interface.ts create mode 100644 app/shared/models/right.interface.ts create mode 100644 app/shared/models/rights-by-client.interface.ts create mode 100644 app/shared/models/rights-category.interface.ts create mode 100644 app/shared/models/role.interface.ts create mode 100644 app/shared/models/rta-user.interface.ts create mode 100644 app/shared/models/scheduler-criteria.interface.ts create mode 100644 app/shared/models/search-response.interface.ts create mode 100644 app/shared/models/sentString.interface.ts create mode 100644 app/shared/models/status-per-document.interface.ts create mode 100644 app/shared/models/system-exception.interface.ts create mode 100644 app/shared/models/template.interface.ts create mode 100644 app/shared/models/user-access.interface.ts create mode 100644 app/shared/models/verification-rule.interface.ts create mode 100644 app/shared/models/vertical-menu.interface.ts create mode 100644 app/shared/pipes/hour-minutes-secs.pipe.spec.ts create mode 100644 app/shared/pipes/hour-minutes-secs.pipe.ts create mode 100644 app/shared/primeng-shared/primeng-shared.module.ts create mode 100644 app/shared/services/administration/application-level-exception.service.ts create mode 100644 app/shared/services/administration/application-level-exception.spec.ts create mode 100644 app/shared/services/administration/capturing-verifications.service.spec.ts create mode 100644 app/shared/services/administration/capturing-verifications.service.ts create mode 100644 app/shared/services/administration/categories.service.spec.ts create mode 100644 app/shared/services/administration/categories.service.ts create mode 100644 app/shared/services/administration/configurator.service.spec.ts create mode 100644 app/shared/services/administration/configurator.service.ts create mode 100644 app/shared/services/administration/document-classifications.service.spec.ts create mode 100644 app/shared/services/administration/document-classifications.service.ts create mode 100644 app/shared/services/administration/document-subclassifications.service.spec.ts create mode 100644 app/shared/services/administration/document-subclassifications.service.ts create mode 100644 app/shared/services/administration/ipower-clients.service.spec.ts create mode 100644 app/shared/services/administration/ipower-clients.service.ts create mode 100644 app/shared/services/administration/journal-verifications.service.spec.ts create mode 100644 app/shared/services/administration/journal-verifications.service.ts create mode 100644 app/shared/services/administration/templates.service.spec.ts create mode 100644 app/shared/services/administration/templates.service.ts create mode 100644 app/shared/services/administration/verification-rules.service.spec.ts create mode 100644 app/shared/services/administration/verification-rules.service.ts create mode 100644 app/shared/services/api.service.spec.ts create mode 100644 app/shared/services/api.service.ts create mode 100644 app/shared/services/auth.service.spec.ts create mode 100644 app/shared/services/auth.service.ts create mode 100644 app/shared/services/dashboard/dashboard.service.spec.ts create mode 100644 app/shared/services/dashboard/dashboard.service.ts create mode 100644 app/shared/services/document-classification.service.spec.ts create mode 100644 app/shared/services/document-classification.service.ts create mode 100644 app/shared/services/document-subclassification.service.spec.ts create mode 100644 app/shared/services/document-subclassification.service.ts create mode 100644 app/shared/services/error-handling/error-handling.service.spec.ts create mode 100644 app/shared/services/error-handling/error-handling.service.ts create mode 100644 app/shared/services/generic-rest.service.spec.ts create mode 100644 app/shared/services/generic-rest.service.ts create mode 100644 app/shared/services/inbox-management.service.spec.ts create mode 100644 app/shared/services/inbox-management.service.ts create mode 100644 app/shared/services/invoice-download-scheduler.service.ts create mode 100644 app/shared/services/invoice-processes.service.spec.ts create mode 100644 app/shared/services/invoice-processes.service.ts create mode 100644 app/shared/services/journal-dialog-edit.service.spec.ts create mode 100644 app/shared/services/journal-dialog-edit.service.ts create mode 100644 app/shared/services/journal-dialog-view.service.spec.ts create mode 100644 app/shared/services/journal-dialog-view.service.ts create mode 100644 app/shared/services/notifications-handling/notifications-handling.service.spec.ts create mode 100644 app/shared/services/notifications-handling/notifications-handling.service.ts create mode 100644 app/shared/services/received-files.service.ts create mode 100644 app/shared/services/record-per-process.interface.ts create mode 100644 app/shared/services/roles-users-management/role.service.spec.ts create mode 100644 app/shared/services/roles-users-management/role.service.ts create mode 100644 app/shared/services/roles-users-management/user.service.spec.ts create mode 100644 app/shared/services/roles-users-management/user.service.ts create mode 100644 app/shared/shared.module.ts create mode 100644 app/shared/utils/components/validation-message/validation-message.component.html create mode 100644 app/shared/utils/components/validation-message/validation-message.component.scss create mode 100644 app/shared/utils/components/validation-message/validation-message.component.spec.ts create mode 100644 app/shared/utils/components/validation-message/validation-message.component.ts create mode 100644 app/shared/utils/utils.service.spec.ts create mode 100644 app/shared/utils/utils.service.ts create mode 100644 assets/.gitkeep create mode 100644 assets/fonts/CharterITCW05-Regular.woff create mode 100644 assets/fonts/HelveticaNeue-Regular.ttf create mode 100644 assets/fonts/PragmaticaMedium.otf create mode 100644 assets/i18n/el.json create mode 100644 assets/i18n/en.json create mode 100644 assets/images/favicons/android-icon-144x144.png create mode 100644 assets/images/favicons/android-icon-192x192.png create mode 100644 assets/images/favicons/android-icon-36x36.png create mode 100644 assets/images/favicons/android-icon-48x48.png create mode 100644 assets/images/favicons/android-icon-72x72.png create mode 100644 assets/images/favicons/android-icon-96x96.png create mode 100644 assets/images/favicons/apple-icon-114x114.png create mode 100644 assets/images/favicons/apple-icon-120x120.png create mode 100644 assets/images/favicons/apple-icon-144x144.png create mode 100644 assets/images/favicons/apple-icon-152x152.png create mode 100644 assets/images/favicons/apple-icon-180x180.png create mode 100644 assets/images/favicons/apple-icon-57x57.png create mode 100644 assets/images/favicons/apple-icon-60x60.png create mode 100644 assets/images/favicons/apple-icon-72x72.png create mode 100644 assets/images/favicons/apple-icon-76x76.png create mode 100644 assets/images/favicons/apple-icon-precomposed.png create mode 100644 assets/images/favicons/apple-icon.png create mode 100644 assets/images/favicons/browserconfig.xml create mode 100644 assets/images/favicons/favicon-16x16.png create mode 100644 assets/images/favicons/favicon-32x32.png create mode 100644 assets/images/favicons/favicon-96x96.png create mode 100644 assets/images/favicons/favicon.ico create mode 100644 assets/images/favicons/manifest.json create mode 100644 assets/images/favicons/ms-icon-144x144.png create mode 100644 assets/images/favicons/ms-icon-150x150.png create mode 100644 assets/images/favicons/ms-icon-310x310.png create mode 100644 assets/images/favicons/ms-icon-70x70.png create mode 100644 assets/images/pwc-logo.svg create mode 100644 environments/environment.dev-docker.ts create mode 100644 environments/environment.dev-pwc.ts create mode 100644 environments/environment.prod.ts create mode 100644 environments/environment.staging.ts create mode 100644 environments/environment.ts create mode 100644 favicon.ico create mode 100644 index.html create mode 100644 main.ts create mode 100644 polyfills.ts create mode 100644 styles.scss create mode 100644 test.ts create mode 100644 web.config diff --git a/_fonts.scss b/_fonts.scss new file mode 100644 index 0000000..2c1cdf2 --- /dev/null +++ b/_fonts.scss @@ -0,0 +1,35 @@ +/* You can add fonts */ + +@font-face { + font-family: "CharterITCW05"; + src: url("assets/fonts/CharterITCW05-Regular.woff") format("woff"); +} + +/*@font-face { + font-family: "HelveticaNeue"; + src: url("assets/fonts/HelveticaNeue-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: "PragmaticaMedium"; + src: url("assets/fonts/PragmaticaMedium.otf") format("opentype"); +}*/ + + +:host ::ng-deep { + h1, h2, h3, h4, h5, h6 { + font-family: "CharterITCW05"; + } + + /*label, .p-button, th { + font-family: "PragmaticaMedium"; + font-weight: 100; + }*/ + + /** { + :not(h1, h2, h3, h4, h5, h6, label, .p-button, th, .pi) { + font-family: "HelveticaNeue"; + font-weight: 600; + } + }*/ +} diff --git a/_general.scss b/_general.scss new file mode 100644 index 0000000..e06252b --- /dev/null +++ b/_general.scss @@ -0,0 +1,1263 @@ +/* You can add general styles */ +@import 'pallete'; + +body { + margin: 0; + padding: 0; +} + +a { + text-decoration: none; +} + +h1 { + font-size: 40px; // Desktop 38/40/45px // Mobile 24px; + line-height: 1.3em; // Mobile 1.2em +} + +h2 { + font-size: 38px; // Desktop 38/40/45px // Mobile 24px; + line-height: 1.3em; // Mobile 1.2em +} + +h3 { + &.sub-title { + padding: 0px 30px 10px; + margin: 0px; + border-bottom: 2px solid $black; + } +} + +.container { + max-width: 1440px; + position: relative; + left: 50%; + transform: translateX(-50%); +} + +// Header +.header { + padding: 30px 30px 0px; +} + +// Main Content +.main-content { + padding: 30px; + + h1 { + text-align: center; + color: $orange; + margin-top: 0px; + } + //sub-content + .sub-content { + padding: 30px; + } +} +// Helper +.readonly { + label { + margin-right: 0.5rem; + font-weight: 600; + } + + span { + color: $orange; + } +} + +.one-button { + min-width: 55px !important; +} + +.two-buttons { + min-width: 117px !important; +} + +.three-buttons { + min-width: 163px !important; +} + +.four-buttons { + min-width: 209px !important; +} + +.float-right { + float: right !important; +} + +.float-left { + float: left !important; +} + +//progressSpinner +.progress-spinner { + position: relative; + width: 100%; + height: 420px; + + .spinner { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + + :host ::ng-deep .p-component { + @keyframes p-progress-spinner-color { + 100%, 0% { + stroke: $orange; + } + + 40% { + stroke: $tangerine; + } + + 66% { + stroke: $light-tangerine-1; + } + + 80%, 90% { + stroke: $light-tangerine-2; + } + } + } +} + +// selectbutton +.p-selectbutton { + //button + .p-button { + background: $white; + border: 2px solid $black; + color: $black; + + &:not(.p-disabled) { + &:not(.p-highlight) { + &:hover { + background: $light-grey; + border-color: $black; + color: $black; + } + } + } + + &:focus { + box-shadow: unset; + } + //highlight + &.p-highlight { + background: $tangerine; + border-color: $tangerine; + color: $black; + + &:hover { + background: $dark-tangerine-1; + border-color: $dark-tangerine-1; + color: $white; + } + } + //button-label + .p-button-label { + font-weight: 600; + line-height: 1; + } + } +} + +// Buttons +.p-button { + padding: 0.5rem 2rem; + font-weight: 600; + + &:enabled { + background: $black; + color: $white; + border: 1px solid $black; + + &:hover { + background: $black; + color: $orange; + border: 1px solid $black; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $orange; + } + + &.p-button-primary { + background: $black; + color: $white; + border: 1px solid $black; + + &:hover { + background: $black; + color: $orange; + border: 1px solid $black; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $orange; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $orange; + border: 2px solid $orange; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $orange; + } + } + } + + &.p-button-secondary { + background: $tangerine; + color: $white; + border: 1px solid $tangerine; + + &:hover { + background: $dark-tangerine-1; + color: $white; + border: 1px solid $dark-tangerine-1; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $tangerine; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $tangerine; + border: 2px solid $tangerine; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-1; + } + } + } + + &.p-button-warning { + background: $light-tangerine-2; + color: $black; + border: 1px solid $light-tangerine-2; + + &:hover { + background: $light-tangerine-1; + color: $black; + border: 1px solid $light-tangerine-1; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $light-tangerine-1; + border: 2px solid $light-tangerine-1; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + } + } + + &.p-button-danger { + background: $dark-orange-1; + color: $white; + border: 1px solid $dark-orange-1; + + &:hover { + background: $dark-orange-2; + color: $white; + border: 1px solid $dark-orange-2; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $dark-orange-1; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $orange; + border: 2px solid $orange; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $orange; + } + } + } + } + + &:disabled { + background: $black; + color: $white; + border: 1px solid $black; + + &:hover { + background: $black; + color: $white; + border: 1px solid $black; + } + + &.p-button-icon-only { + &.p-button-outlined { + &:hover { + transform: rotate(0deg); + } + } + } + + &:focus { + box-shadow: unset; + } + + &.p-button-primary { + background: $black; + color: $white; + border: 1px solid $black; + + &:hover { + background: $black; + color: $white; + border: 1px solid $black; + } + + &:focus { + box-shadow: unset; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $black; + border: 2px solid $black; + } + + &:focus { + box-shadow: unset; + } + } + } + + &.p-button-secondary { + background: $tangerine; + color: $white; + border: 1px solid $tangerine; + + &:hover { + background: $tangerine; + color: $white; + border: 1px solid $tangerine; + } + + &:focus { + box-shadow: unset; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $black; + border: 2px solid $black; + } + + &:focus { + box-shadow: unset; + } + } + } + + &.p-button-warning { + background: $dark-orange-1; + color: $white; + border: 1px solid $dark-orange-1; + + &:hover { + background: $dark-orange-1; + color: $white; + border: 1px solid $dark-orange-1; + } + + &:focus { + box-shadow: unset; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $black; + border: 2px solid $black; + } + + &:focus { + box-shadow: unset; + } + } + } + + &.p-button-danger { + background: $dark-orange-1; + color: $white; + border: 1px solid $dark-orange-1; + + &:hover { + background: $dark-orange-1; + color: $white; + border: 1px solid $dark-orange-1; + } + + &:focus { + box-shadow: unset; + } + + &.p-button-outlined { + background: none; + color: $black; + border: 2px solid $black; + + &:hover { + color: $black; + border: 2px solid $black; + } + + &:focus { + box-shadow: unset; + } + } + } + } + + &.p-button-icon-only { + padding: 0.5rem; + transform: rotate(0deg); + transition: 0.5s; + + &.p-button-outlined { + &:hover { + transform: rotate(360deg); + } + } + } +} + +//form +.p-field { + label { + font-weight: 600; + } +} + +.p-formgrid-inline { + label { + margin-right: 0.5rem; + } +} + +:host ::ng-deep .p-component { + //disabled elements + &:disabled { + opacity: 0.5 !important; + cursor: not-allowed !important; + border-color: $light-grey; + } + //fieldset + &.p-fieldset { + border-width: 2px; + border: 2px solid $black; + background: $white; + color: $black; + margin: 0; + //font-weight: 600; + .p-fieldset-legend { + border: 2px solid $black; + background: $black; + padding: 0.5rem 1rem; + color: $white; + transition: color 0.2s, border 0.2s, background 0.2s; + } + + &.p-fieldset-toggleable { + .p-fieldset-legend { + padding: 0; + + &:hover { + background: $white; + + a { + color: $black; + } + } + + a { + color: $white; + padding: 0.5rem 1rem; + + &:focus { + box-shadow: unset; + } + } + } + } + + .p-field { + + &:first-child { + margin-left: 0px; + } + + &:last-child { + margin-right: 0px; + } + + input { + &[type="checkbox"] { + margin: 0; + vertical-align: middle; + + i { + color: red; + } + + + label { + margin-right: 0px; + margin-left: 0.5rem; + vertical-align: middle; + } + } + + &[disabled] { + border: 1px solid $light-grey; + + &:hover { + border: 1px solid $light-grey; + } + } + } + } + } + //form-inline + .p-formgroup-inline { + margin-top: 1rem; + } + //inputtext + .p-inputtext { + border: 1px solid $black; + transition: border 0.2s, box-shadow 0.2s; + color: $black; + padding: 0.5rem 1rem; + + &:hover { + border: 1px solid $tangerine; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $dark-tangerine-1; + border-color: $dark-tangerine-1; + } + } + //inputswitch + .p-inputswitch { + .p-inputswitch-slider { + background: $light-grey; + } + + &.p-inputswitch-checked { + .p-inputswitch-slider { + background: $tangerine; + } + } + } + //dropdown + .p-dropdown { + border: 1px solid $black; + transition: border 0.2s, box-shadow 0.2s; + + &:hover { + border: 1px solid $tangerine; + } + + &.p-focus { + box-shadow: 0 0 0 0.1rem $dark-tangerine-1; + border-color: $dark-tangerine-1; + } + + .p-dropdown-label { + &.p-placeholder { + color: $grey; + } + } + + .p-inputtext { + border: 1px solid transparent; + padding: 0.4rem 1rem; + + &:hover { + border: 1px solid transparent; + } + } + + .p-dropdown-trigger { + color: $black; + } + + &.p-disabled { + cursor: not-allowed !important; + opacity: 0.5 !important; + border-color: $light-grey; + pointer-events: visible; + } + } + //dropdown-panel + .p-dropdown-panel { + .p-dropdown-items { + .p-dropdown-item { + color: $black; + transition: background 0.2s, color 0.2s; + + &:hover { + background: $light-grey; + color: $black; + } + + &.p-highlight { + color: $black; + background: $light-tangerine-2; + } + } + } + } + //field-checkbox + .p-field-checkbox { + label { + margin-left: 0.5rem; + margin-right: 0.5rem; + opacity: 1; + color: $black; + font-weight: 600; + } + } + //checkbox + .p-checkbox { + + &.p-checkbox-disabled { + + .p-checkbox-box { + &.p-disabled { + cursor: not-allowed !important; + opacity: 0.5 !important; + border-color: $light-grey; + pointer-events: visible; + } + } + } + + .p-checkbox-box { + border: 1px solid $black; + + &:hover { + border: 1px solid $tangerine; + + &.p-highlight { + background: $dark-tangerine-1; + border: 1px solid $dark-tangerine-1; + + &.p-focus { + box-shadow: 0 0 0 0.1rem $tangerine; + } + } + + .p-checkbox-icon { + color: $white; + } + } + + &.p-focus { + box-shadow: 0 0 0 0.1rem $tangerine; + border: 1px solid $tangerine; + } + + &.p-highlight { + border: 1px solid $tangerine; + background: $tangerine; + } + + .p-checkbox-icon { + color: $black; + } + } + } + //datepicker + .p-calendar-w-btn { + .p-datepicker-trigger { + background: $tangerine; + border: 1px solid $tangerine; + color: $black; + left: -1px; + + &:hover { + background: $dark-tangerine-1; + border: 1px solid $dark-tangerine-1; + color: $white; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $tangerine; + } + } + } + //multiselect + &.p-multiselect { + border: 1px solid $black; + transition: border 0.2s, box-shadow 0.2s; + + &:hover { + border: 1px solid $tangerine; + } + + &.p-focus { + box-shadow: 0 0 0 0.1rem $dark-tangerine-1; + border-color: $dark-tangerine-1; + } + + .p-multiselect-label { + &.p-placeholder { + color: $grey; + } + } + + .p-multiselect-panel { + .p-multiselect-header { + color: $black; + } + + .p-multiselect-items-wrapper { + .p-multiselect-items { + padding: 0; + + .p-multiselect-item { + color: $black; + + &:not(.p-disabled) { + &:not(.p-highlight) { + &:hover { + background: $light-grey; + color: $black; + } + } + } + + &:focus { + box-shadow: unset; + } + + } + } + } + } + } + //datepicker + .p-datepicker { + color: $black; + + .p-datepicker-header { + color: $black; + border-bottom: 2px solid $light-grey; + + .p-datepicker-prev, .p-datepicker-next { + color: $black; + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + + &:hover { + background: $light-grey; + } + } + } + + .p-datepicker-calendar-container { + table { + td { + &.p-datepicker-today { + span { + color: $black; + background: $light-grey; + + &.p-highlight { + background: $light-tangerine-2; + color: $black; + + &:hover { + color: $black; + } + } + + &:hover { + color: $white; + } + } + } + + span { + transition: 0.2s; + color: $black; + + &:hover { + background: $grey; + color: $white; + } + } + } + } + + .p-highlight { + background: $light-tangerine-2; + + &:hover { + background: $light-tangerine-2; + color: $black; + } + } + } + + .p-datepicker-buttonbar { + border-top: 2px solid $light-grey; + + .p-button-set-today { + background: $light-grey; + color: $black; + border: 1px solid $light-grey; + + &:hover { + background: $grey; + color: $white; + border: 1px solid $grey; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-grey; + } + } + + .p-button-clear-date { + background: $light-tangerine-2; + color: $black; + border: 1px solid $light-tangerine-2; + + &:hover { + background: $light-tangerine-1; + color: $black; + border: 1px solid $light-tangerine-1; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + } + } + } +} + +//breadcrumb +.p-breadcrumb { + border: 2px solid $black; + background: $black; + border-radius: 2px; + padding: 5px 15px; + + ul { + font-size: 0.8rem; + + li { + &.p-breadcrumb-home { + + .p-menuitem-link { + &:hover { + .p-menuitem-icon { + color: $orange; + } + } + + &:focus { + box-shadow: unset; + border-radius: unset; + } + } + } + + &.p-breadcrumb-chevron { + color: $white; + font-size: 0.8rem; + } + + .p-menuitem-link { + + &:hover { + .p-menuitem-icon { + color: $orange; + } + + .p-menuitem-text { + color: $orange; + } + } + + &:focus { + box-shadow: unset; + border-radius: unset; + } + + .p-menuitem-icon { + color: $white; + transition: 0.2s; + font-size: 0.8rem; + margin-right: 0.5rem; + } + + .p-menuitem-text { + color: $white; + transition: 0.2s; + } + } + } + } +} + +//accordion +.p-accordion { + .p-accordion-tab { + .p-accordion-header { + + .p-accordion-header-link { + transition: 0.2s; + + &:focus { + box-shadow: unset; + } + + } + + &:not(.p-disabled) { + .p-accordion-header-link { + background: $light-grey; + color: $black; + } + + &.p-highlight { + .p-accordion-header-link { + background: $black; + color: $white; + border-color: $black; + + .accrordion-title { + width: 100%; + } + + .p-button-accordion-tab { + background: none; + color: $white; + border: 1px solid $white; + + &:hover { + background: none; + color: $tangerine; + border: 1px solid $tangerine; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-1; + } + + &.p-button-outlined { + background: none; + color: $white; + border: 2px solid $white; + + &:hover { + color: $tangerine; + border: 2px solid $tangerine; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-1; + } + } + } + } + + &:hover { + .p-accordion-header-link { + background: $light-grey; + color: $black; + border-color: $black; + } + + .p-button-accordion-tab { + color: $black; + border: 1px solid $black; + + &.p-button-outlined { + color: $black; + border: 2px solid $black; + } + } + } + } + + &:not(.p-highlight) { + .p-accordion-header-link { + background: $light-grey; + color: $black; + border-color: $black; + } + + &:hover { + .p-accordion-header-link { + background: $black; + color: $white; + border-color: $black; + } + } + } + } + } + + .p-accordion-content { + border: 1px solid $black; + border-top: 0px; + color: $black; + padding: 2rem; + } + } +} + +//toolbar +.p-toolbar { + color: $black; + border: 1px solid $medium-grey; + background: $light-grey; +} + +//Dialog Mask +:host ::ng-deep .p-dialog-mask { + background: rgba($black, 0.5); +} + +//Dialog +.p-dialog { + //confirm dialog + &.p-confirm-dialog { + .p-confirm-dialog-message { + margin-left: 0px; + } + } + //dialog-header + .p-dialog-header { + color: $black; + + .p-dialog-header-icon { + color: $black; + + &:enabled { + &:hover { + color: $black; + background: $light-grey; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + } + } + } + //dialog-content + .p-dialog-content { + color: $black; + + .p-dropdown { + border: 1px solid $black; + transition: border 0.2s, box-shadow 0.2s; + + &:hover { + border: 1px solid $tangerine; + } + + &.p-focus { + box-shadow: 0 0 0 0.1rem $dark-tangerine-1; + border-color: $dark-tangerine-1; + } + + .p-dropdown-label { + &.p-placeholder { + color: $grey; + } + } + + .p-inputtext { + border: 1px solid transparent; + padding: 0.4rem 1rem; + + &:hover { + border: 1px solid transparent; + } + } + + .p-dropdown-trigger { + color: $black; + } + } + + .p-inputtext { + border: 1px solid $black; + transition: border 0.2s, box-shadow 0.2s; + color: $black; + padding: 0.5rem 1rem; + + &:hover { + border: 1px solid $tangerine; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $dark-tangerine-1; + border-color: $dark-tangerine-1; + } + } + } + + .p-dialog-footer { + text-align: center; + } +} + +//datatable +.p-datatable { + + .p-paginator { + padding: 1rem 1rem; + color: $black; + border: none !important; + + .p-paginator-element { + &:not(.p-disabled) { + + &:not(.p-highlight) { + + &:hover { + background: $light-grey; + } + + &:focus { + box-shadow: 0 0 0 0.1rem $light-grey; + } + } + + &.p-highlight { + background: $light-tangerine-2; + border-color: $light-tangerine-2; + + &:focus { + box-shadow: 0 0 0 0.1rem $light-tangerine-2; + } + } + } + } + } + + &.p-datatable-hoverable-rows { + .p-datatable-tbody { + tr:not(.p-highlight) { + &:hover { + background: $light-grey; + color: $black; + } + } + } + } + + .p-datatable-thead { + + tr { + + th { + text-align: center; + border-width: 1px !important; + border-style: solid; + border-left-color: $light-grey; + border-top-color: $light-grey; + border-bottom-color: $light-grey; + border-right-color: $light-grey; + font-weight: 600; + color: $white; + background: $dark-orange-1; + + &:first-child { + border-left-color: $light-grey; + } + + &:last-child { + border-right-color: $light-grey; + } + } + } + } + + .p-datatable-tbody { + tr { + color: $black; + transition: 0.2s; + + &:hover { + &:nth-child(even) { + td { + background: $light-grey; + } + } + } + + &:nth-child(even) { + td { + background: #f8f8f8; + } + } + + td { + border: 1px solid $light-grey; + text-align: center; + transition: 0.2s; + padding: 0.5rem 0.5rem; + } + } + } +} diff --git a/_media.scss b/_media.scss new file mode 100644 index 0000000..208882c --- /dev/null +++ b/_media.scss @@ -0,0 +1,32 @@ +/* You can add media styles */ + +@media (max-width: 991px) { + + //header + .header { + padding: 10px; + } + + //main-content + .main-content { + padding: 10px; + } + +} + +@media (max-width: 961px) { + + .hidden-left-panel { + display: none !important; + } + +} + +@media (min-width: 961px) { + + .hidden-horizontal-menu { + display: none !important; + } + +} + diff --git a/_pallete.scss b/_pallete.scss new file mode 100644 index 0000000..9e55a37 --- /dev/null +++ b/_pallete.scss @@ -0,0 +1,65 @@ +/* You can add reusable colors */ + +// Primary +$dark-orange-1: #933401; +$dark-orange-2: #571F01; +$orange: #D04A02; +$light-orange-1: #FD6412; +$light-orange-2: #FEB791; + +$dark-tangerine-1: #AE6800; +$dark-tangerine-2: #714300; +$tangerine: #EB8C00; +$light-tangerine-1: #FFA929; +$light-tangerine-2: #FFDCA9; + +$dark-yellow-1: #C28A00; +$dark-yellow-2: #855F00; +$yellow: #FFB600; +$light-yellow-1: #FFC83D; +$light-yellow-2: #FFECBD; + +$dark-rose-1: #A43E50; +$dark-rose-2: #6E2A35; +$rose: #DB536A; +$light-rose-1: #E27588; +$light-rose-2: #F1BAC3; + +$dark-red-1: #AA2417; +$dark-red-2: #741910; +$red: #E0301E; +$light-red-1: #E86153; +$Light-red-2: #F7C8C4; + +$white: white; +$black: black; +$dark-grey: #2D2D2D; +$medium-grey: #464646; +$grey: #7D7D7D; +$light-grey: #DEDEDE; + +// Secondary +$dark-purple-1: #6A1CE2; +$dark-purple-2: #4B06B2; +$purple: #9013FE; +$light-purple-1: #B15AFE; +$light-purple-2: #DEB8FF; + +$dark-blue-1: #0060D7; +$dark-blue-2: #003DAB; +$blue: #0089EB; +$light-blue-1: #4DACF1; +$light-blue-2: #B3DCF9; + +$dark-green-1: #2C8646; +$dark-green-2: #175C2C; +$green: #4EB523; +$light-green-1: #86DB4F; +$light-green-2: #C4FC9F; +$rose-for-white-type: #D93954; + +// Status Colors +$status-red: #E0301E; +$status-yellow: #FFB600; +$status-green: #175C2C; + diff --git a/app/app-routing.module.ts b/app/app-routing.module.ts new file mode 100644 index 0000000..1496bff --- /dev/null +++ b/app/app-routing.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +const routes: Routes = []; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } diff --git a/app/app.component.html b/app/app.component.html new file mode 100644 index 0000000..f5052ee --- /dev/null +++ b/app/app.component.html @@ -0,0 +1,9 @@ + +
+
+
+ + +
+
+
diff --git a/app/app.component.scss b/app/app.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/app.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/app.component.spec.ts b/app/app.component.spec.ts new file mode 100644 index 0000000..b2929bb --- /dev/null +++ b/app/app.component.spec.ts @@ -0,0 +1,35 @@ +import { TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + RouterTestingModule + ], + declarations: [ + AppComponent + ], + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'RTA-Admin-UI'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('RTA-Admin-UI'); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.nativeElement; + expect(compiled.querySelector('.content span').textContent).toContain('RTA-Admin-UI app is running!'); + }); +}); diff --git a/app/app.component.ts b/app/app.component.ts new file mode 100644 index 0000000..3f8e304 --- /dev/null +++ b/app/app.component.ts @@ -0,0 +1,19 @@ +import { AuthService } from './shared/services/auth.service'; +import { Component, OnInit } from '@angular/core'; +import { PrimeNGConfig } from 'primeng/api'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent implements OnInit { + + constructor(private primengConfig: PrimeNGConfig, private authService: AuthService) { } + + + ngOnInit(): void { + this.primengConfig.ripple = true; + this.authService.initializeOAuth2Login(); + } +} diff --git a/app/app.module.ts b/app/app.module.ts new file mode 100644 index 0000000..59f73a4 --- /dev/null +++ b/app/app.module.ts @@ -0,0 +1,61 @@ +import { ToastModule } from 'primeng/toast'; +import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc'; +import { environment } from './../environments/environment'; +import { HttpClientModule, HttpClient } from '@angular/common/http'; +import { BrowserModule } from '@angular/platform-browser'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NgModule } from '@angular/core'; + +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { CoreModule } from './core/core.module'; +import { FeaturesModule } from './features/features.module'; +import { SharedModule } from './shared/shared.module'; +import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; +import { ConfirmationService, MessageService } from 'primeng/api'; +import { SearchListStateService } from './shared/back-button/search-list-state.service'; + +export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader { + return new TranslateHttpLoader(http); +} + +// Settings localStorage as OAuth2 storage. +// We need a factory, since localStorage is not available during AOT build time. +export function storageFactory(): OAuthStorage { + return localStorage; +} + + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + BrowserAnimationsModule, + AppRoutingModule, + CoreModule, + FeaturesModule, + SharedModule, + HttpClientModule, + ToastModule, + OAuthModule.forRoot({ + resourceServer: { + allowedUrls: [environment.baseApiUrl], + sendAccessToken: true + } + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient] + }, + defaultLanguage: environment.defaultLanguage, + }), + ], + providers: [ConfirmationService, { provide: OAuthStorage, useFactory: storageFactory }, MessageService, SearchListStateService], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/app/core/core.module.ts b/app/core/core.module.ts new file mode 100644 index 0000000..ee8c617 --- /dev/null +++ b/app/core/core.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { SharedModule } from 'primeng/api'; +import { PrimengSharedModule } from './../shared/primeng-shared/primeng-shared.module'; +import { ErrorHandlingModule } from './error-handling/error-handling.module'; + +import { HeaderComponent } from './header/header.component'; +import { MainPageComponent } from './main-page/main-page.component'; + +@NgModule({ + declarations: [HeaderComponent, MainPageComponent], + imports: [ + CommonModule, + FormsModule, + PrimengSharedModule, + SharedModule, + ErrorHandlingModule + ], + exports: [ + HeaderComponent, + MainPageComponent + ] +}) +export class CoreModule { } diff --git a/app/core/error-handling/error-handling.module.ts b/app/core/error-handling/error-handling.module.ts new file mode 100644 index 0000000..c5482ca --- /dev/null +++ b/app/core/error-handling/error-handling.module.ts @@ -0,0 +1,15 @@ +import { HttpErrorInterceptor } from './http-error.interceptor'; +import { GlobalErrorHandler } from './global-error-handler'; +import { NgModule, ErrorHandler } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; + +@NgModule({ + declarations: [], + imports: [CommonModule], + providers: [ + { provide: ErrorHandler, useClass: GlobalErrorHandler }, + { provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true } + ] +}) +export class ErrorHandlingModule { } diff --git a/app/core/error-handling/global-error-handler.ts b/app/core/error-handling/global-error-handler.ts new file mode 100644 index 0000000..befbfab --- /dev/null +++ b/app/core/error-handling/global-error-handler.ts @@ -0,0 +1,21 @@ +import { environment } from 'src/environments/environment'; +import { HttpErrorResponse } from '@angular/common/http'; +import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service'; +import { ErrorHandler, Injectable, NgZone } from '@angular/core'; + +@Injectable() +export class GlobalErrorHandler implements ErrorHandler { + constructor(private errorHandlingService: ErrorHandlingService, private zone: NgZone) {} + + handleError(error: Error): void { + + this.zone.run(() => { + if (!(error instanceof HttpErrorResponse) && environment.enableGlobalErrorToast){ + this.errorHandlingService.showErrorMessage(error.message); + } + }); + + + console.error('Error from global error handler', error); + } +} diff --git a/app/core/error-handling/http-error.interceptor.ts b/app/core/error-handling/http-error.interceptor.ts new file mode 100644 index 0000000..5ec5c90 --- /dev/null +++ b/app/core/error-handling/http-error.interceptor.ts @@ -0,0 +1,34 @@ +import { ErrorHandlingService } from './../../shared/services/error-handling/error-handling.service'; +import { + HttpHandler, + HttpRequest, + HttpEvent, + HttpErrorResponse, + HttpInterceptor +} from '@angular/common/http'; +import { Observable, throwError } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { Injectable, Injector } from '@angular/core'; + +@Injectable() +export class HttpErrorInterceptor implements HttpInterceptor { + constructor( + private injector: Injector, + ) {} + + intercept( + request: HttpRequest, + next: HttpHandler + ): Observable> { + return next.handle(request).pipe( + catchError((error: HttpErrorResponse) => { + // We don't inject an HttpClient dependent service directly to an http interceptor's constructor, + // or we'll get cyclic dependency errors + const errorHandlingService = this.injector.get(ErrorHandlingService); + + errorHandlingService.showHttpResponseError(error); + return throwError(error); + }) + ) as Observable>; + } +} diff --git a/app/core/header/header.component.html b/app/core/header/header.component.html new file mode 100644 index 0000000..771e3dc --- /dev/null +++ b/app/core/header/header.component.html @@ -0,0 +1,14 @@ +
+
+
+ + + +
+
+
+
+ +
+
+
diff --git a/app/core/header/header.component.scss b/app/core/header/header.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/core/header/header.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/core/header/header.component.spec.ts b/app/core/header/header.component.spec.ts new file mode 100644 index 0000000..f872216 --- /dev/null +++ b/app/core/header/header.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { HeaderComponent } from './header.component'; + +describe('HeaderComponent', () => { + let component: HeaderComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ HeaderComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/core/header/header.component.ts b/app/core/header/header.component.ts new file mode 100644 index 0000000..ab91c5b --- /dev/null +++ b/app/core/header/header.component.ts @@ -0,0 +1,28 @@ +import { Language } from './../../shared/models/language.interface'; +import { environment } from './../../../environments/environment'; +import { AuthService } from './../../shared/services/auth.service'; +import { Component, OnInit } from '@angular/core'; +import { MenuItem } from 'primeng/api'; +import { TranslateService } from '@ngx-translate/core'; +import {Router} from "@angular/router"; + +@Component({ + selector: 'app-header', + templateUrl: './header.component.html', + styleUrls: ['./header.component.scss'] +}) +export class HeaderComponent implements OnInit { + + languages: Language[] = environment.languages; + selectedLang = environment.defaultLanguage; + + constructor(private auth: AuthService, private translateService: TranslateService, private router: Router) { + } + + ngOnInit(): void { + } + + changeLanguage($event): void { + this.translateService.use($event); + } +} diff --git a/app/core/main-page/main-page.component.html b/app/core/main-page/main-page.component.html new file mode 100644 index 0000000..6c46b1d --- /dev/null +++ b/app/core/main-page/main-page.component.html @@ -0,0 +1 @@ + diff --git a/app/core/main-page/main-page.component.scss b/app/core/main-page/main-page.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/core/main-page/main-page.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/core/main-page/main-page.component.spec.ts b/app/core/main-page/main-page.component.spec.ts new file mode 100644 index 0000000..a529e24 --- /dev/null +++ b/app/core/main-page/main-page.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MainPageComponent } from './main-page.component'; + +describe('MainPageComponent', () => { + let component: MainPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MainPageComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MainPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/core/main-page/main-page.component.ts b/app/core/main-page/main-page.component.ts new file mode 100644 index 0000000..cc7bddf --- /dev/null +++ b/app/core/main-page/main-page.component.ts @@ -0,0 +1,22 @@ +import { Router } from '@angular/router'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-main-page', + templateUrl: './main-page.component.html', + styleUrls: ['./main-page.component.scss'] +}) +export class MainPageComponent implements OnInit { + + constructor(private auth: AuthService, private router: Router) { } + + ngOnInit(): void { + this.auth.authStatusChanged.subscribe((isAuthenticated) => { + if (!isAuthenticated) { + this.router.navigateByUrl('login'); + } + }); + } + +} diff --git a/app/features/administration/administration.component.html b/app/features/administration/administration.component.html new file mode 100644 index 0000000..65b6867 --- /dev/null +++ b/app/features/administration/administration.component.html @@ -0,0 +1,26 @@ +
+ + + +
+

{{'ADMINISTRATION' | translate}}

+ +
+ +
+ + +

{{section.title}}

+
+
+ +
+ +
+
+
+
+
+
+ +
diff --git a/app/features/administration/administration.component.scss b/app/features/administration/administration.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/administration.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/administration.component.spec.ts b/app/features/administration/administration.component.spec.ts new file mode 100644 index 0000000..492f119 --- /dev/null +++ b/app/features/administration/administration.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdministrationComponent } from './administration.component'; + +describe('WelcomeComponent', () => { + let component: AdministrationComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AdministrationComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AdministrationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/administration.component.ts b/app/features/administration/administration.component.ts new file mode 100644 index 0000000..bf92252 --- /dev/null +++ b/app/features/administration/administration.component.ts @@ -0,0 +1,103 @@ +import { AuthService } from './../../shared/services/auth.service'; +import { Component, OnInit } from '@angular/core'; +import { CardItem } from './../../shared/models/card-item.interface'; +import { AdministrationSection } from './../../shared/models/administration-section.interface'; + +@Component({ + selector: 'app-administration', + templateUrl: './administration.component.html', + styleUrls: ['./administration.component.scss'] +}) +export class AdministrationComponent implements OnInit { + + data: CardItem; + adminSections: AdministrationSection[]; + + constructor(public authService: AuthService) { } + + ngOnInit(): void { + this.initializeData(); + } + + initializeData() { + this.adminSections = [ + { + title: 'Monitoring', + subSections: [ + { + title: 'Downloads Monitoring', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-desktop', + path: '/pages/administration/downloads-monitoring' + } + ] + }, + { + title: 'Configurations', + subSections: [ + { + title: 'Categories Managenent', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-cog', + path: '/pages/administration/categories-management' + }, + { + title: 'Templates Managenent', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-cog', + path: '/pages/administration/templates-management' + }, + { + title: 'Verification Managenent', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-cog', + path: '/pages/administration/verification-management' + }, + { + title: 'Configurator', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-cog', + path: '/pages/administration/configurator' + } + ] + }, + { + title: 'Access', + subSections: [ + { + title: 'Users Managenent', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-key', + path: '/pages/administration/users-management' + }, + { + title: 'Roles Managenent', + subtitle: 'View File\'s Downloading Process and Manage...', + headerImage: 'pi-image', + footerImage: 'pi-key', + path: '/pages/administration/roles-management' + } + ] + }, + { + title: 'Exception Handling', + subSections: [ + { + title: 'Application Level Exceptions', + subtitle: 'View Application Level exceptions thrown by the Platform', + headerImage: 'pi-image', + footerImage: 'pi-exclamation-triangle', + path: '/pages/administration/application-level-exceptions' + } + ] + } + ]; + } + +} diff --git a/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.html b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.html new file mode 100644 index 0000000..0bf8424 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.html @@ -0,0 +1,18 @@ + + +
+      {{this.trace}}
+    
+
+ + + + +
diff --git a/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.scss b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.scss new file mode 100644 index 0000000..0da3d37 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.scss @@ -0,0 +1,13 @@ +@import 'src/styles'; + +pre { + width: 900px !important; +} + +@media (max-width: 991px) { + + pre { + width: 420px !important; + } + +} diff --git a/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.spec.ts b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.spec.ts new file mode 100644 index 0000000..e691e01 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApplicationLevelDialogComponent } from './application-level-dialog.component'; + +describe('ApplicationLevelDialogComponent', () => { + let component: ApplicationLevelDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApplicationLevelDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApplicationLevelDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.ts b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.ts new file mode 100644 index 0000000..d35eb54 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-dialog/application-level-dialog.component.ts @@ -0,0 +1,24 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service'; + +@Component({ + selector: 'app-application-level-dialog', + templateUrl: './application-level-dialog.component.html', + styleUrls: ['./application-level-dialog.component.scss'] +}) +export class ApplicationLevelDialogComponent implements OnInit { + @Input() displayDialog: boolean; + @Input() header: string; + @Input() trace: string; + @Output() cancelled = new EventEmitter(); + + constructor() { } + + ngOnInit(): void { + } + + cancel() { + this.cancelled.emit(true); + } + +} diff --git a/app/features/administration/application-level-exceptions/application-level-exceptions.component.html b/app/features/administration/application-level-exceptions/application-level-exceptions.component.html new file mode 100644 index 0000000..4a792d8 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-exceptions.component.html @@ -0,0 +1,29 @@ +
+
+ +

{{'APPLICATION-LEVEL-EXCEPTIONS' | translate}}

+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
diff --git a/app/features/administration/application-level-exceptions/application-level-exceptions.component.scss b/app/features/administration/application-level-exceptions/application-level-exceptions.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-exceptions.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/application-level-exceptions/application-level-exceptions.component.spec.ts b/app/features/administration/application-level-exceptions/application-level-exceptions.component.spec.ts new file mode 100644 index 0000000..f81b6da --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-exceptions.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApplicationLevelExceptionsComponent } from './application-level-exceptions.component'; + +describe('ApplicationLevelExceptionsComponent', () => { + let component: ApplicationLevelExceptionsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApplicationLevelExceptionsComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApplicationLevelExceptionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/application-level-exceptions/application-level-exceptions.component.ts b/app/features/administration/application-level-exceptions/application-level-exceptions.component.ts new file mode 100644 index 0000000..288afcc --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-exceptions.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { Page } from 'src/app/shared/models/paging/page.interface'; +import { SystemException } from 'src/app/shared/models/system-exception.interface'; + +@Component({ + selector: 'app-application-level-exceptions', + templateUrl: './application-level-exceptions.component.html', + styleUrls: ['./application-level-exceptions.component.scss'] +}) +export class ApplicationLevelExceptionsComponent implements OnInit { + + searchResults: Page = null; + paginationEventRequest: { page: number, offset: number } ; + loading: boolean; + + constructor() { } + + ngOnInit(): void { + } + + searchMade(results) { + this.searchResults = results; + } + + passloading(loading) { + this.loading = loading; + } + + paginationEvent(paginationEvent) { + this.paginationEventRequest = paginationEvent; + } + +} diff --git a/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.html b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.html new file mode 100644 index 0000000..17f5531 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.html @@ -0,0 +1,14 @@ + + +
+ + + + +
+
diff --git a/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.scss b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.spec.ts b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.spec.ts new file mode 100644 index 0000000..e8e2dbb --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApplicationLevelSearchFormComponent } from './application-level-search-form.component'; + +describe('ApplicationLevelSearchFormComponent', () => { + let component: ApplicationLevelSearchFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApplicationLevelSearchFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApplicationLevelSearchFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.ts b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.ts new file mode 100644 index 0000000..8a83912 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-search-form/application-level-search-form.component.ts @@ -0,0 +1,59 @@ +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { Page } from 'src/app/shared/models/paging/page.interface'; +import { SystemException } from 'src/app/shared/models/system-exception.interface'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; +import { environment } from 'src/environments/environment'; +import { ApplicationLevelFormComponent } from '../../forms/application-level-form/application-level-form.component'; + +@Component({ + selector: 'app-application-level-search-form', + templateUrl: './application-level-search-form.component.html', + styleUrls: ['./application-level-search-form.component.scss'] +}) +export class ApplicationLevelSearchFormComponent implements OnInit { + + @Input() set paginationEventRequest(value: { page: number, offset: number }) { + + // This setter may be called on page setup without arguments. + if (!value) { + return; + } + // this._value = Object.assign(value); + this.search(value.page, value.offset); + } + + @Output() searchResults = new EventEmitter>(); + @Output() loading = new EventEmitter(); + @ViewChild(ApplicationLevelFormComponent) + private searchCriteriaForm: ApplicationLevelFormComponent; + _value : {page: number , offset: number}; + + constructor(private applicationLevelService: ApplicationLevelExceptionService,private errorHandlingService: ErrorHandlingService, private auth: AuthService) { } + + ngOnInit(): void { + } + + search(pageNumber = 0, pageSize = 10) { + this.loading.emit(true); + this.applicationLevelService.searchByCriteriaPaged(pageNumber, pageSize, this.searchCriteriaForm?.formValue(), 'search').subscribe((results: Page) => { + this.searchResults.emit(results); + this.loading.emit(false); + }, + err => { + this.errorHandlingService.showHttpResponseError(err) + this.loading.emit(false); + }); + } + + canPreviewLevelExceptions(): boolean { + return this.auth.userHasRightForClient(USER_RIGHTS.K01, environment.globalRightsClientID); + } + + clear() { + this.searchCriteriaForm.resetForm(); + } + +} diff --git a/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.html b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.html new file mode 100644 index 0000000..2570687 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.html @@ -0,0 +1,54 @@ + + + + + Date-Time + Process Id + Job Name + File Code + iPower Client Code + Message + Cause + Trace + + + + + {{systemException.creationDatetime|date: "dd/MM/yyyy HH:mm"}} + {{systemException.processId}} + {{systemException.jobName}} + {{systemException.dmsFileCode}} + {{systemException.clientId}} + {{systemException.message}} + {{systemException.cause}} + + + + + + + + + + + diff --git a/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.scss b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.spec.ts b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.spec.ts new file mode 100644 index 0000000..8f8c650 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApplicationLevelTableComponent } from './application-level-table.component'; + +describe('ApplicationLevelTableComponent', () => { + let component: ApplicationLevelTableComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApplicationLevelTableComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApplicationLevelTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.ts b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.ts new file mode 100644 index 0000000..fef9646 --- /dev/null +++ b/app/features/administration/application-level-exceptions/application-level-table/application-level-table.component.ts @@ -0,0 +1,64 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { LazyLoadEvent } from 'primeng/api'; +import { Page } from 'src/app/shared/models/paging/page.interface'; +import { SystemException } from 'src/app/shared/models/system-exception.interface'; +import { ApplicationLevelExceptionService } from 'src/app/shared/services/administration/application-level-exception.service'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; + +@Component({ + selector: 'app-application-level-table', + templateUrl: './application-level-table.component.html', + styleUrls: ['./application-level-table.component.scss'] +}) +export class ApplicationLevelTableComponent implements OnInit { + + @Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface. + @Input() loading: boolean; + @Input() set searchResultsPage(results: Page) { + + // This setter may be called on page setup without arguments. + if (!results) { + return; + } + + this._searchResultsPage = results; + this.totalRecords = results.totalElements; + // this.loading = false; + } + _searchResultsPage: Page; + totalRecords: number; + rows: number = 10; + header: string; + trace: string; + displayTraceDialog: boolean; + + constructor(private errorHandlingService: ErrorHandlingService, private applicationLevelService: ApplicationLevelExceptionService) { } + + ngOnInit(): void { + } + + onLazyLoad(event: LazyLoadEvent) { + let pageToRequest = Math.floor(event.first / event.rows); + let pageSize = event.rows; + this.paginationEvent.emit({ page: pageToRequest, offset: pageSize }); + } + + edit(id: number) { + this.header = "Trace"; + if(id){ + this.applicationLevelService.getById(id).subscribe(result => { + this.trace = result.trace; + this.displayTraceDialog = true; + }, + err => { + this.errorHandlingService.showHttpResponseError(err) + }); + } + } + + cancelEditLevelException() { + this.displayTraceDialog = false; + this.trace = null; + } +} diff --git a/app/features/administration/categories-management/categories-management.component.html b/app/features/administration/categories-management/categories-management.component.html new file mode 100644 index 0000000..fbff52c --- /dev/null +++ b/app/features/administration/categories-management/categories-management.component.html @@ -0,0 +1,53 @@ +
+
+ +

{{'CATEGORIES-MANAGEMENT' | translate}}

+ + + + + +
+ +
+
+ + + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+
diff --git a/app/features/administration/categories-management/categories-management.component.scss b/app/features/administration/categories-management/categories-management.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/categories-management/categories-management.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/categories-management/categories-management.component.spec.ts b/app/features/administration/categories-management/categories-management.component.spec.ts new file mode 100644 index 0000000..9d71e6f --- /dev/null +++ b/app/features/administration/categories-management/categories-management.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CategoriesManagementComponent } from './categories-management.component'; + +describe('CategoriesManagementComponent', () => { + let component: CategoriesManagementComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CategoriesManagementComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CategoriesManagementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/categories-management/categories-management.component.ts b/app/features/administration/categories-management/categories-management.component.ts new file mode 100644 index 0000000..9191526 --- /dev/null +++ b/app/features/administration/categories-management/categories-management.component.ts @@ -0,0 +1,59 @@ +import { environment } from './../../../../environments/environment.prod'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { AuthService } from './../../../shared/services/auth.service'; +import { Category } from 'src/app/shared/models/category.interface'; +import { Component, OnInit } from '@angular/core'; +import { Page } from '../../../shared/models/paging/page.interface'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'app-categories-management', + templateUrl: './categories-management.component.html', + styleUrls: ['./categories-management.component.scss'] +}) +export class CategoriesManagementComponent implements OnInit { + + displayCategoryCreationDialog: boolean = false; + searchResults: Page = null; + paginationEventRequest: { page: number, offset: number } = { page: 10, offset: 0 }; + header: string; + passChange: boolean; + valueOfTableChanged: any; + loading: boolean; + + constructor(private authService: AuthService, private translate: TranslateService) { } + + ngOnInit(): void { + } + + searchMade(results) { + this.searchResults = results; + } + + passLoadingForTable(loading) { + this.loading = loading; + } + + paginationEvent(paginationEvent) { + this.paginationEventRequest = paginationEvent; + } + + canAddNewCategory(): boolean { + return this.authService.userHasRightForClient(USER_RIGHTS.H02, environment.globalRightsClientID); + } + + addCategory(): void { + this.header = this.translate.instant('ADD-NEW-CATEGORY'); + this.displayCategoryCreationDialog = true; + } + + passEvent(passEvent: any) { + if (passEvent) { + this.valueOfTableChanged = passEvent; + } + } + + passloading(loading) { + this.loading = loading; + } +} diff --git a/app/features/administration/categories-management/categories-search-results/categories-search-results.component.html b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.html new file mode 100644 index 0000000..2bd19ce --- /dev/null +++ b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.html @@ -0,0 +1,64 @@ + + + + + + + Document Classification + Category Name + Category Code + + Actions + + + + + {{category.documentClassification.classificationName}} + {{category.categoryName}} + {{category.categoryCode}} + + + + + + + + + + + + diff --git a/app/features/administration/categories-management/categories-search-results/categories-search-results.component.scss b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/categories-management/categories-search-results/categories-search-results.component.spec.ts b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.spec.ts new file mode 100644 index 0000000..95e5839 --- /dev/null +++ b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CategoriesSearchResultsComponent } from './categories-search-results.component'; + +describe('CategoriesSearchResultsComponent', () => { + let component: CategoriesSearchResultsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CategoriesSearchResultsComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CategoriesSearchResultsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/categories-management/categories-search-results/categories-search-results.component.ts b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.ts new file mode 100644 index 0000000..8b89f6a --- /dev/null +++ b/app/features/administration/categories-management/categories-search-results/categories-search-results.component.ts @@ -0,0 +1,103 @@ +import { AuthService } from './../../../../shared/services/auth.service'; +import { environment } from './../../../../../environments/environment.prod'; +import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { Category } from './../../../../shared/models/category.interface'; +import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core'; +import { ConfirmationService, LazyLoadEvent } from 'primeng/api'; +import { Page } from '../../../../shared/models/paging/page.interface'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { TranslateService } from '@ngx-translate/core'; +import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service'; + +@Component({ + selector: 'app-categories-search-results', + templateUrl: './categories-search-results.component.html', + styleUrls: ['./categories-search-results.component.scss'] +}) +export class CategoriesSearchResultsComponent implements OnInit { + + @Output() paginationEvent = new EventEmitter<{ page: number, offset: number }>(); // TODO: Use interface. + @Output() valueChange = new EventEmitter(); + @Input() loading: boolean; + @Input() set searchResultsPage(results: Page) { + + // This setter may be called on page setup without arguments. + if (!results) { + return; + } + + this._searchResultsPage = results; + this.totalRecords = results.totalElements; + } + + _searchResultsPage: Page; + totalRecords: number; + rows: number = 10; + header: string; + + displayEditCategoryDialog: boolean; + categoryToEdit: Category; + + constructor( + private categoriesService: CategoriesService, + private errorHandlingService: ErrorHandlingService, + private authService: AuthService, + private translate: TranslateService, + private confirmationService: ConfirmationService, + private notifications: NotificationsHandlingService + ) { } + + ngOnInit(): void { + } + + onLazyLoad(event: LazyLoadEvent) { + let pageToRequest = Math.floor(event.first / event.rows); + let pageSize = event.rows; + this.paginationEvent.emit({ page: pageToRequest, offset: pageSize }); + } + + edit(category: Category) { + this.header = this.translate.instant('EDIT-CATEGORY'); + this.categoryToEdit = category; + this.displayEditCategoryDialog = true; + } + + cancelEditCategory() { + this.displayEditCategoryDialog = false; + this.categoryToEdit = null; + } + + delete(category: Category): void { + this.confirmationService.confirm({ + accept: () => { + this.categoriesService.delete(category.id).subscribe((success) => { + this.valueChange.emit(success); + this.notifications.showDeleteCategorySuccess(); + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + // Actual logic to perform a confirmation + }, reject: () => { + + } + }); + } + + /* + * UserRights-check Methods + */ + canEditCategories(): boolean { + return this.authService.userHasRightForClient(USER_RIGHTS.H03, environment.globalRightsClientID); + } + + canDeleteCategories(): boolean { + return this.authService.userHasRightForClient(USER_RIGHTS.H04, environment.globalRightsClientID); + } + + passEvent(passEvent : any) { + if(passEvent){ + this.valueChange.emit(passEvent); + } + } +} diff --git a/app/features/administration/categories-management/categories-search/categories-search.component.html b/app/features/administration/categories-management/categories-search/categories-search.component.html new file mode 100644 index 0000000..85d5ee3 --- /dev/null +++ b/app/features/administration/categories-management/categories-search/categories-search.component.html @@ -0,0 +1,15 @@ + + +
+ + + + +
+
diff --git a/app/features/administration/categories-management/categories-search/categories-search.component.scss b/app/features/administration/categories-management/categories-search/categories-search.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/categories-management/categories-search/categories-search.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/categories-management/categories-search/categories-search.component.spec.ts b/app/features/administration/categories-management/categories-search/categories-search.component.spec.ts new file mode 100644 index 0000000..b7b296b --- /dev/null +++ b/app/features/administration/categories-management/categories-search/categories-search.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CategoriesSearchComponent } from './categories-search.component'; + +describe('CategoriesSearchComponent', () => { + let component: CategoriesSearchComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CategoriesSearchComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CategoriesSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/categories-management/categories-search/categories-search.component.ts b/app/features/administration/categories-management/categories-search/categories-search.component.ts new file mode 100644 index 0000000..38dcbce --- /dev/null +++ b/app/features/administration/categories-management/categories-search/categories-search.component.ts @@ -0,0 +1,101 @@ +import { environment } from './../../../../../environments/environment.prod'; +import { ErrorHandlingService } from './../../../../shared/services/error-handling/error-handling.service'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { CategoryFormComponent } from './../../forms/category-form/category-form.component'; +import { Category } from './../../../../shared/models/category.interface'; +import { DocumentClassificationsService } from './../../../../shared/services/administration/document-classifications.service'; +import { Component, OnInit, Output, EventEmitter, Input, ViewChild } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { DocumentClassification } from 'src/app/shared/models/document-classification.interface'; +import { Page } from '../../../../shared/models/paging/page.interface'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; + +@Component({ + selector: 'app-categories-search', + templateUrl: './categories-search.component.html', + styleUrls: ['./categories-search.component.scss'] +}) +export class CategoriesSearchComponent implements OnInit { + + @Input() set paginationEventRequest(value: { page: number, offset: number }) { + + // This setter may be called on page setup without arguments. + if (!value) { + return; + } + this._value = Object.assign(value); + this.search(value.page, value.offset); + } + + @Input() set valueTableChange(results: any) { + if (results) { + this.search(this._value.page, this._value.offset); + } + } + + @Output() searchResults = new EventEmitter>(); + @Output() loading = new EventEmitter(); + @Output() searchInitiated = new EventEmitter(); + @Input() passChange: any; + + @ViewChild(CategoryFormComponent) + private categoryForm: CategoryFormComponent; + _value: { page: number, offset: number }; + lastSearchCriteria: { docClassificationId: number | string, categoryName: string, categoryCode: string }; + + constructor( + private categoriesService: CategoriesService, + private authService: AuthService, + private errorHandlingService: ErrorHandlingService + ) { } + + ngOnInit(): void { + } + + clear() { + this.categoryForm.resetForm(); + } + + searchButtonClicked() { + + // Inform anyone interested there is a new search underway. + this.searchInitiated.emit(true); + + // Remember the search for future pagination/whatever requests. + let categoryFormValue = this.categoryForm.formValue(); + let docClassId = categoryFormValue.documentClassification ? categoryFormValue.documentClassification.classificationId : null; + let catName = categoryFormValue.categoryName; + let catCode = categoryFormValue.categoryCode; + + this.lastSearchCriteria = { + docClassificationId: docClassId ? docClassId : '', + categoryName: catName ? catName : '', + categoryCode: catCode ? catCode : '' + }; + + // Then actually search. + this.search(); + } + + search(pageNumber = 0, pageSize = 10) { +this.loading.emit(true); + + // A search may be issued by the paginationEventRequest setter upon setting up the page. + if (!this.lastSearchCriteria) { + return; + } + + this.categoriesService.searchByCriteriaPaged(pageNumber, pageSize, this.lastSearchCriteria, 'search').subscribe((results: Page) => { + this.searchResults.emit(results); + this.loading.emit(false); + },err => { + this.loading.emit(false); + this.errorHandlingService.showHttpResponseError(err); + }); + } + + canPreviewAllCategories(): boolean { + return this.authService.userHasRightForClient(USER_RIGHTS.H01, environment.globalRightsClientID); + } +} diff --git a/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.html b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.html new file mode 100644 index 0000000..08bb288 --- /dev/null +++ b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.html @@ -0,0 +1,33 @@ + +
+ + +
+
+
+ + + + + + +
+
+
diff --git a/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.scss b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.spec.ts b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.spec.ts new file mode 100644 index 0000000..40aff7d --- /dev/null +++ b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateCategoryDialogComponent } from './create-category-dialog.component'; + +describe('CreateCategoryComponent', () => { + let component: CreateCategoryDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateCategoryDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateCategoryDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.ts b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.ts new file mode 100644 index 0000000..3e5a891 --- /dev/null +++ b/app/features/administration/categories-management/create-category-dialog/create-category-dialog.component.ts @@ -0,0 +1,86 @@ +import { CategoryFormComponent } from './../../forms/category-form/category-form.component'; +import { Category } from './../../../../shared/models/category.interface'; +import { CategoriesService } from '../../../../shared/services/administration/categories.service'; +import { Component, Input, OnInit, Output, EventEmitter, ViewChild } from '@angular/core'; +import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service'; + +@Component({ + selector: 'app-create-category-dialog', + templateUrl: './create-category-dialog.component.html', + styleUrls: ['./create-category-dialog.component.scss'] +}) +export class CreateCategoryDialogComponent implements OnInit { + + @ViewChild(CategoryFormComponent) private categoryForm: CategoryFormComponent; + @Input() displayDialog: boolean; + @Input() header: string; + @Input() categoryToEdit: Category; + @Output() cancelled = new EventEmitter(); + @Output() valueChange = new EventEmitter(); + + displayValidationMessagesEvenIfPristine: boolean; + + constructor(private categoriesService: CategoriesService, + private notificationHandling: NotificationsHandlingService) { } + + ngOnInit(): void { + this.reset(); // Make sure everything is cleanly initialised. + } + + reset() { + this.displayValidationMessagesEvenIfPristine = false; + this.categoryForm?.resetForm(); + } + + onShow() { + // If a categoryToEdit was provided. + if (this.categoryToEdit) { + this.categoryForm.setValue(this.categoryToEdit); + } + } + + cancel() { + this.cancelled.emit(true); + } + + addCategory() { + // If the form is not valid, make sure validator messages are displayed and then return without doing anything. + if (!this.categoryForm.isValid()) { + this.displayValidationMessagesEvenIfPristine = true; + return; + } + + // TODO: What is returned from backend on create()?? + this.categoriesService.createNewCategory(this.categoryForm.formValue()).subscribe(result => { + this.valueChange.emit(result); + this.notificationHandling.showCreateCategorySuccess(); + this.cancel(); + this.notificationHandling.showCreateNewCategorySuccess(); + + }, + error => { + + }); + + } + + editCategory() { + // If the form is not valid, make sure validator messages are displayed and then return without doing anything. + if (!this.categoryForm.isValid()) { + this.displayValidationMessagesEvenIfPristine = true; + return; + } + + // TODO: What is returned from backend on create()?? + // TODO: It's to ugly having to provide the categoryId separately. + this.categoriesService.updateCategory(this.categoryForm.formValue()).subscribe(result => { + this.valueChange.emit(result); + this.cancel(); + this.notificationHandling.showUpdateCategorySuccess(); + + }, + error => { + + }); + } +} diff --git a/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.html b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.html new file mode 100644 index 0000000..6f604d8 --- /dev/null +++ b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.html @@ -0,0 +1,3 @@ + + + diff --git a/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.scss b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.spec.ts b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.spec.ts new file mode 100644 index 0000000..f2b2cee --- /dev/null +++ b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfiguratorEditValueComponent } from './configurator-edit-value.component'; + +describe('ConfiguratorEditValueComponent', () => { + let component: ConfiguratorEditValueComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfiguratorEditValueComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfiguratorEditValueComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.ts b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.ts new file mode 100644 index 0000000..c60bfbe --- /dev/null +++ b/app/features/administration/configurator/configurator-edit-value/configurator-edit-value.component.ts @@ -0,0 +1,28 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {ConfiguratorParameter} from "../../../../shared/models/configurator-parameter.interface"; + +@Component({ + selector: 'app-configurator-edit-value', + templateUrl: './configurator-edit-value.component.html', + styleUrls: ['./configurator-edit-value.component.scss'] +}) +export class ConfiguratorEditValueComponent implements OnInit { + + @Input() editParameterRequestInput: ConfiguratorParameter; + @Output() newConfiguratorParameter = new EventEmitter(); + + selectedParameter: ConfiguratorParameter = null; + + + constructor() { } + + ngOnInit(): void { + console.log('editParameterRequestInput in edit: ' + JSON.stringify(this.editParameterRequestInput)); + } + + passValueChange(newConfigurator: ConfiguratorParameter) { + this.newConfiguratorParameter.emit(newConfigurator); + } + + +} diff --git a/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.html b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.html new file mode 100644 index 0000000..c7b5995 --- /dev/null +++ b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.html @@ -0,0 +1,38 @@ + + + + + + + Parameter Name + Parameter Type + Parameter Value + + + + + + + + {{parameter.configurationVariable}} + {{parameter.variableType}} + + {{parameter.integerValue}}
+ {{parameter.stringValue}}
+ + + + +
+
+ +
diff --git a/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.scss b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.spec.ts b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.spec.ts new file mode 100644 index 0000000..528eb47 --- /dev/null +++ b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfiguratorListOfParametersComponent } from './configurator-list-of-parameters.component'; + +describe('ConfiguratorListOfParametersComponent', () => { + let component: ConfiguratorListOfParametersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfiguratorListOfParametersComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfiguratorListOfParametersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.ts b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.ts new file mode 100644 index 0000000..0669164 --- /dev/null +++ b/app/features/administration/configurator/configurator-list-of-parameters/configurator-list-of-parameters.component.ts @@ -0,0 +1,40 @@ +import {AfterViewChecked, AfterViewInit, Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {ConfiguratorParameter} from '../../../../shared/models/configurator-parameter.interface'; +import {Page} from '../../../../shared/models/paging/page.interface'; +import {LazyLoadEvent} from 'primeng/api'; + +@Component({ + selector: 'app-configurator-list-of-parameters', + templateUrl: './configurator-list-of-parameters.component.html', + styleUrls: ['./configurator-list-of-parameters.component.scss'] +}) +export class ConfiguratorListOfParametersComponent implements OnInit { + + @Input() parametersListInput: ConfiguratorParameter[]; + @Input() loadingInput: boolean; + @Output() editEventRequest = new EventEmitter(); + + editParameterRequest: ConfiguratorParameter; + parametersList: ConfiguratorParameter[]; + selectedParameterRequest: ConfiguratorParameter; + totalRecords: number; + rows = 10; + + constructor() { } + + ngOnInit(): void { + const initParameter: ConfiguratorParameter = { + configurationId: null, + configurationVariable: null, + variableType: null, + integerValue: null, + stringValue: null + }; + this.editEventRequest.emit(initParameter); + } + + passSelectedConfigurator(parameter: ConfiguratorParameter) { + this.editEventRequest.emit(parameter); + } + +} diff --git a/app/features/administration/configurator/configurator.component.html b/app/features/administration/configurator/configurator.component.html new file mode 100644 index 0000000..4f760f3 --- /dev/null +++ b/app/features/administration/configurator/configurator.component.html @@ -0,0 +1,27 @@ +
+
+ +

{{'CONFIGURATOR' | translate}}

+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
diff --git a/app/features/administration/configurator/configurator.component.scss b/app/features/administration/configurator/configurator.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/configurator/configurator.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/configurator/configurator.component.spec.ts b/app/features/administration/configurator/configurator.component.spec.ts new file mode 100644 index 0000000..bb442f4 --- /dev/null +++ b/app/features/administration/configurator/configurator.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfiguratorComponent } from './configurator.component'; + +describe('ConfiguratorComponent', () => { + let component: ConfiguratorComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfiguratorComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfiguratorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/configurator/configurator.component.ts b/app/features/administration/configurator/configurator.component.ts new file mode 100644 index 0000000..b50a139 --- /dev/null +++ b/app/features/administration/configurator/configurator.component.ts @@ -0,0 +1,51 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; +import {ConfiguratorParameter} from '../../../shared/models/configurator-parameter.interface'; +import {ConfiguratorService} from "../../../shared/services/administration/configurator.service"; + +@Component({ + selector: 'app-configurator', + templateUrl: './configurator.component.html', + styleUrls: ['./configurator.component.scss'] +}) +export class ConfiguratorComponent implements OnInit { + + // @Input() parametersListInput: [ConfiguratorParameter]; + // @Input() editParameterRequestInput: ConfiguratorParameter; + // @Output() editEventRequest = new EventEmitter(); + + parametersList: ConfiguratorParameter[]; + editEventRequest: ConfiguratorParameter; + loading = true; + + constructor(private configuratorService: ConfiguratorService, private errorHandlingService: ErrorHandlingService) { } + + ngOnInit(): void { + + this.initData(); + console.log('this.parametersList: ' + JSON.stringify(this.parametersList)); + } + + initData() { + this.loading = true; + this.configuratorService.getConfiguratorParameters().subscribe(values => { + this.parametersList = values; + this.loading = false; + console.log('IN this.parametersList: ' + JSON.stringify(this.parametersList)); + }, + err => { + this.errorHandlingService.showHttpResponseError(err); + this.loading = false; + }); + } + + editEvent(request) { + this.editEventRequest = request; + } + + passNewConfigurator(newConfigurator: ConfiguratorParameter){ + this.initData(); + + } + +} diff --git a/app/features/administration/forms/application-level-form/application-level-form.component.html b/app/features/administration/forms/application-level-form/application-level-form.component.html new file mode 100644 index 0000000..4834a21 --- /dev/null +++ b/app/features/administration/forms/application-level-form/application-level-form.component.html @@ -0,0 +1,101 @@ +
+
+ +
+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+
+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+
diff --git a/app/features/administration/forms/application-level-form/application-level-form.component.scss b/app/features/administration/forms/application-level-form/application-level-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/application-level-form/application-level-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/application-level-form/application-level-form.component.spec.ts b/app/features/administration/forms/application-level-form/application-level-form.component.spec.ts new file mode 100644 index 0000000..56492ad --- /dev/null +++ b/app/features/administration/forms/application-level-form/application-level-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ApplicationLevelFormComponent } from './application-level-form.component'; + +describe('ApplicationLevelFormComponent', () => { + let component: ApplicationLevelFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ApplicationLevelFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ApplicationLevelFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/application-level-form/application-level-form.component.ts b/app/features/administration/forms/application-level-form/application-level-form.component.ts new file mode 100644 index 0000000..329d07c --- /dev/null +++ b/app/features/administration/forms/application-level-form/application-level-form.component.ts @@ -0,0 +1,111 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { IPowerClient } from 'src/app/shared/models/ipower-client.interface'; +import { SearchSystemException} from 'src/app/shared/models/request/search-system-exceptions.interface'; +import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service'; + +@Component({ + selector: 'app-application-level-form', + templateUrl: './application-level-form.component.html', + styleUrls: ['./application-level-form.component.scss'] +}) +export class ApplicationLevelFormComponent implements OnInit { + + iPowerClientNameSuggestions: any; + iPowerClientCodeSuggestions: any; + private iPowerClientSuggestions: IPowerClient[]; + private selectedIPowerClient: IPowerClient; + + searchCriteriaForm = this.fb.group({ + processId: [null], + clientId: [null], + clientName: [null], + jobName: [null], + dmsFileCode: [null], + dateFrom: [null], + dateTo: [null], + }); + + constructor(private fb: FormBuilder, private iPowerClientsService: IpowerClientsService) { } + + + + ngOnInit(): void { + } + + public formValue(): SearchSystemException { + let formValue: SearchSystemException = { + processId: this.searchCriteriaForm.get('processId').value, + clientId: this.searchCriteriaForm.get('clientId').value, + jobName: this.searchCriteriaForm.get('jobName').value, + dmsFileCode: this.searchCriteriaForm.get('dmsFileCode').value, + dateFrom: this.searchCriteriaForm.get('dateFrom').value, + dateTo: this.searchCriteriaForm.get('dateTo').value + }; + + formValue.dateFrom = new Date(Date.UTC(formValue.dateFrom?.getFullYear(), formValue.dateFrom?.getMonth(), formValue.dateFrom?.getDate())); + formValue.dateTo = new Date(Date.UTC(formValue.dateTo?.getFullYear(), formValue.dateTo?.getMonth(),formValue.dateTo?.getDate() + 1)); + formValue.dateTo?.setMilliseconds(formValue.dateTo?.getMilliseconds() -1); + + + return formValue; + } + + /* + * Auto-suggest & Auto-complete IPower Client + */ + autosuggestIPowerClientName(event): void { + + if (!event.query || event.query.length < 3) { + this.iPowerClientNameSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.name)); + this.iPowerClientNameSuggestions = temp; + }, + err => console.error(err) // TODO: Handle this via a Messaging Service + ); +} + +autosuggestIPowerClientCode(event): void { + + if (event.query.length < 3) { + this.iPowerClientCodeSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.clientCode)); + this.iPowerClientCodeSuggestions = temp; + }, + err => console.error(err) + ); +} + +iPowerClientNameSelected(name: string): void { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name === name); + this.searchCriteriaForm.get('clientId').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : ''); + this.searchCriteriaForm.updateValueAndValidity(); +} + +iPowerClientCodeSelected(code: string): void { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode === code); + this.searchCriteriaForm.get('clientName').patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : ''); + this.searchCriteriaForm.updateValueAndValidity(); +} + +resetForm() { + this.searchCriteriaForm.reset(); +} + +} diff --git a/app/features/administration/forms/category-form/category-form.component.html b/app/features/administration/forms/category-form/category-form.component.html new file mode 100644 index 0000000..b98b145 --- /dev/null +++ b/app/features/administration/forms/category-form/category-form.component.html @@ -0,0 +1,72 @@ +
+
+ +
+ + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+
diff --git a/app/features/administration/forms/category-form/category-form.component.scss b/app/features/administration/forms/category-form/category-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/category-form/category-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/category-form/category-form.component.spec.ts b/app/features/administration/forms/category-form/category-form.component.spec.ts new file mode 100644 index 0000000..37a585f --- /dev/null +++ b/app/features/administration/forms/category-form/category-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CategoryFormComponent } from './category-form.component'; + +describe('CategoryFormComponent', () => { + let component: CategoryFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CategoryFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CategoryFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/category-form/category-form.component.ts b/app/features/administration/forms/category-form/category-form.component.ts new file mode 100644 index 0000000..b53c7da --- /dev/null +++ b/app/features/administration/forms/category-form/category-form.component.ts @@ -0,0 +1,183 @@ +import { Category } from './../../../../shared/models/category.interface'; +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, Validators, FormGroup } from '@angular/forms'; +import { DocumentClassification } from 'src/app/shared/models/document-classification.interface'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; + +@Component({ + selector: 'app-category-form', + templateUrl: './category-form.component.html', + styleUrls: ['./category-form.component.scss'] +}) +export class CategoryFormComponent implements OnInit { + + /* + * Inputs + */ + @Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog. + @Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required. + @Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty. + @Input() autosuggestInputs: boolean = false; + + /* + * Reactive Form + */ + categoryForm = this.fb.group({ + documentClassification: [null], + categoryName: [null], + categoryCode: [null] + }); + + setFormValue: Category = null; + selectedCategory: Category; + + /* + * Other Variables + */ + documentClassificationsList: DocumentClassification[]; + + categoryNameSuggestions: string[]; + categoryCodeSuggestions: string[]; + categorySuggestions: Category[]; + + /* + * Constructor & Initialisers + */ + constructor( + private fb: FormBuilder, + private categoriesService: CategoriesService, + private documentClassificationsService: DocumentClassificationsService, + private errorHandlingService: ErrorHandlingService + ) { } + + ngOnInit(): void { + this.initData(); + this.initValidators() + } + + initData() { + this.documentClassificationsService.getAll().subscribe( + value => this.documentClassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + // TODO: Have this mechanism offer the use of custom validators too. + initValidators() { + + if (!this.requiredFields) { return; } + + // In a true/false case. + if (typeof this.requiredFields == 'boolean') { + // If true, enable the required validator for all controls and sub-controls. + if (this.requiredFields) { + this.setRequiredValidatorRecursively(this.categoryForm); + } + + // If false, do nothing. + return; + } + + // If it was a string array, enable the validators for all provided field-names. TODO: This ONLY supports 1st level controls and not nested ones. + (this.requiredFields).forEach(field => this.categoryForm.controls[field].setValidators(Validators.required)) + } + + setRequiredValidatorRecursively(group: FormGroup) { + Object.keys(group.controls).forEach(key => { + group.controls[key].setValidators(Validators.required); + + if (group.controls[key]['controls']) { + this.setRequiredValidatorRecursively(group.controls[key]) + } + }); + } + + /* + * Auto-suggest & Auto-complete Category + */ + autosuggestCategoryName(event) { + + if (!event.query || event.query.length < 3) { + this.categoryNameSuggestions = []; + return; + } + + let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryName)); + this.categoryNameSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + autosuggestCategoryCode(event) { + + if (event.query.length < 3) { + this.categoryCodeSuggestions = []; + return; + } + + let classId = this.categoryForm.get('documentClassification').value ? this.categoryForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryCode)); + this.categoryCodeSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + categoryNameSelected(name: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name); + this.categoryForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode); + this.categoryForm.updateValueAndValidity(); + } + + categoryCodeSelected(code: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code); + this.categoryForm.get('categoryName').patchValue(this.selectedCategory.categoryName); + this.categoryForm.updateValueAndValidity(); + } + + /* + * API methods + */ + public resetForm(): void { + this.categoryForm.reset(); + } + + public formValue(): Category { + let formValue: Category = { + id: this.setFormValue ? this.setFormValue.id : null, + documentClassification: this.categoryForm.get('documentClassification').value, + categoryName: this.categoryForm.get('categoryName').value, + categoryCode: this.categoryForm.get('categoryCode').value + }; + + return formValue; + } + + public setValue(value: Category): void { + if (!value) { + return; + } + + this.setFormValue = value; + this.categoryForm.get('documentClassification').setValue(value.documentClassification); + this.categoryForm.get('categoryName').setValue(value.categoryName); + this.categoryForm.get('categoryCode').setValue(value.categoryCode); + this.categoryForm.updateValueAndValidity(); + } + + public isValid(): boolean { + return this.categoryForm.valid; + } +} diff --git a/app/features/administration/forms/configurator-form/configurator-form.component.html b/app/features/administration/forms/configurator-form/configurator-form.component.html new file mode 100644 index 0000000..6129b70 --- /dev/null +++ b/app/features/administration/forms/configurator-form/configurator-form.component.html @@ -0,0 +1,60 @@ +
+
+ + +
+ + + + +
+ +
+ + + + +
+ +
+ + + + +
+ +
+ +
+ + +
+ +
diff --git a/app/features/administration/forms/configurator-form/configurator-form.component.scss b/app/features/administration/forms/configurator-form/configurator-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/configurator-form/configurator-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/configurator-form/configurator-form.component.spec.ts b/app/features/administration/forms/configurator-form/configurator-form.component.spec.ts new file mode 100644 index 0000000..4b86384 --- /dev/null +++ b/app/features/administration/forms/configurator-form/configurator-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConfiguratorFormComponent } from './configurator-form.component'; + +describe('ConfiguratorFormComponent', () => { + let component: ConfiguratorFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ConfiguratorFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ConfiguratorFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/configurator-form/configurator-form.component.ts b/app/features/administration/forms/configurator-form/configurator-form.component.ts new file mode 100644 index 0000000..78f136d --- /dev/null +++ b/app/features/administration/forms/configurator-form/configurator-form.component.ts @@ -0,0 +1,69 @@ +import { AfterViewChecked, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder } from '@angular/forms'; +import { ConfiguratorParameter } from '../../../../shared/models/configurator-parameter.interface'; +import { ConfiguratorService } from "../../../../shared/services/administration/configurator.service"; +import { Category } from "../../../../shared/models/category.interface"; +import { Router } from "@angular/router"; +import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { environment } from 'src/environments/environment'; + +@Component({ + selector: 'app-configurator-form', + templateUrl: './configurator-form.component.html', + styleUrls: ['./configurator-form.component.scss'] +}) +export class ConfiguratorFormComponent implements OnInit { + + @Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog. + @Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty. + @Input() editableParameter: ConfiguratorParameter; + @Output() valueChange = new EventEmitter(); + + /* + * Reactive Form + */ + configuratorForm = this.fb.group({ + parameterName: null, + parameterType: null, + parameterValue: null + }); + + constructor(private fb: FormBuilder, private configuratorService: ConfiguratorService, private router: Router, private notificationService: NotificationsHandlingService, + private authService: AuthService) { } + + ngOnInit(): void { + } + + ngOnChanges(): void { + } + + public formValue(): ConfiguratorParameter { + let formValue: ConfiguratorParameter = { + configurationId: this.editableParameter.configurationId, + configurationVariable: this.editableParameter.configurationVariable, + variableType: this.editableParameter.variableType, + integerValue: this.editableParameter.variableType === 'Integer' ? Number(this.configuratorForm.get('parameterValue').value) : null, + stringValue: this.editableParameter.variableType === 'String' ? String(this.configuratorForm.get('parameterValue').value) : null + }; + + return formValue; + } + + updateButtonClicked(): void { + if (this.editableParameter.configurationId !== null) { + this.configuratorService.updateConfiguratorParameter(this.formValue()).subscribe(result => { + this.valueChange.emit(this.formValue()); + this.notificationService.showUpdateConfiguratorParameterSuccess(); + }, + error => { + }); + } + } + + canEditParameterValue(): boolean { + return this.authService.userHasRightForClient(USER_RIGHTS.J01, environment.globalRightsClientID) && this.editableParameter.configurationVariable != null; + } + +} diff --git a/app/features/administration/forms/template-form/template-form.component.html b/app/features/administration/forms/template-form/template-form.component.html new file mode 100644 index 0000000..c2c22ec --- /dev/null +++ b/app/features/administration/forms/template-form/template-form.component.html @@ -0,0 +1,138 @@ +
+
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + +
+ +
+
diff --git a/app/features/administration/forms/template-form/template-form.component.scss b/app/features/administration/forms/template-form/template-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/template-form/template-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/template-form/template-form.component.spec.ts b/app/features/administration/forms/template-form/template-form.component.spec.ts new file mode 100644 index 0000000..af67224 --- /dev/null +++ b/app/features/administration/forms/template-form/template-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TemplateFormComponent } from './template-form.component'; + +describe('TemplateFormComponent', () => { + let component: TemplateFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TemplateFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TemplateFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/template-form/template-form.component.ts b/app/features/administration/forms/template-form/template-form.component.ts new file mode 100644 index 0000000..5dcec04 --- /dev/null +++ b/app/features/administration/forms/template-form/template-form.component.ts @@ -0,0 +1,369 @@ +import { DocumentClassification } from './../../../../shared/models/document-classification.interface'; +import { Category } from './../../../../shared/models/category.interface'; +import { DocumentSubclassificationsService } from './../../../../shared/services/administration/document-subclassifications.service'; +import { DocumentSubclassification } from './../../../../shared/models/document-subclassification.interface'; +import { IPowerClient } from './../../../../shared/models/ipower-client.interface'; +import { Template } from './../../../../shared/models/template.interface'; +import { Component, Input, OnInit } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service'; +import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; + +@Component({ + selector: 'app-template-form', + templateUrl: './template-form.component.html', + styleUrls: ['./template-form.component.scss'] +}) +export class TemplateFormComponent implements OnInit { + + /* + * Inputs + */ + @Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog. + @Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required. + @Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty. + @Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed. + + /* + * Reactive Form + */ + templateForm = this.fb.group({ + documentClassification: [null], + categoryName: [null], + categoryCode: [null], + iPowerClientName: [null], + iPowerClientCode: [null], + documentSubclassification: [null], + abbyyTemplateCode: [null] + }); + initiallySetFormValue: Template; + + /* + * Other Variables + */ + documentClassificationsList: DocumentClassification[]; + + categoryNameSuggestions: string[]; + categoryCodeSuggestions: string[]; + categorySuggestions: Category[]; + selectedCategory: Category; + + iPowerClientNameSuggestions: string[]; + iPowerClientCodeSuggestions: string[]; + iPowerClientSuggestions: IPowerClient[]; + selectedIPowerClient: IPowerClient; + + documentSubclassificationsList: DocumentSubclassification[]; + availableDocumentSubclassifications: DocumentSubclassification[]; + subCategoryCodeDisabled: boolean = true; + + /* + * Constructor & Initialisers + */ + constructor( + private fb: FormBuilder, + private documentClassificationsService: DocumentClassificationsService, + private categoriesService: CategoriesService, + private iPowerClientsService: IpowerClientsService, + private documentSubclassificationsService: DocumentSubclassificationsService, + private errorHandlingService: ErrorHandlingService + ) { } + + ngOnInit(): void { + this.initData(); + this.initValidators() + this.excludeFields(); + } + + initData() { + this.documentClassificationsService.getAll().subscribe( + value => this.documentClassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + + // This is NOT the list of Subclassifications used for the dropdown. + this.documentSubclassificationsService.getAll().subscribe( + value => this.documentSubclassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + // TODO: Have this mechanism offer the use of custom validators too. + initValidators() { + + if (!this.requiredFields) { return; } + + // In a true/false case. + if (typeof this.requiredFields == 'boolean') { + // If true, enable the required validator for all controls. + if (this.requiredFields) { + Object.keys(this.templateForm.controls).forEach(key => this.templateForm.controls[key].setValidators(Validators.required)); + } + + // If false, do nothing. + return; + } + + // If it was a string array, enable the validators for all provided field-names. + (this.requiredFields).forEach(field => this.templateForm.controls[field].setValidators(Validators.required)) + } + + excludeFields() { + if (!this.excludedFormControls) { return; } + this.excludedFormControls.forEach(field => this.templateForm.removeControl(field)); + } + + /* + * Auto-suggest & Auto-complete Category + */ + autosuggestCategoryName(event) { + + if (!event.query || event.query.length < 3) { + this.categoryNameSuggestions = []; + return; + } + + let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryName)); + this.categoryNameSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + autosuggestCategoryCode(event) { + + if (event.query.length < 3) { + this.categoryCodeSuggestions = []; + return; + } + + let classId = this.templateForm.get('documentClassification').value ? this.templateForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryCode)); + this.categoryCodeSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + categoryNameSelected(name: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name); + this.templateForm.get('categoryCode')?.patchValue(this.selectedCategory.categoryCode); + this.templateForm.updateValueAndValidity(); + } + + categoryCodeSelected(code: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code); + this.templateForm.get('categoryName')?.patchValue(this.selectedCategory?.categoryName); + this.templateForm.updateValueAndValidity(); + } + + /* + * Auto-suggest & Auto-complete IPower Client + */ + autosuggestIPowerClientName(event): void { + + if (!event.query || event.query.length < 3) { + this.iPowerClientNameSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.name)); + this.iPowerClientNameSuggestions = temp; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); +} + + autosuggestIPowerClientCode(event): void { + + if (event.query.length < 3) { + this.iPowerClientCodeSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.clientCode)); + this.iPowerClientCodeSuggestions = temp; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + iPowerClientNameSelected(name: string) { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name); + this.templateForm.get('iPowerClientCode')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.clientCode : ''); + this.templateForm.updateValueAndValidity(); + } + + iPowerClientCodeSelected(code: string) { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code); + this.templateForm.get('iPowerClientName')?.patchValue(this.selectedIPowerClient ? this.selectedIPowerClient.name : ''); + this.templateForm.updateValueAndValidity(); + } + + /* + * Other Methods + */ + documentClassificationSelected(selection: DocumentClassification) { + this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId); + this.templateForm.get('documentSubclassification')?.setValue(this.availableDocumentSubclassifications[0]); //TODO CHECK + this.subCategoryCodeDisabled = false; + } + + /* + * Utility Methods + */ + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it. + syncSelectedCategory() { + + // Ιf our form has no value, truncate the selectedCategory either way. + if (!this.templateForm.get('categoryName')?.value && !this.templateForm.get('categoryCode').value) { + this.selectedCategory = null; + return; + } + + // If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedCategory. + if ( + this.templateForm.get('categoryName')?.value == this.selectedCategory.categoryName + || this.templateForm.get('categoryCode')?.value == this.selectedCategory.categoryCode + ) { + this.selectedCategory.categoryName = this.templateForm.get('categoryName')?.value; + this.selectedCategory.categoryCode = this.templateForm.get('categoryCode')?.value; + } + + // If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.'); + this.selectedCategory = null; + this.templateForm.get('categoryName')?.setValue(''); + this.templateForm.get('categoryCode')?.setValue(''); + this.templateForm.updateValueAndValidity(); + } + } + + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it. + syncSelectedIPowerClient() { + + // Ιf our form has no value, truncate the selectedIPowerClient either way. + if (!this.templateForm.get('iPowerClientName')?.value && !this.templateForm.get('iPowerClientCode')?.value) { + this.selectedIPowerClient = null; + return; + } + + // If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient. + if ( + this.templateForm.get('iPowerClientName')?.value == this.selectedIPowerClient.name + || this.templateForm.get('iPowerClientCode')?.value == this.selectedIPowerClient.clientCode + ) { + this.selectedIPowerClient.name = this.templateForm.get('iPowerClientName')?.value; + this.selectedIPowerClient.clientCode = this.templateForm.get('iPowerClientCode')?.value; + } + + // If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.'); + this.selectedIPowerClient = null; + this.templateForm.get('iPowerClientName')?.setValue(''); + this.templateForm.get('iPowerClientCode')?.setValue(''); + this.templateForm.updateValueAndValidity(); + } + } + + /* + * API methods + */ + public resetForm(): void { + this.templateForm.reset(); + this.selectedCategory = null; + this.selectedIPowerClient = null; + } + + public formValue(): Template { + + // A field ('documentSubclassification') may be excluded, so we have to check for that too. + let subCatCode = this.templateForm.get('documentSubclassification') ? this.templateForm.get('documentSubclassification').value : null; + let abbyy = this.templateForm.get('abbyyTemplateCode') ? this.templateForm.get('abbyyTemplateCode').value : null; + let docClass = this.templateForm.get('documentClassification') ? this.templateForm.get('documentClassification').value : null; + + // We keep track of those two using object-variables separate from our ReactiveForm. + // Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them. + // Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values. + this.syncSelectedCategory(); + this.syncSelectedIPowerClient(); + + let formValue: Template = { + id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null, + category: this.selectedCategory, + subCategoryCode: subCatCode ? subCatCode.subclassificationName : '', + abbyyTemplate: abbyy, + client: this.selectedIPowerClient, + documentClassification: docClass + }; + + return formValue; + } + + public setValue(value: Template): void { + if (!value) { + return; + } + + this.initiallySetFormValue = value; + + // If a documentClassification is already selected, enable the subclassification dropdown. + this.subCategoryCodeDisabled = !value.documentClassification; + + this.templateForm.get('documentClassification')?.setValue(value.documentClassification); + // Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications. + this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => + element.documentClassification.classificationId == value.documentClassification.classificationId + ); + + this.selectedCategory = value.category; + this.templateForm.get('categoryName')?.setValue(value.category.categoryName); + this.templateForm.get('categoryCode')?.setValue(value.category.categoryCode); + + this.selectedIPowerClient = value.client; + this.templateForm.get('iPowerClientName')?.setValue(value.client.name); + this.templateForm.get('iPowerClientCode')?.setValue(value.client.clientCode); + + this.templateForm.get('abbyyTemplateCode')?.setValue(value.abbyyTemplate); + + // To set the subcategory/subclassification we also have to make sure the documentClassification is the same. + // WARNING: Since we have enabled the [forceSelection] option of the , + // if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed. + this.templateForm.get('documentSubclassification').setValue( + this.documentSubclassificationsList.find(subClass => ( + subClass.subclassificationName == value.subCategoryCode && subClass.documentClassification.classificationId == value.documentClassification.classificationId + )) + ); + + this.templateForm.updateValueAndValidity(); + } + + public isValid(): boolean { + return this.templateForm.valid; + } +} diff --git a/app/features/administration/forms/verification-rule-form/create-verification-rule-form-value.interface.ts b/app/features/administration/forms/verification-rule-form/create-verification-rule-form-value.interface.ts new file mode 100644 index 0000000..15effb2 --- /dev/null +++ b/app/features/administration/forms/verification-rule-form/create-verification-rule-form-value.interface.ts @@ -0,0 +1,16 @@ +import { JournalVerification } from './../../../../shared/models/journal-verification.interface'; +import { CapturingVerification } from './../../../../shared/models/capturing-verification.interface'; +import { Template } from 'src/app/shared/models/template.interface'; + +export interface CreateVerificationRuleFormValue { + id: number; + confidenceLevelMinThreshold: number; + clientId: string + categoryId: number; + subCategoryCode: string; + verificationRuleStatus: string; + capturingVerification: CapturingVerification; + journalVerification: JournalVerification; + alteryxRoutineId: string; + template: Template; +} diff --git a/app/features/administration/forms/verification-rule-form/verification-rule-form.component.html b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.html new file mode 100644 index 0000000..24a954f --- /dev/null +++ b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.html @@ -0,0 +1,200 @@ +
+ +
+ +
+
+ + + + + +
+
+ +
+
+ + + + + +
+ +
+ + + + + +
+
+ +
+
+ + + + + +
+ +
+ + + + + +
+
+ +
+
+ + + + + +
+
+ +
+
+ + + + + +
+ +
+ + + + + +
+
+ +
+
+ + + + +
+ +
+ + + + +
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
diff --git a/app/features/administration/forms/verification-rule-form/verification-rule-form.component.scss b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/verification-rule-form/verification-rule-form.component.spec.ts b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.spec.ts new file mode 100644 index 0000000..72905b0 --- /dev/null +++ b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VerificationRuleFormComponent } from './verification-rule-form.component'; + +describe('VerificationRuleFormComponent', () => { + let component: VerificationRuleFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ VerificationRuleFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VerificationRuleFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/verification-rule-form/verification-rule-form.component.ts b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.ts new file mode 100644 index 0000000..8cace4e --- /dev/null +++ b/app/features/administration/forms/verification-rule-form/verification-rule-form.component.ts @@ -0,0 +1,527 @@ +import { Right } from './../../../../shared/models/right.interface'; +import { environment } from './../../../../../environments/environment'; +import { USER_RIGHTS } from './../../../../shared/enums/USER_RIGHTS.enum'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { CreateVerificationRuleFormValue } from './create-verification-rule-form-value.interface'; +import { JournalVerificationsService } from './../../../../shared/services/administration/journal-verifications.service'; +import { CapturingVerificationsService } from './../../../../shared/services/administration/capturing-verifications.service'; +import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service'; +import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service'; +import { FormBuilder, Validators } from '@angular/forms'; +import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface'; +import { Component, Input, OnInit } from '@angular/core'; +import { CapturingVerification } from '../../../../shared/models/capturing-verification.interface'; +import { Category } from '../../../../shared/models/category.interface'; +import { IPowerClient } from '../../../../shared/models/ipower-client.interface'; +import { JournalVerification } from '../../../../shared/models/journal-verification.interface'; +import { VerificationRule } from './../../../../shared/models/verification-rule.interface'; +import { DocumentClassification } from '../../../../shared/models/document-classification.interface'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-verification-rule-form', + templateUrl: './verification-rule-form.component.html', + styleUrls: ['./verification-rule-form.component.scss'] +}) +export class VerificationRuleFormComponent implements OnInit { + + /* + * Inputs + */ + @Input() dialogLayout: boolean = false; // Controls .scss classes to allow for better dispay in a dialog. + @Input() requiredFields: string[] | boolean = false; // True/False indicates that all/none are required. String[] specifies the form controls required. + @Input() displayValidationMessagesEvenIfPristine: boolean = false; // Serves for manually treating the controls as dirty. + @Input() excludedFormControls: string[]; // Specifies the form controls to be removed and NOT displayed. + + /* + * Reactive Form + */ + verificationRuleForm = this.fb.group({ + documentClassification: [null], + ipowerName: [null], + ipowerCode: [null], + categoryName: [null], + categoryCode: [null], + subCategoryCode: [null], // This actually represents the complete DocumentSubclassification object. + confidenceLevelMinThreshold: [null], + capturingVerification: [null], + journalVerification: [null], + alteryxRoutineId: [null], + verificationRuleStatus: [true], + template: [null] + }); + initiallySetFormValue: VerificationRule; + editMode: boolean = false; + + /* + * Other Variables + */ + documentClassificationsList: DocumentClassification[]; + + categoryNameSuggestions: string[]; + categoryCodeSuggestions: string[]; + categorySuggestions: Category[]; + selectedCategory: Category; + + iPowerClientNameSuggestions: string[]; + iPowerClientCodeSuggestions: string[]; + iPowerClientSuggestions: IPowerClient[]; + selectedIPowerClient: IPowerClient; + + capturingVerificationsList: CapturingVerification[]; + journalVerificationsList: JournalVerification[]; + + documentSubclassificationsList: DocumentSubclassification[]; + availableDocumentSubclassifications: DocumentSubclassification[]; + subCategoryCodeDisabled: boolean = true; + + /* + * Constructor & Initialisers + */ + constructor( + private fb: FormBuilder, + private documentClassificationsService: DocumentClassificationsService, + private categoriesService: CategoriesService, + private iPowerClientsService: IpowerClientsService, + private documentSubclassificationsService: DocumentSubclassificationsService, + private capturingVerificationsService: CapturingVerificationsService, + private journalVerificationsService: JournalVerificationsService, + private authService: AuthService, + private errorHandlingService: ErrorHandlingService + + ) { } + + ngOnInit(): void { + this.initData(); + this.initValidators() + this.excludeFields(); + } + + initData() { + this.documentClassificationsService.getAll().subscribe( + value => this.documentClassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + + // This is NOT the list of Subclassifications used for the dropdown. + this.documentSubclassificationsService.getAll().subscribe( + value => this.documentSubclassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + + this.journalVerificationsService.getJournalVerifications().subscribe( + values => this.journalVerificationsList = values, + err => this.errorHandlingService.showHttpResponseError(err) + ); + + this.capturingVerificationsService.getCapturingVerifications().subscribe( + values => this.capturingVerificationsList = values, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + // TODO: Have this mechanism offer the use of custom validators too. + initValidators() { + + if (!this.requiredFields) { return; } + + // In a true/false case. + if (typeof this.requiredFields == 'boolean') { + // If true, enable the required validator for all controls. + if (this.requiredFields) { + Object.keys(this.verificationRuleForm.controls).forEach(key => this.verificationRuleForm.controls[key].setValidators(Validators.required)); + } + + // If false, do nothing. + return; + } + + // If it was a string array, enable the validators for all provided field-names. + (this.requiredFields).forEach(field => this.verificationRuleForm.controls[field].setValidators(Validators.required)) + } + + excludeFields() { + if (!this.excludedFormControls) { return; } + this.excludedFormControls.forEach(field => this.verificationRuleForm.removeControl(field)); + } + + /* + * Auto-suggest & Auto-complete Category + */ + autosuggestCategoryName(event) { + + if (!event.query || event.query.length < 3) { + this.categoryNameSuggestions = []; + return; + } + + let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryName)); + this.categoryNameSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + autosuggestCategoryCode(event) { + + if (event.query.length < 3) { + this.categoryCodeSuggestions = []; + return; + } + + let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryCode)); + this.categoryCodeSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + categoryNameSelected(name: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name); + this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode); + this.verificationRuleForm.updateValueAndValidity(); + } + + categoryCodeSelected(code: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code); + this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName); + this.verificationRuleForm.updateValueAndValidity(); + } + + // /* + // * Auto-suggest & Auto-complete IPower Client + // */ + // /* + // * Rights-check Warning: + // * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule. + // * Note: + // * I know that if on editMode the client-input is disabled and thus this check is redundant, + // * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes. + // */ + // autosuggestIPowerClientName(event) { + + // if (!event.query || event.query.length < 3) { + // this.iPowerClientNameSuggestions = []; + // return; + // } + + // // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients, + // // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button. + // let endpointToSubscribeTo: Observable = USER_RIGHTS.B01.isGrantedToUser( + // this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights + // ) + // ? this.iPowerClientsService.getClientsByNameOnly(event.query) + // : this.iPowerClientsService.getClientsByNameDistinct(event.query); + + // endpointToSubscribeTo.subscribe( + // (values: IPowerClient[]) => { + + // // ***See comment at method level*** + // if (!this.editMode) { + // values = values.filter(client => USER_RIGHTS.B03.isGrantedToUser( + // this.authService.userRights.find(rdc => rdc.client.id == client.id)?.rights + // )); + // } + + // let temp: string[] = []; + // this.iPowerClientSuggestions = values; + // values.map(val => temp.push(val.name)); + // this.iPowerClientNameSuggestions = temp + // }, + // err => this.errorHandlingService.showHttpResponseError(err) + // ); + // } + + // /* + // * Rights-check Warning: + // * If we are NOT in editMode (and are thus on "addMode"), we should only suggest clients for which we actually CAN add a new rule. + // * Note: + // * I know that if on editMode the client-input is disabled and thus this check is redundant, + // * but I think it is better to work with as an abstract perspective as possible, not entailing business logic that may either be unrelated or prone to changes. + // */ + // autosuggestIPowerClientCode(event) { + + // if (event.query.length < 3) { + // this.iPowerClientCodeSuggestions = []; + // return; + // } + + // // If the user has the right to preview all rules (B01), we use the endpoint that returns all iPowerClients, + // // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button. + // let endpointToSubscribeTo: Observable = USER_RIGHTS.B01.isGrantedToUser( + // this.authService.userRights.find(rbc => rbc.client.id == environment.globalRightsClientID)?.rights + // ) + // ? this.iPowerClientsService.getClientsByCodeOnly(event.query): null; + + // endpointToSubscribeTo.subscribe( + // (values: IPowerClient[]) => { + + // // ***See comment at method level*** + // if (!this.editMode) { + // values = values; + // } + + // let temp: string[] = []; + // this.iPowerClientSuggestions = values; + // values.map(val => temp.push(val.clientCode)); + // this.iPowerClientCodeSuggestions = temp + // }, + // err => this.errorHandlingService.showHttpResponseError(err) + // ); + // } + + + /* + * Auto-suggest & Auto-complete IPower Client + */ + autosuggestIPowerClientName(event): void { + + if (!event.query || event.query.length < 3) { + this.iPowerClientNameSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByNameOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.name)); + this.iPowerClientNameSuggestions = temp; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); +} + + autosuggestIPowerClientCode(event): void { + + if (event.query.length < 3) { + this.iPowerClientCodeSuggestions = []; + return; + } + + this.iPowerClientsService.getClientsByCodeOnly(event.query).subscribe( + (values: IPowerClient[]) => { + this.iPowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.clientCode)); + this.iPowerClientCodeSuggestions = temp; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + iPowerClientNameSelected(name: string) { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.name == name); + this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode); + this.verificationRuleForm.updateValueAndValidity(); + } + + iPowerClientCodeSelected(code: string) { + this.selectedIPowerClient = this.iPowerClientSuggestions.find(client => client.clientCode == code); + this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name); + this.verificationRuleForm.updateValueAndValidity(); + } + + /* + * Other Methods + */ + documentClassificationSelected(selection) { + this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.value.classificationId); + this.verificationRuleForm.get('subCategoryCode').setValue(this.availableDocumentSubclassifications[0]); + this.subCategoryCodeDisabled = false; + } + + /* + * Utility Methods + */ + initiateEditMode() { + // let controlsToDisableInEditMode = ['documentClassification', 'ipowerName', 'ipowerCode', 'categoryName', 'categoryCode', 'subCategoryCode'] + // controlsToDisableInEditMode.forEach(ctrl => this.verificationRuleForm.get(ctrl).disable()); + } + + + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it. + syncSelectedCategory() { + + // Ιf our form has no value, truncate the selectedCategory either way. + if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) { + this.selectedCategory = null; + return; + } + + // If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedCategory. + if ( + this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName + || this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode + ) { + this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value; + this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value; + } + + // If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.'); + this.selectedCategory = null; + this.verificationRuleForm.get('categoryName').setValue(''); + this.verificationRuleForm.get('categoryCode').setValue(''); + this.verificationRuleForm.updateValueAndValidity(); + } + } + + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it. + syncSelectedIPowerClient() { + + // Ιf our form has no value, truncate the selectedIPowerClient either way. + if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) { + this.selectedIPowerClient = null; + return; + } + + // If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient. + if ( + this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name + || this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode + ) { + this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value; + this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value; + } + + // If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.'); + this.selectedIPowerClient = null; + this.verificationRuleForm.get('ipowerName').setValue(''); + this.verificationRuleForm.get('ipowerCode').setValue(''); + this.verificationRuleForm.updateValueAndValidity(); + } + } + + /* + * Rights-check Methods + */ + canEditRuleStatus(): boolean { + if (this.initiallySetFormValue) { + return this.authService.userHasRightForClient(USER_RIGHTS.B06, environment.globalRightsClientID); + } + return false; + } + + // canEditConfidenceLevel(): boolean { + // if (this.initiallySetFormValue) { + // return this.authService.userHasRightForClient(USER_RIGHTS.B07, this.initiallySetFormValue.client.id); + // } + // return false; + // } + + /* + * API methods + */ + public resetForm(): void { + this.verificationRuleForm.reset(); + this.selectedCategory = null; + this.selectedIPowerClient = null; + this.editMode = null; + } + + public formValue(): CreateVerificationRuleFormValue { + + // We keep track of those two using object-variables separate from our ReactiveForm. + // Thus, we now have to make sure the ReactiveForm really has values that match those objects, before we forward them. + // Also, keep in mind that our auto-suggest inputs limit the user in choosing one of their values. + this.syncSelectedCategory(); + this.syncSelectedIPowerClient(); + + let formValue: CreateVerificationRuleFormValue = { + id: this.initiallySetFormValue ? this.initiallySetFormValue.id : null, + confidenceLevelMinThreshold: this.verificationRuleForm.get('confidenceLevelMinThreshold').value, + clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : null, + categoryId: this.selectedCategory ? this.selectedCategory.id : null, + // The backend only requires the subcategory's name, and not the whole object. Don't ask me. + subCategoryCode: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : '', + capturingVerification: this.verificationRuleForm.get('capturingVerification').value, + journalVerification: this.verificationRuleForm.get('journalVerification').value, + alteryxRoutineId: this.verificationRuleForm.get('alteryxRoutineId').value, + template: this.verificationRuleForm.get('template').value, + + // Convert 'verificationRuleStatus' from boolean to string. + verificationRuleStatus: this.verificationRuleForm.get('verificationRuleStatus').value ? 'Enabled' : 'Disabled' + }; + + return formValue; + } + + public setValue(value: VerificationRule): void { + if (!value) { + return; + } + + this.editMode = true; + this.initiateEditMode(); + + this.initiallySetFormValue = value + + // If a documentClassification is already selected, enable the subclassification dropdown. + this.subCategoryCodeDisabled = !value.docClassificationCategory; + + this.verificationRuleForm.get('documentClassification').setValue(value.docClassificationCategory); + // Having set the documentClassification -and provided there was one- we must also set the availableDocumentSubclassifications. + this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => + element.documentClassification.classificationId == value.docClassificationCategory.classificationId + ); + + this.verificationRuleForm.get('ipowerName').setValue(value.client.name); + this.verificationRuleForm.get('ipowerCode').setValue(value.client.clientCode); + this.selectedIPowerClient = value.client; + + this.verificationRuleForm.get('categoryName').setValue(value.template.category.categoryName); + this.verificationRuleForm.get('categoryCode').setValue(value.template.category.categoryCode); + this.selectedCategory = value.template.category; + + this.verificationRuleForm.get('confidenceLevelMinThreshold').setValue(value.confidenceLevelMinThreshold); + this.verificationRuleForm.get('capturingVerification').setValue(value.capturingVerification); + this.verificationRuleForm.get('journalVerification').setValue(value.journalVerification); + this.verificationRuleForm.get('alteryxRoutineId').setValue(value.alteryxRoutineId); + this.verificationRuleForm.get('template').setValue(value.template); + + // Convert 'verificationRuleStatus' from string to boolean. + this.verificationRuleForm.get('verificationRuleStatus').setValue(value.verificationRuleStatus.trim().toLowerCase() == 'enabled'); + + // To set the subcategory/subclassification we also have to make sure the documentClassification is the same. + // WARNING: Since we have enabled the [forceSelection] option of the , + // if the availableDocumentSubclassifications are not set, documentSubclassification won't be displayed. + this.verificationRuleForm.get('subCategoryCode').setValue( + this.documentSubclassificationsList.find(subClass => + subClass.subclassificationName == value.template.subCategoryCode && subClass.documentClassification.classificationId == value.docClassificationCategory.classificationId + ) + ); + + this.verificationRuleForm.updateValueAndValidity(); + } + + public isValid(): boolean { + return this.verificationRuleForm.valid; + } + + public initForCreation() { + this.editMode = false; + this.verificationRuleForm.get('verificationRuleStatus').setValue(true); // The default value in creation mode. + this.verificationRuleForm.get('template').setValidators(null); // 'template' is not required during the creation. + } +} diff --git a/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form-value.interface.ts b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form-value.interface.ts new file mode 100644 index 0000000..e85ce19 --- /dev/null +++ b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form-value.interface.ts @@ -0,0 +1,6 @@ +export interface VerificationRuleSearchFormValue { + clientId: string; + categoryId: number; + docClassificationId: number; + docSubcategory: string; +} diff --git a/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.html b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.html new file mode 100644 index 0000000..8dc8f63 --- /dev/null +++ b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.html @@ -0,0 +1,93 @@ +
+
+ +
+
+
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+
+
+ +
+
+
+ + + +
+ +
+ + + +
+
+
+ +
+
diff --git a/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.scss b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.spec.ts b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.spec.ts new file mode 100644 index 0000000..57f9051 --- /dev/null +++ b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VerificationRuleSearchFormComponent } from './verification-rule-search-form.component'; + +describe('VerificationRuleSearchFormComponent', () => { + let component: VerificationRuleSearchFormComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ VerificationRuleSearchFormComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VerificationRuleSearchFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.ts b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.ts new file mode 100644 index 0000000..5a82974 --- /dev/null +++ b/app/features/administration/forms/verification-rule-search-form/verification-rule-search-form.component.ts @@ -0,0 +1,358 @@ +import { VerificationRulesService } from './../../../../shared/services/administration/verification-rules.service'; +import { VerificationRule } from './../../../../shared/models/verification-rule.interface'; +import { Component, Input, OnInit } from '@angular/core'; +import { AbstractControl, FormBuilder } from '@angular/forms'; +import { Category } from 'src/app/shared/models/category.interface'; +import { DocumentClassification } from 'src/app/shared/models/document-classification.interface'; +import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface'; +import { IPowerClient } from 'src/app/shared/models/ipower-client.interface'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service'; +import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service'; +import { IpowerClientsService } from 'src/app/shared/services/administration/ipower-clients.service'; +import { VerificationRuleSearchFormValue } from './verification-rule-search-form-value.interface'; +import { ErrorHandlingService } from 'src/app/shared/services/error-handling/error-handling.service'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { AuthService } from 'src/app/shared/services/auth.service'; +import { Observable } from 'rxjs'; +import { environment } from 'src/environments/environment'; + +@Component({ + selector: 'app-verification-rule-search-form', + templateUrl: './verification-rule-search-form.component.html', + styleUrls: ['./verification-rule-search-form.component.scss'] +}) +export class VerificationRuleSearchFormComponent implements OnInit { + + @Input() disabled: boolean = false; + + documentClassificationsList: DocumentClassification[]; + documentSubclassificationsList: DocumentSubclassification[]; + availableDocumentSubclassifications: DocumentSubclassification[]; + previouslySelectedClassificationId: number; + + categoryNameSuggestions: string[]; + categoryCodeSuggestions: string[]; + categorySuggestions: Category[]; + selectedCategory: Category = null; + + ipowerClientNameSuggestions: string[]; + ipowerClientCodeSuggestions: string[]; + ipowerClientSuggestions: IPowerClient[]; + selectedIPowerClient: IPowerClient = null; + + displayValidationMessagesEvenIfPristine: boolean; + + verificationRuleForm = this.fb.group({ + ipowerName: [null], + ipowerCode: [null], + categoryName: [null], + categoryCode: [null], + documentClassification: [null], + subCategoryCode: [null] // This actually represents the complete DocumentSubclassification object. + }); + + constructor( + private fb: FormBuilder, + private documentClassificationsService: DocumentClassificationsService, + private documentSubclassificationsService: DocumentSubclassificationsService, + private verificationRulesService: VerificationRulesService, + private categoriesService: CategoriesService, + private ipowerClientsService: IpowerClientsService, + private errorHandlingService: ErrorHandlingService, + private authService: AuthService + ) { } + + ngOnInit(): void { + + if (this.disabled) { + Object.keys(this.verificationRuleForm.controls).forEach(ctrl => this.verificationRuleForm.get(ctrl).disable()); + return; // Don't even bother initialising or requesting anything. + } + + this.initData(); + } + + initData() { + this.documentClassificationsService.getAll().subscribe( + value => this.documentClassificationsList = value, + err => this.errorHandlingService.showHttpResponseError(err) + ); + + // This is NOT the list of Subclassifications used for the dropdown. + this.documentSubclassificationsService.getAll().subscribe( + value => { + this.documentSubclassificationsList = value; + this.availableDocumentSubclassifications = value; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + clear() { + this.verificationRuleForm.reset(); + + this.selectedCategory = null; + this.selectedIPowerClient = null; + } + + documentClassificationSelected(selection: DocumentClassification) { + + // If a different Classification has been selected, reset the Subclassification's value. + if (this.previouslySelectedClassificationId && selection.classificationId != this.previouslySelectedClassificationId) { + this.verificationRuleForm.get('subCategoryCode').reset(); + } + this.previouslySelectedClassificationId = this.verificationRuleForm.get('documentClassification').value.classificationId; + + this.availableDocumentSubclassifications = this.documentSubclassificationsList.filter(element => element.documentClassification.classificationId == selection.classificationId); + } + + documentSubclassificationSelected(selection: DocumentSubclassification) { + this.verificationRuleForm.get('documentClassification').setValue(selection.documentClassification); + } + + /* + * Auto-suggest/complete Categories + */ + autosuggestCategoryName(event) { + + if (!event.query || event.query.length < 3) { + this.categoryNameSuggestions = []; + return; + } + + let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryName(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryName)); + this.categoryNameSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + autosuggestCategoryCode(event) { + + if (event.query.length < 3) { + this.categoryCodeSuggestions = []; + return; + } + + let classId = this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : null; + this.categoriesService.autosuggestCategoryCode(event.query, classId).subscribe( + (values: Category[]) => { + let temp: string[] = []; + this.categorySuggestions = values; + values.map(val => temp.push(val.categoryCode)); + this.categoryCodeSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + categoryNameSelected(name: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryName == name); + this.verificationRuleForm.get('categoryCode').patchValue(this.selectedCategory.categoryCode); + this.verificationRuleForm.updateValueAndValidity(); + } + + categoryCodeSelected(code: string) { + this.selectedCategory = this.categorySuggestions.find(cat => cat.categoryCode == code); + this.verificationRuleForm.get('categoryName').patchValue(this.selectedCategory.categoryName); + this.verificationRuleForm.updateValueAndValidity(); + } + + // /* + // * Auto-suggest/complete iPower Clients + // */ + // autosuggestIPowerClientName(event) { + + // if (!event.query || event.query.length < 3) { + // this.ipowerClientNameSuggestions = []; + // return; + // } + + // this.ipowerClientsService.getClientsByNameDistinct(event.query).subscribe( + // (values: IPowerClient[]) => { + // let temp: string[] = []; + // this.ipowerClientSuggestions = values; + // values.map(val => temp.push(val.name)); + // this.ipowerClientNameSuggestions = temp + // }, + // err => this.errorHandlingService.showHttpResponseError(err) + // ); + // } + + // autosuggestIPowerClientCode(event) { + + // if (!event.query || event.query.length < 3) { + // this.ipowerClientCodeSuggestions = []; + // return; + // } + + // this.ipowerClientsService.getClientsByCodeDistinct(event.query).subscribe( + // (values: IPowerClient[]) => { + // let temp: string[] = []; + // this.ipowerClientSuggestions = values; + // values.map(val => temp.push(val.clientCode)); + // this.ipowerClientCodeSuggestions = temp + // }, + // err => this.errorHandlingService.showHttpResponseError(err) + // ); + // } + + autosuggestIPowerClientCode(event) { + + if (event.query.length < 3) { + this.ipowerClientCodeSuggestions = []; + return; + } + + // If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients, + // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button. + let endpointToSubscribeTo: Observable = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID) + ? this.ipowerClientsService.getClientsByCodeOnly(event.query) + : this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByCodeDistinct(event.query) : null; + + endpointToSubscribeTo.subscribe( + (values: IPowerClient[]) => { + let temp: string[] = []; + this.ipowerClientSuggestions = values; + values.map(val => temp.push(val.clientCode)); + this.ipowerClientCodeSuggestions = temp + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); + } + + /* + * Auto-suggest & Auto-complete IPower Client + */ + autosuggestIPowerClientName(event): void { + + if (!event.query || event.query.length < 3) { + this.ipowerClientNameSuggestions = []; + return; + } + + // If the user has the right to Preview of Scheduling Procedure (A02), we use the endpoint that returns all iPowerClients, + // otherwise, the one that checks for the user's User_Access too. Whether the user can see ANY rule has already been handled by the 'search' button. + let endpointToSubscribeTo: Observable = this.authService.userHasRightForClient(USER_RIGHTS.B01, environment.globalRightsClientID) + ? this.ipowerClientsService.getClientsByNameOnly(event.query) + : this.authService.userRights.find(rdc => USER_RIGHTS.B02.isGrantedToUser(rdc.rights)) != null ? this.ipowerClientsService.getClientsByNameDistinct(event.query) : null; + + endpointToSubscribeTo.subscribe( + (values: IPowerClient[]) => { + this.ipowerClientSuggestions = values; + + const temp: string[] = []; + values.map(val => temp.push(val.name)); + this.ipowerClientNameSuggestions = temp; + }, + err => this.errorHandlingService.showHttpResponseError(err) + ); +} + + ipowerClientNameSelected(name: string) { + this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.name == name); + this.verificationRuleForm.get('ipowerCode').patchValue(this.selectedIPowerClient.clientCode); + this.verificationRuleForm.updateValueAndValidity(); + } + + ipowerClientCodeSelected(code: string) { + this.selectedIPowerClient = this.ipowerClientSuggestions.find(client => client.clientCode == code); + this.verificationRuleForm.get('ipowerName').patchValue(this.selectedIPowerClient.name); + this.verificationRuleForm.updateValueAndValidity(); + } + + /* + * Utility Methods + */ + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedCategory, otherwise truncate it. + syncSelectedCategory() { + + // Ιf our form has no value, truncate the selectedCategory either way. + if (!this.verificationRuleForm.get('categoryName').value && !this.verificationRuleForm.get('categoryCode').value) { + this.selectedCategory = null; + return; + } + + // If both or either of our form's values match the selectedCategory's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedCategory. + if ( + this.verificationRuleForm.get('categoryName').value == this.selectedCategory.categoryName + || this.verificationRuleForm.get('categoryCode').value == this.selectedCategory.categoryCode + ) { + this.selectedCategory.categoryName = this.verificationRuleForm.get('categoryName').value; + this.selectedCategory.categoryCode = this.verificationRuleForm.get('categoryCode').value; + } + + // If both our values were different from the selectedCategory's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedCategory()', 'Both of our form\'s values were different from the selectedCategory\'s.'); + this.selectedCategory = null; + this.verificationRuleForm.get('categoryName').setValue(''); + this.verificationRuleForm.get('categoryCode').setValue(''); + this.verificationRuleForm.updateValueAndValidity(); + } + } + + // Auto-suggest inputs - We have to ensure our reactive form holds values that represent the selectedIPowerClient, otherwise truncate it. + syncSelectedIPowerClient() { + + // Ιf our form has no value, truncate the selectedIPowerClient either way. + if (!this.verificationRuleForm.get('ipowerName').value && !this.verificationRuleForm.get('ipowerCode').value) { + this.selectedIPowerClient = null; + return; + } + + // If both or either of our form's values match the selectedIPowerClient's and the other one doesn't have a value, all is good. + // Just sync the values in case one is missing. Otherwise truncate the selectedIPowerClient. + if ( + this.verificationRuleForm.get('ipowerName').value == this.selectedIPowerClient.name + || this.verificationRuleForm.get('ipowerCode').value == this.selectedIPowerClient.clientCode + ) { + this.selectedIPowerClient.name = this.verificationRuleForm.get('ipowerName').value; + this.selectedIPowerClient.clientCode = this.verificationRuleForm.get('ipowerCode').value; + } + + // If both our values were different from the selectedIPowerClient's, truncate it. This is an extremely abnormal scenario. + else { + console.error('WARNING - syncSelectedIPowerClient()', 'Both of our form\'s values were different from the selectedIPowerClient\'s.'); + this.selectedIPowerClient = null; + this.verificationRuleForm.get('ipowerName').setValue(''); + this.verificationRuleForm.get('ipowerCode').setValue(''); + this.verificationRuleForm.updateValueAndValidity(); + } + } + + /* + * API methods + */ + public resetForm(): void { + this.verificationRuleForm.reset(); + } + + // TODO: Set type + public formValue(): VerificationRuleSearchFormValue { + + this.syncSelectedCategory(); + this.syncSelectedIPowerClient(); + + let formValue: VerificationRuleSearchFormValue = { + clientId: this.selectedIPowerClient ? this.selectedIPowerClient.id : '', + categoryId: this.selectedCategory ? this.selectedCategory.id : null, + docClassificationId: this.verificationRuleForm.get('documentClassification').value ? this.verificationRuleForm.get('documentClassification').value.classificationId : '', + // The backend only requires the subcategory's name, and not the whole object. Don't ask me. + docSubcategory: this.verificationRuleForm.get('subCategoryCode').value ? this.verificationRuleForm.get('subCategoryCode').value['subclassificationName'] : '' + } + + return formValue; + } + + public isValid(): boolean { + return this.verificationRuleForm.valid; + } +} diff --git a/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.html b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.html new file mode 100644 index 0000000..b74e203 --- /dev/null +++ b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.html @@ -0,0 +1,30 @@ + +
+ +
+
+
+ + + + + + +
+
+
diff --git a/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.scss b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.spec.ts b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.spec.ts new file mode 100644 index 0000000..fed9ba9 --- /dev/null +++ b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateTemplateDialogComponent } from './create-template-dialog.component'; + +describe('CreateTemplateDialogComponent', () => { + let component: CreateTemplateDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CreateTemplateDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateTemplateDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.ts b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.ts new file mode 100644 index 0000000..9ec20b0 --- /dev/null +++ b/app/features/administration/templates-management/create-template-dialog/create-template-dialog.component.ts @@ -0,0 +1,92 @@ +import { TemplateFormComponent } from './../../forms/template-form/template-form.component'; +import { CategoriesService } from 'src/app/shared/services/administration/categories.service'; +import { IpowerClientsService } from './../../../../shared/services/administration/ipower-clients.service'; +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; +import { Category } from 'src/app/shared/models/category.interface'; +import { DocumentClassification } from 'src/app/shared/models/document-classification.interface'; +import { DocumentSubclassification } from 'src/app/shared/models/document-subclassification.interface'; +import { IPowerClient } from 'src/app/shared/models/ipower-client.interface'; +import { Template } from 'src/app/shared/models/template.interface'; +import { DocumentClassificationsService } from 'src/app/shared/services/administration/document-classifications.service'; +import { DocumentSubclassificationsService } from 'src/app/shared/services/administration/document-subclassifications.service'; +import { TemplatesService } from 'src/app/shared/services/administration/templates.service'; +import { NotificationsHandlingService } from 'src/app/shared/services/notifications-handling/notifications-handling.service'; + +@Component({ + selector: 'app-create-template-dialog', + templateUrl: './create-template-dialog.component.html', + styleUrls: ['./create-template-dialog.component.scss'] +}) +export class CreateTemplateDialogComponent implements OnInit { + + @ViewChild(TemplateFormComponent) templateForm: TemplateFormComponent; + + @Input() displayDialog: boolean; + @Input() header: string; + @Input() templateToEdit: Template; + @Output() cancelled = new EventEmitter(); + @Output() valueChange = new EventEmitter(); + + displayValidationMessagesEvenIfPristine: boolean; + + constructor(private templatesService: TemplatesService, private notificationService: NotificationsHandlingService) { } + + ngOnInit(): void { + this.reset(); // Make sure everything is cleanly initialised. + } + + reset() { + this.displayValidationMessagesEvenIfPristine = false; + if (this.templateForm) { + this.templateForm.resetForm(); + } + } + + onShow() { + // If a categoryToEdit was provided. + if (this.templateToEdit) { + this.templateForm.setValue(this.templateToEdit); + } + } + + cancel() { + this.cancelled.emit(true); + } + + addTemplate() { + // If the form is not valid, make sure validator messages are displayed and then return without doing anything. + if (!this.templateForm.isValid()) { + this.displayValidationMessagesEvenIfPristine = true; + return; + } + + // TODO: What is returned from backend on create()?? + this.templatesService.createNewTemplate(this.templateForm.formValue()).subscribe(result => { + this.valueChange.emit(result); + this.cancel(); + this.notificationService.showCreateNewTemplateSuccess(); + }, + error => { + + }); + } + + editTemplate() { + // If the form is not valid, make sure validator messages are displayed and then return without doing anything. + if (!this.templateForm.isValid()) { + this.displayValidationMessagesEvenIfPristine = true; + return; + } + + // TODO: What is returned from backend on create()?? + this.templatesService.updateTemplate(this.templateForm.formValue()).subscribe(result => { + this.valueChange.emit(result); + this.cancel(); + this.notificationService.showUpdateTemplateSuccess(); + }, + error => { + + }); + } +} diff --git a/app/features/administration/templates-management/templates-management.component.html b/app/features/administration/templates-management/templates-management.component.html new file mode 100644 index 0000000..1a1c868 --- /dev/null +++ b/app/features/administration/templates-management/templates-management.component.html @@ -0,0 +1,50 @@ +
+
+ +

{{'TEMPLATES-MANAGEMENT' | translate}}

+ + + + + +
+ +
+
+ + + +
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+
diff --git a/app/features/administration/templates-management/templates-management.component.scss b/app/features/administration/templates-management/templates-management.component.scss new file mode 100644 index 0000000..2f71de1 --- /dev/null +++ b/app/features/administration/templates-management/templates-management.component.scss @@ -0,0 +1 @@ +@import 'src/styles'; diff --git a/app/features/administration/templates-management/templates-management.component.spec.ts b/app/features/administration/templates-management/templates-management.component.spec.ts new file mode 100644 index 0000000..09d1b75 --- /dev/null +++ b/app/features/administration/templates-management/templates-management.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TemplatesManagementComponent } from './templates-management.component'; + +describe('TemplatesManagementComponent', () => { + let component: TemplatesManagementComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ TemplatesManagementComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(TemplatesManagementComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/app/features/administration/templates-management/templates-management.component.ts b/app/features/administration/templates-management/templates-management.component.ts new file mode 100644 index 0000000..50de905 --- /dev/null +++ b/app/features/administration/templates-management/templates-management.component.ts @@ -0,0 +1,58 @@ +import { AuthService } from './../../../shared/services/auth.service'; +import { Component, OnInit } from '@angular/core'; +import { Template } from 'src/app/shared/models/template.interface'; +import { Page } from '../../../shared/models/paging/page.interface'; +import { USER_RIGHTS } from 'src/app/shared/enums/USER_RIGHTS.enum'; +import { environment } from 'src/environments/environment'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'app-templates-management', + templateUrl: './templates-management.component.html', + styleUrls: ['./templates-management.component.scss'] +}) +export class TemplatesManagementComponent implements OnInit { + + displayTemplateCreationDialog = false; + searchResults: Page