@tuki-io/tuki-widgets 0.0.219-dev.54 → 0.0.219-dev.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/contact-center/cc-import/cc-import.module.d.ts +13 -0
- package/contact-center/cc-import/cc-import.service.d.ts +85 -0
- package/contact-center/cc-import/components/import-contact-center-panel/import-contact-center-panel.component.d.ts +56 -0
- package/contact-center/cc-import/components/import-contact-center-wizard/import-contact-center-wizard.component.d.ts +77 -0
- package/contact-center/cc-import/components/import-contact-center-wizard/import-contact-center-wizard.types.d.ts +3 -0
- package/contact-center/cc-import/constants/cc-import.constants.d.ts +37 -0
- package/contact-center/cc-import/mock/cc-import.mock.d.ts +4 -0
- package/contact-center/cc-import/types/cc-import.d.ts +73 -0
- package/contact-center/cc-import/types/uccx.d.ts +109 -0
- package/contact-center/cc-readiness/cc-readiness.module.d.ts +3 -3
- package/contact-center/public-api.d.ts +8 -0
- package/contact-center/shared/api.endpoints.d.ts +25 -0
- package/contact-center/shared/api.service.d.ts +3 -1
- package/contact-center/shared/components/card/card.component.d.ts +13 -0
- package/contact-center/shared/dcp-api.service.d.ts +15 -0
- package/contact-center/shared/shared.module.d.ts +11 -5
- package/esm2020/contact-center/cc-import/cc-import.module.mjs +45 -0
- package/esm2020/contact-center/cc-import/cc-import.service.mjs +228 -0
- package/esm2020/contact-center/cc-import/components/import-contact-center-panel/import-contact-center-panel.component.mjs +144 -0
- package/esm2020/contact-center/cc-import/components/import-contact-center-wizard/import-contact-center-wizard.component.mjs +243 -0
- package/esm2020/contact-center/cc-import/components/import-contact-center-wizard/import-contact-center-wizard.types.mjs +3 -0
- package/esm2020/contact-center/cc-import/constants/cc-import.constants.mjs +62 -0
- package/esm2020/contact-center/cc-import/mock/cc-import.mock.mjs +78 -0
- package/esm2020/contact-center/cc-import/types/cc-import.mjs +2 -0
- package/esm2020/contact-center/cc-import/types/uccx.mjs +24 -0
- package/esm2020/contact-center/cc-readiness/cc-readiness.module.mjs +7 -6
- package/esm2020/contact-center/cc-readiness/cc-readiness.service.mjs +1 -1
- package/esm2020/contact-center/cc-readiness/widgets/licences-requirement/licences-requirement.component.mjs +7 -7
- package/esm2020/contact-center/cc-readiness/widgets/summary-grid/summary-grid.component.mjs +2 -2
- package/esm2020/contact-center/public-api.mjs +9 -1
- package/esm2020/contact-center/shared/api.endpoints.mjs +26 -1
- package/esm2020/contact-center/shared/api.service.mjs +8 -3
- package/esm2020/contact-center/shared/components/card/card.component.mjs +24 -0
- package/esm2020/contact-center/shared/dcp-api.service.mjs +26 -0
- package/esm2020/contact-center/shared/shared.module.mjs +15 -5
- package/esm2020/di2mt/widgets/site-upgrade/progress-bar/progress-bar.component.mjs +3 -3
- package/esm2020/di2mt/widgets/site-upgrade/site-upgrade-data-table/site-upgrade-data-table.component.mjs +2 -2
- package/esm2020/di2mt/widgets/upgrade-overview/cards/pending-activation-users/pending-activation-users.component.mjs +17 -17
- package/esm2020/lib/widgets.component.mjs +9 -9
- package/esm2020/lib/widgets.module.mjs +1 -1
- package/esm2020/lib/widgets.service.mjs +1 -1
- package/esm2020/locations/public-api.mjs +1 -1
- package/esm2020/locations/src/app.constants.mjs +1 -1
- package/esm2020/locations/src/location-confirm-dialog/location-confirm-dialog.component.mjs +3 -3
- package/esm2020/locations/src/locations.component.mjs +3 -3
- package/esm2020/locations/src/locations.module.mjs +1 -1
- package/esm2020/locations/src/material.module.mjs +1 -1
- package/esm2020/locations/src/services/api.service.mjs +1 -1
- package/esm2020/locations/src/services/locations.service.mjs +1 -1
- package/esm2020/locations/src/types/location.mjs +1 -1
- package/esm2020/locations/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/meetings/src/app.constants.mjs +1 -1
- package/esm2020/meetings/src/components/live-meetings/live-meetings.component.mjs +3 -3
- package/esm2020/meetings/src/components/meeting-spaces/meeting-spaces.component.mjs +3 -3
- package/esm2020/meetings/src/meetings.component.mjs +3 -3
- package/esm2020/meetings/src/meetings.module.mjs +1 -1
- package/esm2020/meetings/src/services/live-meetings.service.mjs +1 -1
- package/esm2020/meetings/src/services/meeting-spaces.service.mjs +1 -1
- package/esm2020/meetings/src/types/live-meeting.mjs +1 -1
- package/esm2020/meetings/src/types/meeting-space.mjs +1 -1
- package/esm2020/meetings/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/public-api.mjs +1 -1
- package/esm2020/user-creation/src/app.constants.mjs +1 -1
- package/esm2020/user-creation/src/classes/notification.mjs +1 -1
- package/esm2020/user-creation/src/classes/site.mjs +1 -1
- package/esm2020/user-creation/src/environments/environment.mjs +1 -1
- package/esm2020/user-creation/src/interfaces/user-creation-wizard.interfaces.mjs +1 -1
- package/esm2020/user-creation/src/shared/components/notification/notification.component.mjs +3 -3
- package/esm2020/user-creation/src/shared/pipes/truncate.pipe.mjs +1 -1
- package/esm2020/user-creation/src/shared/services/notification.service.mjs +1 -1
- package/esm2020/user-creation/src/shared/services/user-creation-api.service.mjs +1 -1
- package/esm2020/user-creation/src/shared/services/utils.mjs +1 -1
- package/esm2020/user-creation/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/user-creation/src/utils/build-savable-end-user.mjs +1 -1
- package/esm2020/user-creation/src/utils/device-default-prefix.mjs +1 -1
- package/esm2020/user-creation/src/utils/device-name-dynamic-tokens.mjs +1 -1
- package/esm2020/user-creation/src/utils/device-name-validation.mjs +1 -1
- package/esm2020/user-creation/src/utils/model.mjs +1 -1
- package/esm2020/user-creation/src/utils/parse-device-name-rule.mjs +1 -1
- package/esm2020/user-creation/src/widgets/user-creation-wizard/user-creation-wizard.component.mjs +3 -3
- package/esm2020/user-device-manage/public-api.mjs +4 -1
- package/esm2020/user-device-manage/src/app.constants.mjs +9 -3
- package/esm2020/user-device-manage/src/associate-lines/associate-lines.component.mjs +311 -0
- package/esm2020/user-device-manage/src/classes/device.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/deviceProfile.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/line-association-interface.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/line-association.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/line-call-info-display.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/line-directory.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/line.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/notification.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/recording-options.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/simplified-user.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/site-defaults.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/translation-pattern.mjs +1 -1
- package/esm2020/user-device-manage/src/classes/types.mjs +1 -1
- package/esm2020/user-device-manage/src/common-functions.mjs +1 -1
- package/esm2020/user-device-manage/src/confirm-dialog/info-dialog.component.mjs +3 -3
- package/esm2020/user-device-manage/src/device-associated-line/associated-line-row/associated-line-row.component.mjs +3 -3
- package/esm2020/user-device-manage/src/device-associated-line/device-associated-line-details-box/device-associated-line-details-box.component.mjs +3 -3
- package/esm2020/user-device-manage/src/device-associated-line/device-associated-line-extension/device-associated-line-extension.component.mjs +3 -3
- package/esm2020/user-device-manage/src/device-associated-line/device-associated-line.component.mjs +1 -1
- package/esm2020/user-device-manage/src/device-info/device-info.component.mjs +3 -3
- package/esm2020/user-device-manage/src/device-manage-widget.component.mjs +34 -17
- package/esm2020/user-device-manage/src/device-settings/device-settings.component.mjs +207 -0
- package/esm2020/user-device-manage/src/environments/environment.mjs +1 -1
- package/esm2020/user-device-manage/src/interseptors/auth.interceptor.mjs +1 -1
- package/esm2020/user-device-manage/src/lazy-loading-select/lazy-loading-select.component.mjs +3 -3
- package/esm2020/user-device-manage/src/line-key-config/line-key-config.component.mjs +401 -0
- package/esm2020/user-device-manage/src/material.module.mjs +1 -1
- package/esm2020/user-device-manage/src/notifications/notification.component.mjs +3 -3
- package/esm2020/user-device-manage/src/pipes/mac-address.pipe.mjs +1 -1
- package/esm2020/user-device-manage/src/services/api.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/device.service.mjs +32 -2
- package/esm2020/user-device-manage/src/services/dns.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/line.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/notification.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/removeKynFromIBM.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/site-settings.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/sorting-utils.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/user.service.mjs +34 -6
- package/esm2020/user-device-manage/src/services/utils.service.mjs +1 -1
- package/esm2020/user-device-manage/src/services/validation.service.mjs +1 -1
- package/esm2020/user-device-manage/src/user-device-manage.module.mjs +19 -4
- package/esm2020/user-device-manage/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/user-manage/public-api.mjs +1 -1
- package/esm2020/user-manage/src/app.constants.mjs +1 -1
- package/esm2020/user-manage/src/classes/device.mjs +1 -1
- package/esm2020/user-manage/src/classes/line-association-interface.mjs +1 -1
- package/esm2020/user-manage/src/classes/line-association.mjs +1 -1
- package/esm2020/user-manage/src/classes/line-call-info-display.mjs +1 -1
- package/esm2020/user-manage/src/classes/line-directory.mjs +1 -1
- package/esm2020/user-manage/src/classes/line.mjs +1 -1
- package/esm2020/user-manage/src/classes/notification.mjs +1 -1
- package/esm2020/user-manage/src/classes/pagination.mjs +1 -1
- package/esm2020/user-manage/src/classes/recording-options.mjs +1 -1
- package/esm2020/user-manage/src/classes/simplified-user.mjs +1 -1
- package/esm2020/user-manage/src/classes/table-data.mjs +1 -1
- package/esm2020/user-manage/src/classes/translation-pattern.mjs +1 -1
- package/esm2020/user-manage/src/classes/user-list.mjs +1 -1
- package/esm2020/user-manage/src/common-functions.mjs +1 -1
- package/esm2020/user-manage/src/device-list/device-list.component.mjs +3 -3
- package/esm2020/user-manage/src/device-list/device-row/device-row.component.mjs +3 -3
- package/esm2020/user-manage/src/environments/environment.mjs +1 -1
- package/esm2020/user-manage/src/interseptors/auth.interceptor.mjs +1 -1
- package/esm2020/user-manage/src/lazy-loading-select/lazy-loading-select.component.mjs +3 -3
- package/esm2020/user-manage/src/material.module.mjs +1 -1
- package/esm2020/user-manage/src/notifications/notification.component.mjs +3 -3
- package/esm2020/user-manage/src/removeKynFromIBM.service.mjs +1 -1
- package/esm2020/user-manage/src/services/api.service.mjs +1 -1
- package/esm2020/user-manage/src/services/dcp-api.service.mjs +1 -1
- package/esm2020/user-manage/src/services/dns.service.mjs +1 -1
- package/esm2020/user-manage/src/services/line.service.mjs +1 -1
- package/esm2020/user-manage/src/services/notification.service.mjs +1 -1
- package/esm2020/user-manage/src/services/removeKynFromIBM.service.mjs +1 -1
- package/esm2020/user-manage/src/services/site-settings.service.mjs +1 -1
- package/esm2020/user-manage/src/services/sorting-utils.service.mjs +1 -1
- package/esm2020/user-manage/src/services/user.service.mjs +1 -1
- package/esm2020/user-manage/src/services/utils.service.mjs +1 -1
- package/esm2020/user-manage/src/user-calling/user-calling-extension/user-calling-extension.component.mjs +3 -3
- package/esm2020/user-manage/src/user-info/user-info.component.mjs +3 -3
- package/esm2020/user-manage/src/user-manage-widget.component.mjs +2 -2
- package/esm2020/user-manage/src/user-manage.module.mjs +1 -1
- package/esm2020/user-manage/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/user-manage/src/utils/pagination/pagination.component.mjs +3 -3
- package/esm2020/users-list/public-api.mjs +1 -1
- package/esm2020/users-list/src/app.constants.mjs +1 -1
- package/esm2020/users-list/src/classes/app-location.mjs +1 -1
- package/esm2020/users-list/src/classes/device.mjs +1 -1
- package/esm2020/users-list/src/classes/line.mjs +1 -1
- package/esm2020/users-list/src/classes/move-user.mjs +1 -1
- package/esm2020/users-list/src/classes/notification.mjs +1 -1
- package/esm2020/users-list/src/classes/simlified-user.mjs +1 -1
- package/esm2020/users-list/src/classes/table-data.mjs +1 -1
- package/esm2020/users-list/src/classes/user-list.mjs +1 -1
- package/esm2020/users-list/src/move-user-wizard/move-user-stepper/device-move-user/device-move-user-wizard.component.mjs +3 -3
- package/esm2020/users-list/src/move-user-wizard/move-user-stepper/device-move-user-tab/devices-move-user-wizard-tab.component.mjs +3 -3
- package/esm2020/users-list/src/move-user-wizard/move-user-wizard.component.mjs +3 -3
- package/esm2020/users-list/src/services/api-webex.service.mjs +1 -1
- package/esm2020/users-list/src/services/api.service.mjs +1 -1
- package/esm2020/users-list/src/services/dns.service.mjs +1 -1
- package/esm2020/users-list/src/services/events-communication.service.mjs +1 -1
- package/esm2020/users-list/src/services/notification.service.mjs +1 -1
- package/esm2020/users-list/src/services/removeKynFromIBM.service.mjs +1 -1
- package/esm2020/users-list/src/services/site-settings.service.mjs +1 -1
- package/esm2020/users-list/src/services/user.service.mjs +1 -1
- package/esm2020/users-list/src/user-list-confirm-dialog/user-list-confirm-dialog.component.mjs +3 -3
- package/esm2020/users-list/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/users-list/src/utils/common-functions.mjs +1 -1
- package/esm2020/users-list/src/utils/notifications/notification.component.mjs +3 -3
- package/esm2020/users-list/src/utils/utils.service.mjs +1 -1
- package/esm2020/workspaces/public-api.mjs +1 -1
- package/esm2020/workspaces/src/app.constants.mjs +1 -1
- package/esm2020/workspaces/src/components/workspace-detail/workspace-detail.component.mjs +17 -4
- package/esm2020/workspaces/src/components/workspace-device-detail/workspace-device-detail.component.mjs +66 -0
- package/esm2020/workspaces/src/components/workspaces-filters/workspaces-filters.component.mjs +3 -3
- package/esm2020/workspaces/src/components/workspaces-table/workspaces-table.component.mjs +6 -3
- package/esm2020/workspaces/src/material.module.mjs +1 -1
- package/esm2020/workspaces/src/services/api.service.mjs +1 -1
- package/esm2020/workspaces/src/services/workspace-detail.service.mjs +43 -1
- package/esm2020/workspaces/src/services/workspaces-migration.service.mjs +1 -1
- package/esm2020/workspaces/src/services/workspaces.service.mjs +2 -1
- package/esm2020/workspaces/src/types/workspace.mjs +1 -1
- package/esm2020/workspaces/src/utils/app-loader/app-loader.mjs +3 -3
- package/esm2020/workspaces/src/utils/device-icon.mjs +1 -1
- package/esm2020/workspaces/src/workspaces.component.mjs +8 -8
- package/esm2020/workspaces/src/workspaces.module.mjs +4 -1
- package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs +999 -128
- package/fesm2015/tuki-io-tuki-widgets-contact-center.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-di2mt.mjs +20 -20
- package/fesm2015/tuki-io-tuki-widgets-di2mt.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-locations.mjs +6 -6
- package/fesm2015/tuki-io-tuki-widgets-locations.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-meetings.mjs +8 -8
- package/fesm2015/tuki-io-tuki-widgets-meetings.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-user-creation.mjs +6 -6
- package/fesm2015/tuki-io-tuki-widgets-user-creation.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-user-device-manage.mjs +1029 -51
- package/fesm2015/tuki-io-tuki-widgets-user-device-manage.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-user-manage.mjs +18 -18
- package/fesm2015/tuki-io-tuki-widgets-user-manage.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-users-list.mjs +12 -12
- package/fesm2015/tuki-io-tuki-widgets-users-list.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets-workspaces.mjs +151 -25
- package/fesm2015/tuki-io-tuki-widgets-workspaces.mjs.map +1 -1
- package/fesm2015/tuki-io-tuki-widgets.mjs +8 -8
- package/fesm2015/tuki-io-tuki-widgets.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs +990 -128
- package/fesm2020/tuki-io-tuki-widgets-contact-center.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-di2mt.mjs +20 -20
- package/fesm2020/tuki-io-tuki-widgets-di2mt.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-locations.mjs +6 -6
- package/fesm2020/tuki-io-tuki-widgets-locations.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-meetings.mjs +8 -8
- package/fesm2020/tuki-io-tuki-widgets-meetings.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-user-creation.mjs +6 -6
- package/fesm2020/tuki-io-tuki-widgets-user-creation.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-user-device-manage.mjs +1012 -50
- package/fesm2020/tuki-io-tuki-widgets-user-device-manage.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-user-manage.mjs +18 -18
- package/fesm2020/tuki-io-tuki-widgets-user-manage.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-users-list.mjs +12 -12
- package/fesm2020/tuki-io-tuki-widgets-users-list.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets-workspaces.mjs +142 -25
- package/fesm2020/tuki-io-tuki-widgets-workspaces.mjs.map +1 -1
- package/fesm2020/tuki-io-tuki-widgets.mjs +8 -8
- package/fesm2020/tuki-io-tuki-widgets.mjs.map +1 -1
- package/package.json +1 -1
- package/user-device-manage/public-api.d.ts +3 -0
- package/user-device-manage/src/app.constants.d.ts +6 -0
- package/user-device-manage/src/associate-lines/associate-lines.component.d.ts +95 -0
- package/user-device-manage/src/classes/device.d.ts +15 -0
- package/user-device-manage/src/classes/deviceProfile.d.ts +5 -0
- package/user-device-manage/src/device-associated-line/device-associated-line.component.d.ts +1 -0
- package/user-device-manage/src/device-manage-widget.component.d.ts +6 -1
- package/user-device-manage/src/device-settings/device-settings.component.d.ts +53 -0
- package/user-device-manage/src/line-key-config/line-key-config.component.d.ts +84 -0
- package/user-device-manage/src/services/device.service.d.ts +6 -1
- package/user-device-manage/src/services/user.service.d.ts +2 -1
- package/user-device-manage/src/user-device-manage.module.d.ts +10 -7
- package/workspaces/src/components/workspace-detail/workspace-detail.component.d.ts +6 -1
- package/workspaces/src/components/workspace-device-detail/workspace-device-detail.component.d.ts +25 -0
- package/workspaces/src/components/workspaces-table/workspaces-table.component.d.ts +1 -0
- package/workspaces/src/services/workspace-detail.service.d.ts +2 -0
- package/workspaces/src/types/workspace.d.ts +19 -0
- package/workspaces/src/workspaces.module.d.ts +8 -7
- package/contact-center/cc-readiness/components/card/card.component.d.ts +0 -6
- package/esm2020/contact-center/cc-readiness/components/card/card.component.mjs +0 -13
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, Component, Input, NgModule, ChangeDetectionStrategy, Inject, EventEmitter, Output, ViewChild } from '@angular/core';
|
|
2
|
+
import { Injectable, inject, Component, Input, NgModule, ChangeDetectionStrategy, Inject, EventEmitter, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/common/http';
|
|
6
6
|
import { HttpHeaders, HttpClientModule } from '@angular/common/http';
|
|
7
|
-
import { map, catchError, of, finalize, Subject, forkJoin, throwError } from 'rxjs';
|
|
8
|
-
import * as
|
|
9
|
-
import { NgApexchartsModule } from 'ng-apexcharts';
|
|
10
|
-
import * as i3 from '@angular/material/select';
|
|
7
|
+
import { map, catchError, of, finalize, Subject, forkJoin, throwError, delay, switchMap, Subscription } from 'rxjs';
|
|
8
|
+
import * as i6 from '@angular/material/select';
|
|
11
9
|
import { MatSelectModule } from '@angular/material/select';
|
|
12
|
-
import * as
|
|
10
|
+
import * as i3 from '@angular/material/core';
|
|
13
11
|
import { MatOptionModule } from '@angular/material/core';
|
|
12
|
+
import * as i5 from 'ng-apexcharts';
|
|
13
|
+
import { NgApexchartsModule } from 'ng-apexcharts';
|
|
14
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
15
|
+
import { MatTableModule } from '@angular/material/table';
|
|
16
|
+
import * as i3$1 from '@angular/material/tooltip';
|
|
17
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
18
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
14
19
|
import * as i1$4 from '@angular/material/button';
|
|
15
20
|
import { MatButtonModule } from '@angular/material/button';
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import
|
|
21
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
22
|
+
import * as i2$1 from '@angular/material/form-field';
|
|
23
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
24
|
+
import { MatInputModule } from '@angular/material/input';
|
|
25
|
+
import * as i4 from '@angular/material/progress-spinner';
|
|
19
26
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
20
|
-
import {
|
|
27
|
+
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
21
28
|
import cytoscape from 'cytoscape';
|
|
22
29
|
import dagre from 'cytoscape-dagre';
|
|
23
30
|
import nodeHtmlLabel from 'cytoscape-node-html-label';
|
|
@@ -25,17 +32,12 @@ import * as i1$2 from '@angular/material/dialog';
|
|
|
25
32
|
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
26
33
|
import { __rest } from 'tslib';
|
|
27
34
|
import * as uuid from 'uuid';
|
|
28
|
-
import * as i3$1 from '@angular/material/tooltip';
|
|
29
|
-
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
30
35
|
import * as i1$3 from '@angular/platform-browser';
|
|
31
|
-
import * as i2
|
|
36
|
+
import * as i2 from '@angular/forms';
|
|
32
37
|
import { FormsModule } from '@angular/forms';
|
|
33
|
-
import * as i2$2 from '@angular/material/form-field';
|
|
34
|
-
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
35
38
|
import { mergeMap, takeUntil, finalize as finalize$1, tap } from 'rxjs/operators';
|
|
36
|
-
import
|
|
37
|
-
import {
|
|
38
|
-
import { MatInputModule } from '@angular/material/input';
|
|
39
|
+
import * as i2$2 from '@angular/material/stepper';
|
|
40
|
+
import { MatStepperModule } from '@angular/material/stepper';
|
|
39
41
|
|
|
40
42
|
class APIService {
|
|
41
43
|
constructor(httpClient) {
|
|
@@ -46,10 +48,15 @@ class APIService {
|
|
|
46
48
|
params = params || {};
|
|
47
49
|
return this.httpClient.get(this.apiUrl + url, { params: this.prepareEncodedParams(params), headers });
|
|
48
50
|
}
|
|
49
|
-
post(url, body, params = {}) {
|
|
51
|
+
post(url, body, params = {}, options = {}) {
|
|
50
52
|
body = body || null;
|
|
51
53
|
const headers = this.getHeaders();
|
|
52
|
-
return this.httpClient.post(this.apiUrl + url, body, {
|
|
54
|
+
return this.httpClient.post(this.apiUrl + url, body, {
|
|
55
|
+
params: this.prepareEncodedParams(params),
|
|
56
|
+
headers,
|
|
57
|
+
// Some migration endpoints answer with a file rather than JSON.
|
|
58
|
+
responseType: (options.responseType || 'json')
|
|
59
|
+
});
|
|
53
60
|
}
|
|
54
61
|
// use when response extended data is necessary:
|
|
55
62
|
postExtended(url, body = null, params = {}, headers = {}) {
|
|
@@ -118,6 +125,31 @@ const API = {
|
|
|
118
125
|
READINESS: {
|
|
119
126
|
UCCX_SERVER_ENTITY_STATS: (customerId) => `/api/uccx/migration/customer/${customerId}/entity-counts`,
|
|
120
127
|
LICENSE_USAGE_SUMMARY: (customerId) => `/api/uccx/migration/customer/${customerId}/cc-license-stats`,
|
|
128
|
+
},
|
|
129
|
+
/**
|
|
130
|
+
* The application-centric UCCX migration endpoints, as used by webex-ops-client
|
|
131
|
+
* (`ContactCenterService` / `constants.json`). There is no dedicated
|
|
132
|
+
* "contact center" API - a contact center *is* a UCCX application, and its
|
|
133
|
+
* entities are reached through the e2emigration batches that carry it.
|
|
134
|
+
*/
|
|
135
|
+
UCCX: {
|
|
136
|
+
/** Every UCCX application known for the customer. Served by the **dcp** host. */
|
|
137
|
+
APPLICATION_NAMES: (customerId) => `/api/cache/uccx/application/customer/${customerId}/getall`,
|
|
138
|
+
/** All UCCX batches for the customer, one per entity type. */
|
|
139
|
+
BATCHES: (customerId) => `/api/e2emigration/batch/${customerId}/UCCX`,
|
|
140
|
+
/**
|
|
141
|
+
* The entities of one batch.
|
|
142
|
+
*
|
|
143
|
+
* It also takes an `applicationName` param, but on dev2 that filter answers
|
|
144
|
+
* `[]` for every application - including ones whose items *do* carry a
|
|
145
|
+
* matching `applicationName` - so the widget reads the batch unfiltered and
|
|
146
|
+
* narrows on the item field itself.
|
|
147
|
+
*/
|
|
148
|
+
BATCH_ITEMS: (customerId, batchId) => `/api/e2emigration/batch/${batchId}/customer/${customerId}/uccx/filter`,
|
|
149
|
+
/** Per-AEF-script migration state (NEW / MIGRATED / MIGRATION_FAILED / ...). */
|
|
150
|
+
CALL_FLOW_MIGRATION_STATUSES: (customerId) => `/api/uccx/migration/customer/${customerId}/callflow/getAll`,
|
|
151
|
+
/** Runs the UCCX -> Webex Contact Center migration. Responds with an XLSX tracker. */
|
|
152
|
+
MIGRATE: (customerId) => `/api/migration/webex/customer/${customerId}/uccx/migrate`,
|
|
121
153
|
}
|
|
122
154
|
};
|
|
123
155
|
|
|
@@ -154,15 +186,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
154
186
|
}]
|
|
155
187
|
}], ctorParameters: function () { return []; } });
|
|
156
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Standard contact-center panel chrome. Content goes into the `card-content` slot;
|
|
191
|
+
* `card-title-adornment` takes a small element rendered next to the title (info icon,
|
|
192
|
+
* badge).
|
|
193
|
+
*/
|
|
157
194
|
class CardComponent {
|
|
195
|
+
constructor() {
|
|
196
|
+
/** Tightens the padding and inner spacing for compact panels. */
|
|
197
|
+
this.dense = false;
|
|
198
|
+
}
|
|
158
199
|
}
|
|
159
200
|
CardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
160
|
-
CardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CardComponent, selector: "tk-card", inputs: { title: "title" }, ngImport: i0, template: "<article class=\"card\">\r\n <header class=\"card__header\">\r\n <h2>{{ title }}</h2>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] });
|
|
201
|
+
CardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: CardComponent, selector: "tk-card", inputs: { title: "title", dense: "dense" }, ngImport: i0, template: "<article class=\"card\" [class.card--dense]=\"dense\">\r\n <header class=\"card__header\">\r\n <div class=\"card__title-group\">\r\n <h2>{{ title }}</h2>\r\n <ng-content select=\"card-title-adornment\"></ng-content>\r\n </div>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card--dense{border-radius:8px;padding:1.5rem;gap:1.25rem}.card--dense .card__content{gap:1.25rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__title-group{display:flex;align-items:center;gap:.375rem}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] });
|
|
161
202
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CardComponent, decorators: [{
|
|
162
203
|
type: Component,
|
|
163
|
-
args: [{ selector: 'tk-card', template: "<article class=\"card\">\r\n <header class=\"card__header\">\r\n <h2>{{ title }}</h2>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] }]
|
|
204
|
+
args: [{ selector: 'tk-card', template: "<article class=\"card\" [class.card--dense]=\"dense\">\r\n <header class=\"card__header\">\r\n <div class=\"card__title-group\">\r\n <h2>{{ title }}</h2>\r\n <ng-content select=\"card-title-adornment\"></ng-content>\r\n </div>\r\n <!--<div class=\"card__menu-button\">\r\n <img width=\"18\" src=\"assets/icons/menu_icon.png\" alt=\"Menu Icon\">\r\n </div>-->\r\n </header>\r\n <div class=\"card__content\">\r\n <ng-content select=\"card-content\"></ng-content>\r\n </div>\r\n</article>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;height:100%;box-sizing:border-box}.card{font-family:Inter,Inter,sans-serif;background-color:#fff;border-radius:1rem;padding:2rem;border:1px solid hsla(0,0%,0%,.2);min-width:300px;max-width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;gap:2.5rem}.card--dense{border-radius:8px;padding:1.5rem;gap:1.25rem}.card--dense .card__content{gap:1.25rem}.card__header{position:relative;display:flex;align-items:center;justify-content:space-between}.card__header h2{font-size:16px;margin:0}.card__header .card__menu-button{position:relative;display:flex;align-items:center}.card__title-group{display:flex;align-items:center;gap:.375rem}.card__content{display:flex;flex-direction:column;gap:2.5rem;flex-grow:1}\n"] }]
|
|
164
205
|
}], propDecorators: { title: [{
|
|
165
206
|
type: Input
|
|
207
|
+
}], dense: [{
|
|
208
|
+
type: Input
|
|
166
209
|
}] } });
|
|
167
210
|
|
|
168
211
|
const LEGEND_COLORS = {
|
|
@@ -342,10 +385,10 @@ class LicencesRequirementComponent {
|
|
|
342
385
|
}
|
|
343
386
|
}
|
|
344
387
|
LicencesRequirementComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LicencesRequirementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
345
|
-
LicencesRequirementComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: LicencesRequirementComponent, selector: "cc-licenses-requirement", inputs: { customerId: "customerId", host: "host", token: "token" }, usesOnChanges: true, ngImport: i0, template: "<tk-card title=\"Licenses requirement\">\n <ng-container ngProjectAs=\"card-content\">\n <div\n class=\"widget-body\"\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\n >\n <div class=\"left-section\">\n <mat-select\n [(value)]=\"selectedSummaryIndex\"\n (selectionChange)=\"onFilterChange($event.value)\"\n class=\"filter-select\"\n >\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\n {{ option }}\n </mat-option>\n </mat-select>\n\n <div class=\"chart-section\">\n <div class=\"chart-wrapper\">\n <apx-chart\n [series]=\"viewModel.chartOptions.series\"\n [chart]=\"viewModel.chartOptions.chart\"\n [labels]=\"viewModel.chartOptions.labels\"\n [colors]=\"viewModel.chartOptions.colors\"\n [legend]=\"viewModel.chartOptions.legend\"\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\n [tooltip]=\"viewModel.chartOptions.tooltip\"\n >\n </apx-chart>\n </div>\n <div class=\"legend\">\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\n <span\n class=\"legend-marker\"\n [style.backgroundColor]=\"item.color\"\n ></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ item.count | number }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"divider\" aria-hidden=\"true\"></div>\n\n <div class=\"table-section\">\n <div class=\"lic-table-header\">\n <span>License</span>\n <span>Required</span>\n </div>\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\n <span>{{ row.label }}</span>\n <span>{{ row.value | number }}</span>\n </div>\n <div class=\"table-row total-row\">\n <span>Total</span>\n <span>{{ viewModel.totalRequired | number }}</span>\n </div>\n </div>\n </div>\n\n <ng-template #widgetState>\n <div class=\"state-message\" *ngIf=\"loading\">\n Loading license requirements\u2026\n </div>\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\n Unable to load license requirements.\n </div>\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\n No license data available.\n </div>\n </ng-template>\n </ng-container>\n</tk-card>\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.lic-table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.lic-table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type:
|
|
388
|
+
LicencesRequirementComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: LicencesRequirementComponent, selector: "cc-licenses-requirement", inputs: { customerId: "customerId", host: "host", token: "token" }, usesOnChanges: true, ngImport: i0, template: "<tk-card title=\"Licenses requirement\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div\r\n class=\"widget-body\"\r\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\r\n >\r\n <div class=\"left-section\">\r\n <mat-select\r\n [(value)]=\"selectedSummaryIndex\"\r\n (selectionChange)=\"onFilterChange($event.value)\"\r\n class=\"filter-select\"\r\n >\r\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\r\n {{ option }}\r\n </mat-option>\r\n </mat-select>\r\n\r\n <div class=\"chart-section\">\r\n <div class=\"chart-wrapper\">\r\n <apx-chart\r\n [series]=\"viewModel.chartOptions.series\"\r\n [chart]=\"viewModel.chartOptions.chart\"\r\n [labels]=\"viewModel.chartOptions.labels\"\r\n [colors]=\"viewModel.chartOptions.colors\"\r\n [legend]=\"viewModel.chartOptions.legend\"\r\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\r\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\r\n [tooltip]=\"viewModel.chartOptions.tooltip\"\r\n >\r\n </apx-chart>\r\n </div>\r\n <div class=\"legend\">\r\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\r\n <span\r\n class=\"legend-marker\"\r\n [style.backgroundColor]=\"item.color\"\r\n ></span>\r\n <span class=\"legend-label\">{{ item.label }}</span>\r\n <span class=\"legend-value\">{{ item.count | number }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"divider\" aria-hidden=\"true\"></div>\r\n\r\n <div class=\"table-section\">\r\n <div class=\"lic-table-header\">\r\n <span>License</span>\r\n <span>Required</span>\r\n </div>\r\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\r\n <span>{{ row.label }}</span>\r\n <span>{{ row.value | number }}</span>\r\n </div>\r\n <div class=\"table-row total-row\">\r\n <span>Total</span>\r\n <span>{{ viewModel.totalRequired | number }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <ng-template #widgetState>\r\n <div class=\"state-message\" *ngIf=\"loading\">\r\n Loading license requirements\u2026\r\n </div>\r\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\r\n Unable to load license requirements.\r\n </div>\r\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\r\n No license data available.\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n</tk-card>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.lic-table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.lic-table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i3.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title", "dense"] }, { kind: "component", type: i5.ChartComponent, selector: "apx-chart", inputs: ["chart", "annotations", "colors", "dataLabels", "series", "stroke", "labels", "legend", "markers", "noData", "fill", "tooltip", "plotOptions", "responsive", "xaxis", "yaxis", "forecastDataPoints", "grid", "states", "title", "subtitle", "theme", "autoUpdateSeries"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }] });
|
|
346
389
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LicencesRequirementComponent, decorators: [{
|
|
347
390
|
type: Component,
|
|
348
|
-
args: [{ selector: 'cc-licenses-requirement', template: "<tk-card title=\"Licenses requirement\">\n <ng-container ngProjectAs=\"card-content\">\n <div\n class=\"widget-body\"\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\n >\n <div class=\"left-section\">\n <mat-select\n [(value)]=\"selectedSummaryIndex\"\n (selectionChange)=\"onFilterChange($event.value)\"\n class=\"filter-select\"\n >\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\n {{ option }}\n </mat-option>\n </mat-select>\n\n <div class=\"chart-section\">\n <div class=\"chart-wrapper\">\n <apx-chart\n [series]=\"viewModel.chartOptions.series\"\n [chart]=\"viewModel.chartOptions.chart\"\n [labels]=\"viewModel.chartOptions.labels\"\n [colors]=\"viewModel.chartOptions.colors\"\n [legend]=\"viewModel.chartOptions.legend\"\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\n [tooltip]=\"viewModel.chartOptions.tooltip\"\n >\n </apx-chart>\n </div>\n <div class=\"legend\">\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\n <span\n class=\"legend-marker\"\n [style.backgroundColor]=\"item.color\"\n ></span>\n <span class=\"legend-label\">{{ item.label }}</span>\n <span class=\"legend-value\">{{ item.count | number }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"divider\" aria-hidden=\"true\"></div>\n\n <div class=\"table-section\">\n <div class=\"lic-table-header\">\n <span>License</span>\n <span>Required</span>\n </div>\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\n <span>{{ row.label }}</span>\n <span>{{ row.value | number }}</span>\n </div>\n <div class=\"table-row total-row\">\n <span>Total</span>\n <span>{{ viewModel.totalRequired | number }}</span>\n </div>\n </div>\n </div>\n\n <ng-template #widgetState>\n <div class=\"state-message\" *ngIf=\"loading\">\n Loading license requirements\u2026\n </div>\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\n Unable to load license requirements.\n </div>\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\n No license data available.\n </div>\n </ng-template>\n </ng-container>\n</tk-card>\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.lic-table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.lic-table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"] }]
|
|
391
|
+
args: [{ selector: 'cc-licenses-requirement', template: "<tk-card title=\"Licenses requirement\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div\r\n class=\"widget-body\"\r\n *ngIf=\"!loading && !error && viewModel; else widgetState\"\r\n >\r\n <div class=\"left-section\">\r\n <mat-select\r\n [(value)]=\"selectedSummaryIndex\"\r\n (selectionChange)=\"onFilterChange($event.value)\"\r\n class=\"filter-select\"\r\n >\r\n <mat-option *ngFor=\"let option of filters; index as i\" [value]=\"i\">\r\n {{ option }}\r\n </mat-option>\r\n </mat-select>\r\n\r\n <div class=\"chart-section\">\r\n <div class=\"chart-wrapper\">\r\n <apx-chart\r\n [series]=\"viewModel.chartOptions.series\"\r\n [chart]=\"viewModel.chartOptions.chart\"\r\n [labels]=\"viewModel.chartOptions.labels\"\r\n [colors]=\"viewModel.chartOptions.colors\"\r\n [legend]=\"viewModel.chartOptions.legend\"\r\n [plotOptions]=\"viewModel.chartOptions.plotOptions\"\r\n [dataLabels]=\"viewModel.chartOptions.dataLabels\"\r\n [tooltip]=\"viewModel.chartOptions.tooltip\"\r\n >\r\n </apx-chart>\r\n </div>\r\n <div class=\"legend\">\r\n <div class=\"legend-item\" *ngFor=\"let item of viewModel.legendItems\">\r\n <span\r\n class=\"legend-marker\"\r\n [style.backgroundColor]=\"item.color\"\r\n ></span>\r\n <span class=\"legend-label\">{{ item.label }}</span>\r\n <span class=\"legend-value\">{{ item.count | number }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"divider\" aria-hidden=\"true\"></div>\r\n\r\n <div class=\"table-section\">\r\n <div class=\"lic-table-header\">\r\n <span>License</span>\r\n <span>Required</span>\r\n </div>\r\n <div class=\"table-row\" *ngFor=\"let row of viewModel.rows\">\r\n <span>{{ row.label }}</span>\r\n <span>{{ row.value | number }}</span>\r\n </div>\r\n <div class=\"table-row total-row\">\r\n <span>Total</span>\r\n <span>{{ viewModel.totalRequired | number }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <ng-template #widgetState>\r\n <div class=\"state-message\" *ngIf=\"loading\">\r\n Loading license requirements\u2026\r\n </div>\r\n <div class=\"state-message error\" *ngIf=\"!loading && error\">\r\n Unable to load license requirements.\r\n </div>\r\n <div class=\"state-message\" *ngIf=\"!loading && !error && !viewModel\">\r\n No license data available.\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n</tk-card>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;width:100%;box-sizing:border-box}.filter-select{font-family:Inter,Inter,sans-serif;font-size:14px;min-width:140px;border:1px solid #e5e7eb;border-radius:.5rem;padding:.5rem .75rem;background-color:#fff}.filter-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select{border:1px solid #e5e7eb;border-radius:.5rem;background-color:#fff}:host ::ng-deep .filter-select.mat-mdc-select:hover{border-color:#d1d5db}:host ::ng-deep .filter-select.mat-mdc-select.mat-focused{border-color:#16a693}:host ::ng-deep .filter-select .mat-mdc-select-trigger{font-size:14px;padding:.5rem .75rem}:host ::ng-deep .filter-select .mat-mdc-select-value{color:#111827}:host ::ng-deep .filter-select .mat-mdc-select-arrow-wrapper{padding-left:.5rem}.widget-body{display:flex;gap:2.5rem;align-items:flex-start}.left-section{flex:2;display:flex;flex-direction:column;gap:1rem}.chart-section{display:flex;gap:1.5rem;align-items:center}.chart-wrapper{width:220px;min-height:220px;flex-shrink:0}.chart-wrapper apx-chart{width:220px!important;height:220px!important}.legend{display:flex;flex-direction:column;gap:.75rem}.legend-item{display:flex;align-items:center;gap:.5rem;font-family:Inter,Inter,sans-serif;font-size:14px}.legend-marker{width:14px;height:14px;border-radius:50%;display:inline-flex}.legend-label{color:#4b5563}.legend-value{margin-left:auto;font-weight:600;color:#111827}.divider{width:1px;min-height:200px;align-self:stretch;background:#e5e7eb}.table-section{flex:3;display:flex;flex-direction:column;gap:.75rem;font-family:Inter,Inter,sans-serif}.lic-table-header,.table-row{display:flex;justify-content:space-between;font-size:14px}.lic-table-header{font-weight:600;color:#6b7280;padding-bottom:.5rem;border-bottom:1px solid #e5e7eb}.table-row{color:#111827}.total-row{font-weight:700;margin-top:.5rem;padding-top:.5rem;border-top:1px solid #e5e7eb}.state-message{font-family:Inter,Inter,sans-serif;font-size:14px;color:#6b7280}.state-message.error{color:#b91c1c}@media (max-width: 960px){.widget-body{flex-direction:column}.divider{display:none}.chart-section{justify-content:space-between}}:host ::ng-deep .apexcharts-legend{display:none!important}\n"] }]
|
|
349
392
|
}], propDecorators: { customerId: [{
|
|
350
393
|
type: Input
|
|
351
394
|
}], host: [{
|
|
@@ -386,7 +429,7 @@ class SummaryGridComponent {
|
|
|
386
429
|
}
|
|
387
430
|
}
|
|
388
431
|
SummaryGridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SummaryGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
389
|
-
SummaryGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SummaryGridComponent, selector: "cc-summary-grid", inputs: { customerId: "customerId", host: "host", token: "token" }, ngImport: i0, template: "<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>", styles: [".grid-wrapper{display:grid;grid-template-columns:repeat(6,1fr);gap:2rem;row-gap:2rem}.grid-item{display:flex;flex-direction:column;gap:.5rem}.item-top{display:flex;align-items:center;gap:inherit}.item-icon{display:flex;align-items:center;background-color:#f2f2f2;padding:.75rem;border-radius:.5rem}.item-count{font-size:30px}.item-label{font-size:14px;margin-left:.15rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] });
|
|
432
|
+
SummaryGridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SummaryGridComponent, selector: "cc-summary-grid", inputs: { customerId: "customerId", host: "host", token: "token" }, ngImport: i0, template: "<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>", styles: [".grid-wrapper{display:grid;grid-template-columns:repeat(6,1fr);gap:2rem;row-gap:2rem}.grid-item{display:flex;flex-direction:column;gap:.5rem}.item-top{display:flex;align-items:center;gap:inherit}.item-icon{display:flex;align-items:center;background-color:#f2f2f2;padding:.75rem;border-radius:.5rem}.item-count{font-size:30px}.item-label{font-size:14px;margin-left:.15rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title", "dense"] }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }] });
|
|
390
433
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SummaryGridComponent, decorators: [{
|
|
391
434
|
type: Component,
|
|
392
435
|
args: [{ selector: 'cc-summary-grid', template: "<ng-container *ngIf=\"data$ | async as data\">\r\n <div *ngFor=\"let stats of data\">\r\n <tk-card [title]=\"stats.uccxIp\">\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"grid-wrapper\">\r\n <div class=\"grid-item\" *ngFor=\"let item of stats.counts\">\r\n <div class=\"item-top\">\r\n <span class=\"item-icon\">\r\n <img width=\"24\" height=\"24\" src=\"assets/icons/{{ item.name }}.svg\" alt=\"{{ item.name }} Icon\">\r\n </span>\r\n <span class=\"item-count\">{{ item.value }}</span>\r\n </div>\r\n <span class=\"item-label\">{{ ENTITY_CONFIG[item.name].label }}</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </tk-card>\r\n </div>\r\n</ng-container>", styles: [".grid-wrapper{display:grid;grid-template-columns:repeat(6,1fr);gap:2rem;row-gap:2rem}.grid-item{display:flex;flex-direction:column;gap:.5rem}.item-top{display:flex;align-items:center;gap:inherit}.item-icon{display:flex;align-items:center;background-color:#f2f2f2;padding:.75rem;border-radius:.5rem}.item-count{font-size:30px}.item-label{font-size:14px;margin-left:.15rem}\n"] }]
|
|
@@ -398,12 +441,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
398
441
|
type: Input
|
|
399
442
|
}] } });
|
|
400
443
|
|
|
444
|
+
class MaterialModule {
|
|
445
|
+
}
|
|
446
|
+
MaterialModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
447
|
+
MaterialModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
|
|
448
|
+
MatTooltipModule,
|
|
449
|
+
MatTableModule,
|
|
450
|
+
MatCheckboxModule,
|
|
451
|
+
MatButtonModule,
|
|
452
|
+
MatIconModule,
|
|
453
|
+
MatFormFieldModule,
|
|
454
|
+
MatInputModule,
|
|
455
|
+
MatSelectModule], exports: [MatProgressBarModule,
|
|
456
|
+
MatTooltipModule,
|
|
457
|
+
MatTableModule,
|
|
458
|
+
MatCheckboxModule,
|
|
459
|
+
MatButtonModule,
|
|
460
|
+
MatIconModule,
|
|
461
|
+
MatFormFieldModule,
|
|
462
|
+
MatInputModule,
|
|
463
|
+
MatSelectModule,
|
|
464
|
+
MatProgressSpinnerModule] });
|
|
465
|
+
MaterialModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
|
|
466
|
+
MatTooltipModule,
|
|
467
|
+
MatTableModule,
|
|
468
|
+
MatCheckboxModule,
|
|
469
|
+
MatButtonModule,
|
|
470
|
+
MatIconModule,
|
|
471
|
+
MatFormFieldModule,
|
|
472
|
+
MatInputModule,
|
|
473
|
+
MatSelectModule, MatProgressBarModule,
|
|
474
|
+
MatTooltipModule,
|
|
475
|
+
MatTableModule,
|
|
476
|
+
MatCheckboxModule,
|
|
477
|
+
MatButtonModule,
|
|
478
|
+
MatIconModule,
|
|
479
|
+
MatFormFieldModule,
|
|
480
|
+
MatInputModule,
|
|
481
|
+
MatSelectModule,
|
|
482
|
+
MatProgressSpinnerModule] });
|
|
483
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, decorators: [{
|
|
484
|
+
type: NgModule,
|
|
485
|
+
args: [{
|
|
486
|
+
imports: [
|
|
487
|
+
MatProgressBarModule,
|
|
488
|
+
MatTooltipModule,
|
|
489
|
+
MatTableModule,
|
|
490
|
+
MatCheckboxModule,
|
|
491
|
+
MatButtonModule,
|
|
492
|
+
MatIconModule,
|
|
493
|
+
MatFormFieldModule,
|
|
494
|
+
MatInputModule,
|
|
495
|
+
MatSelectModule
|
|
496
|
+
],
|
|
497
|
+
exports: [
|
|
498
|
+
MatProgressBarModule,
|
|
499
|
+
MatTooltipModule,
|
|
500
|
+
MatTableModule,
|
|
501
|
+
MatCheckboxModule,
|
|
502
|
+
MatButtonModule,
|
|
503
|
+
MatIconModule,
|
|
504
|
+
MatFormFieldModule,
|
|
505
|
+
MatInputModule,
|
|
506
|
+
MatSelectModule,
|
|
507
|
+
MatProgressSpinnerModule
|
|
508
|
+
]
|
|
509
|
+
}]
|
|
510
|
+
}] });
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Presentational building blocks shared by the contact-center widgets.
|
|
514
|
+
* Widget modules import this to pick up the standard card chrome plus the
|
|
515
|
+
* Material/Apex modules they all need.
|
|
516
|
+
*/
|
|
517
|
+
class SharedModule {
|
|
518
|
+
}
|
|
519
|
+
SharedModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
520
|
+
SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, declarations: [CardComponent], imports: [CommonModule,
|
|
521
|
+
MaterialModule,
|
|
522
|
+
NgApexchartsModule,
|
|
523
|
+
HttpClientModule], exports: [MaterialModule,
|
|
524
|
+
CardComponent] });
|
|
525
|
+
SharedModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, imports: [CommonModule,
|
|
526
|
+
MaterialModule,
|
|
527
|
+
NgApexchartsModule,
|
|
528
|
+
HttpClientModule, MaterialModule] });
|
|
529
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, decorators: [{
|
|
530
|
+
type: NgModule,
|
|
531
|
+
args: [{
|
|
532
|
+
declarations: [
|
|
533
|
+
CardComponent
|
|
534
|
+
],
|
|
535
|
+
imports: [
|
|
536
|
+
CommonModule,
|
|
537
|
+
MaterialModule,
|
|
538
|
+
NgApexchartsModule,
|
|
539
|
+
HttpClientModule
|
|
540
|
+
],
|
|
541
|
+
exports: [
|
|
542
|
+
MaterialModule,
|
|
543
|
+
CardComponent
|
|
544
|
+
]
|
|
545
|
+
}]
|
|
546
|
+
}] });
|
|
547
|
+
|
|
401
548
|
class CcReadinessModule {
|
|
402
549
|
}
|
|
403
550
|
CcReadinessModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
404
551
|
CcReadinessModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, declarations: [LicencesRequirementComponent,
|
|
405
|
-
SummaryGridComponent,
|
|
406
|
-
|
|
552
|
+
SummaryGridComponent], imports: [CommonModule,
|
|
553
|
+
SharedModule,
|
|
407
554
|
HttpClientModule,
|
|
408
555
|
NgApexchartsModule,
|
|
409
556
|
MatTableModule,
|
|
@@ -416,6 +563,7 @@ CcReadinessModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", versi
|
|
|
416
563
|
MatSelectModule], exports: [LicencesRequirementComponent,
|
|
417
564
|
SummaryGridComponent] });
|
|
418
565
|
CcReadinessModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcReadinessModule, imports: [CommonModule,
|
|
566
|
+
SharedModule,
|
|
419
567
|
HttpClientModule,
|
|
420
568
|
NgApexchartsModule,
|
|
421
569
|
MatTableModule,
|
|
@@ -431,11 +579,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
431
579
|
args: [{
|
|
432
580
|
declarations: [
|
|
433
581
|
LicencesRequirementComponent,
|
|
434
|
-
SummaryGridComponent
|
|
435
|
-
CardComponent
|
|
582
|
+
SummaryGridComponent
|
|
436
583
|
],
|
|
437
584
|
imports: [
|
|
438
585
|
CommonModule,
|
|
586
|
+
SharedModule,
|
|
439
587
|
HttpClientModule,
|
|
440
588
|
NgApexchartsModule,
|
|
441
589
|
MatTableModule,
|
|
@@ -1453,7 +1601,7 @@ class NodeDetailsSidebarComponent {
|
|
|
1453
1601
|
}
|
|
1454
1602
|
}
|
|
1455
1603
|
NodeDetailsSidebarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeDetailsSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1456
|
-
NodeDetailsSidebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NodeDetailsSidebarComponent, selector: "node-details-sidebar", inputs: { isOpen: "isOpen", nodeData: "nodeData" }, outputs: { close: "close", activityTypeChange: "activityTypeChange", descriptionChange: "descriptionChange" }, usesOnChanges: true, ngImport: i0, template: "<!-- <div class=\"sidebar-overlay\" *ngIf=\"isOpen\" (click)=\"onClose()\"></div> -->\r\n\r\n<div class=\"node-details-sidebar\" [class.open]=\"isOpen\">\r\n <div class=\"sidebar-header\">\r\n <h3>Node Details</h3>\r\n <button class=\"close-btn\" (click)=\"onClose()\">\r\n <span>×</span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"sidebar-content\" *ngIf=\"nodeData\">\r\n <!-- Node Preview -->\r\n <div class=\"node-preview\">\r\n <div class=\"node-preview-card\" [ngClass]=\"getNodeColorClass()\">\r\n <div class=\"node-icon\">\r\n <img [src]=\"getNodeIcon()\" alt=\"Node Icon\" />\r\n </div>\r\n <div class=\"node-info\">\r\n <div class=\"node-label\">{{ nodeData.name?.split(\"\\n\")?.[0] }}</div>\r\n <div class=\"node-type\">{{ transformedActivityName }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity Type Selector -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Activity Type</label>\r\n <div class=\"display-type-selector\">\r\n <select\r\n class=\"form-control\"\r\n title=\"Select activity type\"\r\n [value]=\"selectedActivityType?.value\"\r\n (change)=\"onActivityTypeSelectChange($event)\"\r\n >\r\n <option\r\n *ngFor=\"let type of activityDisplayTypes; trackBy: trackByValue\"\r\n [value]=\"type.value\"\r\n >\r\n {{ type.label }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section\">\r\n <label class=\"section-label\">Description</label>\r\n <div class=\"display-type-selector\">\r\n <textarea\r\n class=\"form-control\"\r\n aria-label=\"property-description\"\r\n (input)=\"onDescriptionChange($event)\"\r\n [value]=\"nodeData.suggestedProperties?.uccxDescription\"\r\n rows=\"3\"\r\n ></textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Node Information -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Information</label>\r\n <div class=\"info-grid\">\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">UCCX Type:</span>\r\n <span class=\"info-value\" [title]=\"nodeData.uccxTypeName\">{{\r\n nodeData.uccxTypeName\r\n }}</span>\r\n </div>\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">WxCC Activity Name:</span>\r\n <span class=\"info-value\" [title]=\"transformedActivityName\">{{\r\n transformedActivityName\r\n }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Review Status -->\r\n <div class=\"section\" *ngIf=\"nodeData.review\">\r\n <label class=\"section-label\">Review Status</label>\r\n <div class=\"review-status\">\r\n <div class=\"review-badge\" [style.background-color]=\"getReviewColor()\">\r\n {{ getReviewLabel() }}\r\n </div>\r\n <div\r\n class=\"review-reasons\"\r\n *ngIf=\"nodeData.review.reasons && nodeData.review.reasons.length > 0\"\r\n >\r\n <div class=\"reason\" *ngFor=\"let reason of nodeData.review.reasons\">\r\n <span class=\"reason-icon\">\u26A0</span>\r\n <span>{{ reason }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Suggested Properties -->\r\n <div class=\"section\" *ngIf=\"nodeData.suggestedProperties\">\r\n <label class=\"section-label\">Migration Information</label>\r\n <div class=\"migration-info\">\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.closestWxccActivity\"\r\n >\r\n <div class=\"card-label\">Closest WXCC Activity</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.closestWxccActivity }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.mappingNotes\"\r\n >\r\n <div class=\"card-label\">Mapping Notes</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.mappingNotes }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.migrationInstructions\"\r\n >\r\n <div class=\"card-label\">Migration Instructions</div>\r\n <div class=\"card-value instructions\">\r\n {{ nodeData.suggestedProperties.migrationInstructions }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.node-details-sidebar{position:fixed;top:0;right:-420px;width:420px;height:100%;background:#ffffff;box-shadow:-2px 0 8px #00000026;z-index:1000;transition:right .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}.node-details-sidebar.open{right:0}.node-details-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid #e1e4e8;background:#f8f9fa}.node-details-sidebar .sidebar-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#24292e}.node-details-sidebar .sidebar-header .close-btn{background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;color:#586069;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.node-details-sidebar .sidebar-header .close-btn:hover{background:rgba(0,0,0,.05);color:#24292e}.node-details-sidebar .sidebar-content{flex:1;overflow-y:auto;padding:1.5rem}.node-details-sidebar .sidebar-content .node-preview{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .node-preview .node-preview-card{display:flex;align-items:center;gap:1rem;padding:1rem;border-radius:8px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:8px;flex-shrink:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon img{width:24px;height:24px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info{flex:1;min-width:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-label{font-size:1rem;font-weight:600;margin-bottom:.25rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-type{font-size:.875rem;color:#586069}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start{background-color:#4caf500d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-icon{background-color:#4caf501a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-label{color:#4caf50}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end{background-color:#f443360d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-icon{background-color:#f443361a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-label{color:#f44336}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway{background-color:#ff98000d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-icon{background-color:#ff98001a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-label{color:#ff9800}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action{background-color:#9c27b00d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-icon{background-color:#9c27b01a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-label{color:#9c27b0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default{background-color:#607d8b0d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-icon{background-color:#607d8b1a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-label{color:#607d8b}.node-details-sidebar .sidebar-content .section{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .section .section-label{display:block;font-size:.65rem;font-weight:600;color:#24292e;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s;box-sizing:border-box;resize:vertical}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.node-details-sidebar .sidebar-content .section .info-grid{display:flex;flex-direction:column;gap:.75rem}.node-details-sidebar .sidebar-content .section .info-grid .info-item{display:flex;justify-content:space-between;align-items:flex-start;padding:.75rem;background:#f6f8fa;border-radius:6px}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-label{font-size:.8125rem;color:#586069;font-weight:500}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-value{font-size:.8125rem;color:#24292e;font-weight:600;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .section .review-status .review-badge{display:inline-block;padding:.5rem 1rem;border-radius:20px;color:#fff;font-size:.8125rem;font-weight:600;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;background:#fff3cd;border-radius:4px;margin-bottom:.5rem;font-size:.8125rem;color:#856404}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason .reason-icon{flex-shrink:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card{padding:1rem;background:#f6f8fa;border-radius:6px;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card:last-child{margin-bottom:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-label{font-size:.75rem;font-weight:600;color:#586069;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value{font-size:.875rem;color:#24292e;line-height:1.5}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value.instructions{white-space:pre-wrap}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1604
|
+
NodeDetailsSidebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: NodeDetailsSidebarComponent, selector: "node-details-sidebar", inputs: { isOpen: "isOpen", nodeData: "nodeData" }, outputs: { close: "close", activityTypeChange: "activityTypeChange", descriptionChange: "descriptionChange" }, usesOnChanges: true, ngImport: i0, template: "<!-- <div class=\"sidebar-overlay\" *ngIf=\"isOpen\" (click)=\"onClose()\"></div> -->\r\n\r\n<div class=\"node-details-sidebar\" [class.open]=\"isOpen\">\r\n <div class=\"sidebar-header\">\r\n <h3>Node Details</h3>\r\n <button class=\"close-btn\" (click)=\"onClose()\">\r\n <span>×</span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"sidebar-content\" *ngIf=\"nodeData\">\r\n <!-- Node Preview -->\r\n <div class=\"node-preview\">\r\n <div class=\"node-preview-card\" [ngClass]=\"getNodeColorClass()\">\r\n <div class=\"node-icon\">\r\n <img [src]=\"getNodeIcon()\" alt=\"Node Icon\" />\r\n </div>\r\n <div class=\"node-info\">\r\n <div class=\"node-label\">{{ nodeData.name?.split(\"\\n\")?.[0] }}</div>\r\n <div class=\"node-type\">{{ transformedActivityName }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity Type Selector -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Activity Type</label>\r\n <div class=\"display-type-selector\">\r\n <select\r\n class=\"form-control\"\r\n title=\"Select activity type\"\r\n [value]=\"selectedActivityType?.value\"\r\n (change)=\"onActivityTypeSelectChange($event)\"\r\n >\r\n <option\r\n *ngFor=\"let type of activityDisplayTypes; trackBy: trackByValue\"\r\n [value]=\"type.value\"\r\n >\r\n {{ type.label }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section\">\r\n <label class=\"section-label\">Description</label>\r\n <div class=\"display-type-selector\">\r\n <textarea\r\n class=\"form-control\"\r\n aria-label=\"property-description\"\r\n (input)=\"onDescriptionChange($event)\"\r\n [value]=\"nodeData.suggestedProperties?.uccxDescription\"\r\n rows=\"3\"\r\n ></textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Node Information -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Information</label>\r\n <div class=\"info-grid\">\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">UCCX Type:</span>\r\n <span class=\"info-value\" [title]=\"nodeData.uccxTypeName\">{{\r\n nodeData.uccxTypeName\r\n }}</span>\r\n </div>\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">WxCC Activity Name:</span>\r\n <span class=\"info-value\" [title]=\"transformedActivityName\">{{\r\n transformedActivityName\r\n }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Review Status -->\r\n <div class=\"section\" *ngIf=\"nodeData.review\">\r\n <label class=\"section-label\">Review Status</label>\r\n <div class=\"review-status\">\r\n <div class=\"review-badge\" [style.background-color]=\"getReviewColor()\">\r\n {{ getReviewLabel() }}\r\n </div>\r\n <div\r\n class=\"review-reasons\"\r\n *ngIf=\"nodeData.review.reasons && nodeData.review.reasons.length > 0\"\r\n >\r\n <div class=\"reason\" *ngFor=\"let reason of nodeData.review.reasons\">\r\n <span class=\"reason-icon\">\u26A0</span>\r\n <span>{{ reason }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Suggested Properties -->\r\n <div class=\"section\" *ngIf=\"nodeData.suggestedProperties\">\r\n <label class=\"section-label\">Migration Information</label>\r\n <div class=\"migration-info\">\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.closestWxccActivity\"\r\n >\r\n <div class=\"card-label\">Closest WXCC Activity</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.closestWxccActivity }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.mappingNotes\"\r\n >\r\n <div class=\"card-label\">Mapping Notes</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.mappingNotes }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.migrationInstructions\"\r\n >\r\n <div class=\"card-label\">Migration Instructions</div>\r\n <div class=\"card-value instructions\">\r\n {{ nodeData.suggestedProperties.migrationInstructions }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.node-details-sidebar{position:fixed;top:0;right:-420px;width:420px;height:100%;background:#ffffff;box-shadow:-2px 0 8px #00000026;z-index:1000;transition:right .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}.node-details-sidebar.open{right:0}.node-details-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid #e1e4e8;background:#f8f9fa}.node-details-sidebar .sidebar-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#24292e}.node-details-sidebar .sidebar-header .close-btn{background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;color:#586069;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.node-details-sidebar .sidebar-header .close-btn:hover{background:rgba(0,0,0,.05);color:#24292e}.node-details-sidebar .sidebar-content{flex:1;overflow-y:auto;padding:1.5rem}.node-details-sidebar .sidebar-content .node-preview{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .node-preview .node-preview-card{display:flex;align-items:center;gap:1rem;padding:1rem;border-radius:8px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:8px;flex-shrink:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon img{width:24px;height:24px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info{flex:1;min-width:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-label{font-size:1rem;font-weight:600;margin-bottom:.25rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-type{font-size:.875rem;color:#586069}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start{background-color:#4caf500d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-icon{background-color:#4caf501a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-label{color:#4caf50}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end{background-color:#f443360d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-icon{background-color:#f443361a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-label{color:#f44336}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway{background-color:#ff98000d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-icon{background-color:#ff98001a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-label{color:#ff9800}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action{background-color:#9c27b00d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-icon{background-color:#9c27b01a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-label{color:#9c27b0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default{background-color:#607d8b0d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-icon{background-color:#607d8b1a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-label{color:#607d8b}.node-details-sidebar .sidebar-content .section{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .section .section-label{display:block;font-size:.65rem;font-weight:600;color:#24292e;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s;box-sizing:border-box;resize:vertical}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.node-details-sidebar .sidebar-content .section .info-grid{display:flex;flex-direction:column;gap:.75rem}.node-details-sidebar .sidebar-content .section .info-grid .info-item{display:flex;justify-content:space-between;align-items:flex-start;padding:.75rem;background:#f6f8fa;border-radius:6px}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-label{font-size:.8125rem;color:#586069;font-weight:500}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-value{font-size:.8125rem;color:#24292e;font-weight:600;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .section .review-status .review-badge{display:inline-block;padding:.5rem 1rem;border-radius:20px;color:#fff;font-size:.8125rem;font-weight:600;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;background:#fff3cd;border-radius:4px;margin-bottom:.5rem;font-size:.8125rem;color:#856404}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason .reason-icon{flex-shrink:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card{padding:1rem;background:#f6f8fa;border-radius:6px;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card:last-child{margin-bottom:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-label{font-size:.75rem;font-weight:600;color:#586069;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value{font-size:.875rem;color:#24292e;line-height:1.5}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value.instructions{white-space:pre-wrap}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1457
1605
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: NodeDetailsSidebarComponent, decorators: [{
|
|
1458
1606
|
type: Component,
|
|
1459
1607
|
args: [{ selector: 'node-details-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- <div class=\"sidebar-overlay\" *ngIf=\"isOpen\" (click)=\"onClose()\"></div> -->\r\n\r\n<div class=\"node-details-sidebar\" [class.open]=\"isOpen\">\r\n <div class=\"sidebar-header\">\r\n <h3>Node Details</h3>\r\n <button class=\"close-btn\" (click)=\"onClose()\">\r\n <span>×</span>\r\n </button>\r\n </div>\r\n\r\n <div class=\"sidebar-content\" *ngIf=\"nodeData\">\r\n <!-- Node Preview -->\r\n <div class=\"node-preview\">\r\n <div class=\"node-preview-card\" [ngClass]=\"getNodeColorClass()\">\r\n <div class=\"node-icon\">\r\n <img [src]=\"getNodeIcon()\" alt=\"Node Icon\" />\r\n </div>\r\n <div class=\"node-info\">\r\n <div class=\"node-label\">{{ nodeData.name?.split(\"\\n\")?.[0] }}</div>\r\n <div class=\"node-type\">{{ transformedActivityName }}</div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity Type Selector -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Activity Type</label>\r\n <div class=\"display-type-selector\">\r\n <select\r\n class=\"form-control\"\r\n title=\"Select activity type\"\r\n [value]=\"selectedActivityType?.value\"\r\n (change)=\"onActivityTypeSelectChange($event)\"\r\n >\r\n <option\r\n *ngFor=\"let type of activityDisplayTypes; trackBy: trackByValue\"\r\n [value]=\"type.value\"\r\n >\r\n {{ type.label }}\r\n </option>\r\n </select>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section\">\r\n <label class=\"section-label\">Description</label>\r\n <div class=\"display-type-selector\">\r\n <textarea\r\n class=\"form-control\"\r\n aria-label=\"property-description\"\r\n (input)=\"onDescriptionChange($event)\"\r\n [value]=\"nodeData.suggestedProperties?.uccxDescription\"\r\n rows=\"3\"\r\n ></textarea>\r\n </div>\r\n </div>\r\n\r\n <!-- Node Information -->\r\n <div class=\"section\">\r\n <label class=\"section-label\">Information</label>\r\n <div class=\"info-grid\">\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">UCCX Type:</span>\r\n <span class=\"info-value\" [title]=\"nodeData.uccxTypeName\">{{\r\n nodeData.uccxTypeName\r\n }}</span>\r\n </div>\r\n <div class=\"info-item\">\r\n <span class=\"info-label\">WxCC Activity Name:</span>\r\n <span class=\"info-value\" [title]=\"transformedActivityName\">{{\r\n transformedActivityName\r\n }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Review Status -->\r\n <div class=\"section\" *ngIf=\"nodeData.review\">\r\n <label class=\"section-label\">Review Status</label>\r\n <div class=\"review-status\">\r\n <div class=\"review-badge\" [style.background-color]=\"getReviewColor()\">\r\n {{ getReviewLabel() }}\r\n </div>\r\n <div\r\n class=\"review-reasons\"\r\n *ngIf=\"nodeData.review.reasons && nodeData.review.reasons.length > 0\"\r\n >\r\n <div class=\"reason\" *ngFor=\"let reason of nodeData.review.reasons\">\r\n <span class=\"reason-icon\">\u26A0</span>\r\n <span>{{ reason }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Suggested Properties -->\r\n <div class=\"section\" *ngIf=\"nodeData.suggestedProperties\">\r\n <label class=\"section-label\">Migration Information</label>\r\n <div class=\"migration-info\">\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.closestWxccActivity\"\r\n >\r\n <div class=\"card-label\">Closest WXCC Activity</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.closestWxccActivity }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.mappingNotes\"\r\n >\r\n <div class=\"card-label\">Mapping Notes</div>\r\n <div class=\"card-value\">\r\n {{ nodeData.suggestedProperties.mappingNotes }}\r\n </div>\r\n </div>\r\n <div\r\n class=\"info-card\"\r\n *ngIf=\"nodeData.suggestedProperties.migrationInstructions\"\r\n >\r\n <div class=\"card-label\">Migration Instructions</div>\r\n <div class=\"card-value instructions\">\r\n {{ nodeData.suggestedProperties.migrationInstructions }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.node-details-sidebar{position:fixed;top:0;right:-420px;width:420px;height:100%;background:#ffffff;box-shadow:-2px 0 8px #00000026;z-index:1000;transition:right .4s cubic-bezier(.4,0,.2,1);display:flex;flex-direction:column;overflow:hidden}.node-details-sidebar.open{right:0}.node-details-sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:1.5rem;border-bottom:1px solid #e1e4e8;background:#f8f9fa}.node-details-sidebar .sidebar-header h3{margin:0;font-size:1.25rem;font-weight:600;color:#24292e}.node-details-sidebar .sidebar-header .close-btn{background:none;border:none;font-size:2rem;line-height:1;cursor:pointer;color:#586069;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.node-details-sidebar .sidebar-header .close-btn:hover{background:rgba(0,0,0,.05);color:#24292e}.node-details-sidebar .sidebar-content{flex:1;overflow-y:auto;padding:1.5rem}.node-details-sidebar .sidebar-content .node-preview{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .node-preview .node-preview-card{display:flex;align-items:center;gap:1rem;padding:1rem;border-radius:8px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:8px;flex-shrink:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-icon img{width:24px;height:24px}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info{flex:1;min-width:0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-label{font-size:1rem;font-weight:600;margin-bottom:.25rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .node-preview .node-preview-card .node-info .node-type{font-size:.875rem;color:#586069}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start{background-color:#4caf500d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-icon{background-color:#4caf501a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-start .node-label{color:#4caf50}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end{background-color:#f443360d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-icon{background-color:#f443361a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-end .node-label{color:#f44336}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway{background-color:#ff98000d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-icon{background-color:#ff98001a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-gateway .node-label{color:#ff9800}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action{background-color:#9c27b00d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-icon{background-color:#9c27b01a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-action .node-label{color:#9c27b0}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default{background-color:#607d8b0d}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-icon{background-color:#607d8b1a}.node-details-sidebar .sidebar-content .node-preview .node-preview-card.node-default .node-label{color:#607d8b}.node-details-sidebar .sidebar-content .section{margin-bottom:1.5rem}.node-details-sidebar .sidebar-content .section .section-label{display:block;font-size:.65rem;font-weight:600;color:#24292e;margin-bottom:.75rem;text-transform:uppercase;letter-spacing:.5px}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control{width:100%;padding:.625rem .875rem;font-size:.875rem;border:1px solid #d1d5da;border-radius:6px;background:white;transition:border-color .2s;box-sizing:border-box;resize:vertical}.node-details-sidebar .sidebar-content .section .display-type-selector .form-control:focus{outline:none;border-color:#0366d6;box-shadow:0 0 0 3px #0366d61a}.node-details-sidebar .sidebar-content .section .info-grid{display:flex;flex-direction:column;gap:.75rem}.node-details-sidebar .sidebar-content .section .info-grid .info-item{display:flex;justify-content:space-between;align-items:flex-start;padding:.75rem;background:#f6f8fa;border-radius:6px}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-label{font-size:.8125rem;color:#586069;font-weight:500}.node-details-sidebar .sidebar-content .section .info-grid .info-item .info-value{font-size:.8125rem;color:#24292e;font-weight:600;text-align:right;max-width:60%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.node-details-sidebar .sidebar-content .section .review-status .review-badge{display:inline-block;padding:.5rem 1rem;border-radius:20px;color:#fff;font-size:.8125rem;font-weight:600;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;background:#fff3cd;border-radius:4px;margin-bottom:.5rem;font-size:.8125rem;color:#856404}.node-details-sidebar .sidebar-content .section .review-status .review-reasons .reason .reason-icon{flex-shrink:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card{padding:1rem;background:#f6f8fa;border-radius:6px;margin-bottom:.75rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card:last-child{margin-bottom:0}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-label{font-size:.75rem;font-weight:600;color:#586069;text-transform:uppercase;letter-spacing:.5px;margin-bottom:.5rem}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value{font-size:.875rem;color:#24292e;line-height:1.5}.node-details-sidebar .sidebar-content .section .migration-info .info-card .card-value.instructions{white-space:pre-wrap}\n"] }]
|
|
@@ -2123,7 +2271,7 @@ class WxCCFileSelectionBarComponent {
|
|
|
2123
2271
|
}
|
|
2124
2272
|
}
|
|
2125
2273
|
WxCCFileSelectionBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFileSelectionBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2126
|
-
WxCCFileSelectionBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFileSelectionBarComponent, selector: "wxcc-file-selection-bar", inputs: { fileNames: "fileNames", selectedFileName: "selectedFileName", selectedHost: "selectedHost" }, outputs: { fileNameSelectionChange: "fileNameSelectionChange" }, ngImport: i0, template: "<div class=\"file-selection-bar\">\r\n <mat-form-field appearance=\"outline\" class=\"host-selection\" *ngIf=\"hosts?.length\">\r\n <!-- <mat-label>Host</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedHost\"\r\n (selectionChange)=\"onHostSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let host of hosts; trackBy: trackByHost\"\r\n title=\"{{ host }}\"\r\n [value]=\"host\">\r\n {{ host }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"file-selection\">\r\n <!-- <mat-label>Script file</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedFileName\"\r\n (selectionChange)=\"onFileSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let name of fileNamesByHost; trackBy: trackByFileName\"\r\n title=\"{{ name }}\"\r\n [value]=\"name\">\r\n {{ name }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-wrapper{margin:0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{padding:.25rem 0 .5rem}:host ::ng-deep .mat-select-trigger{display:block}:host ::ng-deep .mat-select-trigger .mat-select-arrow-wrapper{transform:none}.file-selection-bar{display:flex;gap:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$
|
|
2274
|
+
WxCCFileSelectionBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFileSelectionBarComponent, selector: "wxcc-file-selection-bar", inputs: { fileNames: "fileNames", selectedFileName: "selectedFileName", selectedHost: "selectedHost" }, outputs: { fileNameSelectionChange: "fileNameSelectionChange" }, ngImport: i0, template: "<div class=\"file-selection-bar\">\r\n <mat-form-field appearance=\"outline\" class=\"host-selection\" *ngIf=\"hosts?.length\">\r\n <!-- <mat-label>Host</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedHost\"\r\n (selectionChange)=\"onHostSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let host of hosts; trackBy: trackByHost\"\r\n title=\"{{ host }}\"\r\n [value]=\"host\">\r\n {{ host }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"file-selection\">\r\n <!-- <mat-label>Script file</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedFileName\"\r\n (selectionChange)=\"onFileSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let name of fileNamesByHost; trackBy: trackByFileName\"\r\n title=\"{{ name }}\"\r\n [value]=\"name\">\r\n {{ name }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-wrapper{margin:0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{padding:.25rem 0 .5rem}:host ::ng-deep .mat-select-trigger{display:block}:host ::ng-deep .mat-select-trigger .mat-select-arrow-wrapper{transform:none}.file-selection-bar{display:flex;gap:1rem}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "component", type: i3.MatOption, selector: "mat-option", exportAs: ["matOption"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2127
2275
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFileSelectionBarComponent, decorators: [{
|
|
2128
2276
|
type: Component,
|
|
2129
2277
|
args: [{ selector: 'wxcc-file-selection-bar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"file-selection-bar\">\r\n <mat-form-field appearance=\"outline\" class=\"host-selection\" *ngIf=\"hosts?.length\">\r\n <!-- <mat-label>Host</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedHost\"\r\n (selectionChange)=\"onHostSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let host of hosts; trackBy: trackByHost\"\r\n title=\"{{ host }}\"\r\n [value]=\"host\">\r\n {{ host }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"file-selection\">\r\n <!-- <mat-label>Script file</mat-label> -->\r\n <mat-select\r\n [value]=\"selectedFileName\"\r\n (selectionChange)=\"onFileSelectionChange($event.value)\">\r\n <mat-option\r\n *ngFor=\"let name of fileNamesByHost; trackBy: trackByFileName\"\r\n title=\"{{ name }}\"\r\n [value]=\"name\">\r\n {{ name }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n</div>", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-wrapper{margin:0}:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix{padding:.25rem 0 .5rem}:host ::ng-deep .mat-select-trigger{display:block}:host ::ng-deep .mat-select-trigger .mat-select-arrow-wrapper{transform:none}.file-selection-bar{display:flex;gap:1rem}\n"] }]
|
|
@@ -3251,7 +3399,7 @@ class WxCCFlowchartPageComponent {
|
|
|
3251
3399
|
}
|
|
3252
3400
|
}
|
|
3253
3401
|
WxCCFlowchartPageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartPageComponent, deps: [{ token: WxCCAPIService }, { token: WxCC2GraphService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3254
|
-
WxCCFlowchartPageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFlowchartPageComponent, selector: "cc-script-editor", inputs: { customerId: "customerId", host: "host", token: "token" }, ngImport: i0, template: "<div class=\"wxcc-flowchart-wrapper\">\r\n <header class=\"wxcc-flowchart-header\">\r\n <wxcc-file-selection-bar\r\n *ngIf=\"state.fileNames && state.fileNames.length\"\r\n [fileNames]=\"state.fileNames\"\r\n [selectedHost]=\"state.uccxIp\"\r\n [selectedFileName]=\"state.selectedFileName\"\r\n (fileNameSelectionChange)=\"onFileNameSelectionChange($event)\">\r\n </wxcc-file-selection-bar>\r\n <wxcc-actions-bar\r\n *ngIf=\"state.flowchart\"\r\n (save)=\"onSave()\"\r\n (reset)=\"onReset()\"\r\n (exportNonIr)=\"onExportNonIr()\"\r\n (complete)=\"onComplete()\">\r\n </wxcc-actions-bar>\r\n </header>\r\n <ng-container *ngIf=\"!state.loading; else loadingTemplate\">\r\n <wxcc-flowchart\r\n *ngIf=\"state.flowchart; else errorTemplate\"\r\n [flowchart]=\"state.flowchart\">\r\n </wxcc-flowchart>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-template #loadingTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n <mat-spinner diameter=\"40\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #errorTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n Error loading script\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block;width:100%;height:100%}.wxcc-flowchart-wrapper{width:100%;height:100%;display:flex;gap:.5rem;flex-direction:column}.wxcc-flowchart-wrapper .wxcc-flowchart-header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.wxcc-flowchart-wrapper .placeholder-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4
|
|
3402
|
+
WxCCFlowchartPageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WxCCFlowchartPageComponent, selector: "cc-script-editor", inputs: { customerId: "customerId", host: "host", token: "token" }, ngImport: i0, template: "<div class=\"wxcc-flowchart-wrapper\">\r\n <header class=\"wxcc-flowchart-header\">\r\n <wxcc-file-selection-bar\r\n *ngIf=\"state.fileNames && state.fileNames.length\"\r\n [fileNames]=\"state.fileNames\"\r\n [selectedHost]=\"state.uccxIp\"\r\n [selectedFileName]=\"state.selectedFileName\"\r\n (fileNameSelectionChange)=\"onFileNameSelectionChange($event)\">\r\n </wxcc-file-selection-bar>\r\n <wxcc-actions-bar\r\n *ngIf=\"state.flowchart\"\r\n (save)=\"onSave()\"\r\n (reset)=\"onReset()\"\r\n (exportNonIr)=\"onExportNonIr()\"\r\n (complete)=\"onComplete()\">\r\n </wxcc-actions-bar>\r\n </header>\r\n <ng-container *ngIf=\"!state.loading; else loadingTemplate\">\r\n <wxcc-flowchart\r\n *ngIf=\"state.flowchart; else errorTemplate\"\r\n [flowchart]=\"state.flowchart\">\r\n </wxcc-flowchart>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-template #loadingTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n <mat-spinner diameter=\"40\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #errorTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n Error loading script\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block;width:100%;height:100%}.wxcc-flowchart-wrapper{width:100%;height:100%;display:flex;gap:.5rem;flex-direction:column}.wxcc-flowchart-wrapper .wxcc-flowchart-header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.wxcc-flowchart-wrapper .placeholder-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: WxCCFlowchartComponent, selector: "wxcc-flowchart", inputs: ["flowchart"] }, { kind: "component", type: WxCCFileSelectionBarComponent, selector: "wxcc-file-selection-bar", inputs: ["fileNames", "selectedFileName", "selectedHost"], outputs: ["fileNameSelectionChange"] }, { kind: "component", type: WxCCActionsBarComponent, selector: "wxcc-actions-bar", outputs: ["save", "reset", "complete", "exportNonIr"] }] });
|
|
3255
3403
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WxCCFlowchartPageComponent, decorators: [{
|
|
3256
3404
|
type: Component,
|
|
3257
3405
|
args: [{ selector: 'cc-script-editor', template: "<div class=\"wxcc-flowchart-wrapper\">\r\n <header class=\"wxcc-flowchart-header\">\r\n <wxcc-file-selection-bar\r\n *ngIf=\"state.fileNames && state.fileNames.length\"\r\n [fileNames]=\"state.fileNames\"\r\n [selectedHost]=\"state.uccxIp\"\r\n [selectedFileName]=\"state.selectedFileName\"\r\n (fileNameSelectionChange)=\"onFileNameSelectionChange($event)\">\r\n </wxcc-file-selection-bar>\r\n <wxcc-actions-bar\r\n *ngIf=\"state.flowchart\"\r\n (save)=\"onSave()\"\r\n (reset)=\"onReset()\"\r\n (exportNonIr)=\"onExportNonIr()\"\r\n (complete)=\"onComplete()\">\r\n </wxcc-actions-bar>\r\n </header>\r\n <ng-container *ngIf=\"!state.loading; else loadingTemplate\">\r\n <wxcc-flowchart\r\n *ngIf=\"state.flowchart; else errorTemplate\"\r\n [flowchart]=\"state.flowchart\">\r\n </wxcc-flowchart>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-template #loadingTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n <mat-spinner diameter=\"40\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #errorTemplate>\r\n <div class=\"placeholder-wrapper\">\r\n Error loading script\r\n </div>\r\n</ng-template>\r\n", styles: [":host{display:block;width:100%;height:100%}.wxcc-flowchart-wrapper{width:100%;height:100%;display:flex;gap:.5rem;flex-direction:column}.wxcc-flowchart-wrapper .wxcc-flowchart-header{display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.wxcc-flowchart-wrapper .placeholder-wrapper{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
|
|
@@ -3263,101 +3411,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
3263
3411
|
type: Input
|
|
3264
3412
|
}] } });
|
|
3265
3413
|
|
|
3266
|
-
class MaterialModule {
|
|
3267
|
-
}
|
|
3268
|
-
MaterialModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3269
|
-
MaterialModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
|
|
3270
|
-
MatTooltipModule,
|
|
3271
|
-
MatTableModule,
|
|
3272
|
-
MatCheckboxModule,
|
|
3273
|
-
MatButtonModule,
|
|
3274
|
-
MatIconModule,
|
|
3275
|
-
MatFormFieldModule,
|
|
3276
|
-
MatInputModule,
|
|
3277
|
-
MatSelectModule], exports: [MatProgressBarModule,
|
|
3278
|
-
MatTooltipModule,
|
|
3279
|
-
MatTableModule,
|
|
3280
|
-
MatCheckboxModule,
|
|
3281
|
-
MatButtonModule,
|
|
3282
|
-
MatIconModule,
|
|
3283
|
-
MatFormFieldModule,
|
|
3284
|
-
MatInputModule,
|
|
3285
|
-
MatSelectModule,
|
|
3286
|
-
MatProgressSpinnerModule] });
|
|
3287
|
-
MaterialModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, imports: [MatProgressBarModule,
|
|
3288
|
-
MatTooltipModule,
|
|
3289
|
-
MatTableModule,
|
|
3290
|
-
MatCheckboxModule,
|
|
3291
|
-
MatButtonModule,
|
|
3292
|
-
MatIconModule,
|
|
3293
|
-
MatFormFieldModule,
|
|
3294
|
-
MatInputModule,
|
|
3295
|
-
MatSelectModule, MatProgressBarModule,
|
|
3296
|
-
MatTooltipModule,
|
|
3297
|
-
MatTableModule,
|
|
3298
|
-
MatCheckboxModule,
|
|
3299
|
-
MatButtonModule,
|
|
3300
|
-
MatIconModule,
|
|
3301
|
-
MatFormFieldModule,
|
|
3302
|
-
MatInputModule,
|
|
3303
|
-
MatSelectModule,
|
|
3304
|
-
MatProgressSpinnerModule] });
|
|
3305
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MaterialModule, decorators: [{
|
|
3306
|
-
type: NgModule,
|
|
3307
|
-
args: [{
|
|
3308
|
-
imports: [
|
|
3309
|
-
MatProgressBarModule,
|
|
3310
|
-
MatTooltipModule,
|
|
3311
|
-
MatTableModule,
|
|
3312
|
-
MatCheckboxModule,
|
|
3313
|
-
MatButtonModule,
|
|
3314
|
-
MatIconModule,
|
|
3315
|
-
MatFormFieldModule,
|
|
3316
|
-
MatInputModule,
|
|
3317
|
-
MatSelectModule
|
|
3318
|
-
],
|
|
3319
|
-
exports: [
|
|
3320
|
-
MatProgressBarModule,
|
|
3321
|
-
MatTooltipModule,
|
|
3322
|
-
MatTableModule,
|
|
3323
|
-
MatCheckboxModule,
|
|
3324
|
-
MatButtonModule,
|
|
3325
|
-
MatIconModule,
|
|
3326
|
-
MatFormFieldModule,
|
|
3327
|
-
MatInputModule,
|
|
3328
|
-
MatSelectModule,
|
|
3329
|
-
MatProgressSpinnerModule
|
|
3330
|
-
]
|
|
3331
|
-
}]
|
|
3332
|
-
}] });
|
|
3333
|
-
|
|
3334
|
-
class SharedModule {
|
|
3335
|
-
}
|
|
3336
|
-
SharedModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3337
|
-
SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, imports: [CommonModule,
|
|
3338
|
-
MaterialModule,
|
|
3339
|
-
NgApexchartsModule,
|
|
3340
|
-
HttpClientModule], exports: [MaterialModule] });
|
|
3341
|
-
SharedModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, imports: [CommonModule,
|
|
3342
|
-
MaterialModule,
|
|
3343
|
-
NgApexchartsModule,
|
|
3344
|
-
HttpClientModule, MaterialModule] });
|
|
3345
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SharedModule, decorators: [{
|
|
3346
|
-
type: NgModule,
|
|
3347
|
-
args: [{
|
|
3348
|
-
declarations: [],
|
|
3349
|
-
imports: [
|
|
3350
|
-
CommonModule,
|
|
3351
|
-
MaterialModule,
|
|
3352
|
-
NgApexchartsModule,
|
|
3353
|
-
HttpClientModule
|
|
3354
|
-
],
|
|
3355
|
-
exports: [
|
|
3356
|
-
MaterialModule
|
|
3357
|
-
]
|
|
3358
|
-
}]
|
|
3359
|
-
}] });
|
|
3360
|
-
|
|
3361
3414
|
class FloatingToolbarModule {
|
|
3362
3415
|
}
|
|
3363
3416
|
FloatingToolbarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FloatingToolbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -3444,9 +3497,827 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
|
|
|
3444
3497
|
}]
|
|
3445
3498
|
}] });
|
|
3446
3499
|
|
|
3500
|
+
/**
|
|
3501
|
+
* Same contract as {@link APIService}, pointed at the **dcp** host instead of the
|
|
3502
|
+
* main API host. A handful of UCCX endpoints (application names, file downloads,
|
|
3503
|
+
* dependency analysis) are only served there - webex-ops-client does the same thing
|
|
3504
|
+
* with its `ContactCenterService.customUrl`.
|
|
3505
|
+
*
|
|
3506
|
+
* Registered separately from `APIService` so each keeps its own `apiUrl`/`token`.
|
|
3507
|
+
*/
|
|
3508
|
+
class DcpApiService extends APIService {
|
|
3509
|
+
constructor() {
|
|
3510
|
+
super(...arguments);
|
|
3511
|
+
this.apiUrl = window.location.protocol + '//' + window.location.hostname + '/dcp';
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
DcpApiService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DcpApiService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
3515
|
+
DcpApiService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DcpApiService, providedIn: 'root' });
|
|
3516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DcpApiService, decorators: [{
|
|
3517
|
+
type: Injectable,
|
|
3518
|
+
args: [{
|
|
3519
|
+
providedIn: 'root'
|
|
3520
|
+
}]
|
|
3521
|
+
}] });
|
|
3522
|
+
|
|
3523
|
+
/**
|
|
3524
|
+
* The UCCX migration payloads as the backend returns them, mirroring
|
|
3525
|
+
* webex-ops-client's `pages/contact-center/interfaces/uccx-batch.interface.ts`.
|
|
3526
|
+
* Only the fields this widget reads are declared.
|
|
3527
|
+
*/
|
|
3528
|
+
/** The `type` values a {@link UccxItem} can carry. */
|
|
3529
|
+
const UCCX_ITEM_TYPE = {
|
|
3530
|
+
RESOURCE_GROUP: 'Resource Group',
|
|
3531
|
+
TRIGGER: 'Trigger',
|
|
3532
|
+
SCRIPT: 'Script',
|
|
3533
|
+
APPLICATION: 'Application',
|
|
3534
|
+
CSQ: 'CSQ',
|
|
3535
|
+
DOCUMENT: 'Document',
|
|
3536
|
+
PHONE_BOOK: 'Phone Book',
|
|
3537
|
+
PROMPT: 'Prompt',
|
|
3538
|
+
REASON_CODE: 'Reason Code',
|
|
3539
|
+
RESOURCE: 'Resource',
|
|
3540
|
+
SKILL: 'Skill',
|
|
3541
|
+
TEAM: 'Team',
|
|
3542
|
+
WRAP_UP_CODE: 'Wrap Up Code'
|
|
3543
|
+
};
|
|
3544
|
+
/** The only call-flow state that counts as imported. */
|
|
3545
|
+
const CALL_FLOW_MIGRATED = 'MIGRATED';
|
|
3546
|
+
|
|
3547
|
+
const CHART_COLORS = {
|
|
3548
|
+
customerAssist: '#177A5C',
|
|
3549
|
+
webexContactCenter: '#D0D0D0',
|
|
3550
|
+
requiresReview: '#1268E3'
|
|
3551
|
+
};
|
|
3552
|
+
/** Compatibility score thresholds, per the ticket's scoring table. */
|
|
3553
|
+
const COMPATIBILITY_THRESHOLDS = {
|
|
3554
|
+
/** 80-100 - migrates to Customer Assist with no functional loss. */
|
|
3555
|
+
migratable: 80,
|
|
3556
|
+
/** 60-79 - migrates to Customer Assist, minor unsupported steps dropped. */
|
|
3557
|
+
requiresReview: 60
|
|
3558
|
+
};
|
|
3559
|
+
/**
|
|
3560
|
+
* Slices of the panel's pie chart, in order: the recommended destination for every
|
|
3561
|
+
* contact center detected in the connected UCCX environment.
|
|
3562
|
+
*
|
|
3563
|
+
* The panel is slice-driven, so re-cutting the chart when the design changes means
|
|
3564
|
+
* editing this array - no component change.
|
|
3565
|
+
*/
|
|
3566
|
+
const IMPORT_PANEL_SLICES = [
|
|
3567
|
+
{
|
|
3568
|
+
label: 'To Customer Assist',
|
|
3569
|
+
color: CHART_COLORS.customerAssist,
|
|
3570
|
+
tooltip: 'Fully supported by Customer Assist.',
|
|
3571
|
+
match: contactCenter => contactCenter.compatibilityStatus === 'migratable'
|
|
3572
|
+
},
|
|
3573
|
+
{
|
|
3574
|
+
label: 'Requires Review',
|
|
3575
|
+
color: CHART_COLORS.requiresReview,
|
|
3576
|
+
tooltip: 'Supported by Customer Assist, but a few unsupported steps would change. '
|
|
3577
|
+
+ 'Can also go to Webex Contact Center for full feature coverage.',
|
|
3578
|
+
match: contactCenter => contactCenter.compatibilityStatus === 'requires-review'
|
|
3579
|
+
},
|
|
3580
|
+
{
|
|
3581
|
+
label: 'To Webex Contact Center',
|
|
3582
|
+
color: CHART_COLORS.webexContactCenter,
|
|
3583
|
+
tooltip: 'Not supported by Customer Assist - migrate to Webex Contact Center.',
|
|
3584
|
+
match: contactCenter => contactCenter.compatibilityStatus === 'unsupported'
|
|
3585
|
+
}
|
|
3586
|
+
];
|
|
3587
|
+
/**
|
|
3588
|
+
* How UCCX entity types roll up into the groups the Overview step shows, in display
|
|
3589
|
+
* order. Types not listed here get a group of their own under their raw type name,
|
|
3590
|
+
* so nothing the backend returns is silently dropped.
|
|
3591
|
+
*/
|
|
3592
|
+
const OVERVIEW_ENTITY_GROUPS = [
|
|
3593
|
+
{ label: 'Channel', types: [UCCX_ITEM_TYPE.TRIGGER] },
|
|
3594
|
+
{ label: 'Queues', types: [UCCX_ITEM_TYPE.CSQ] },
|
|
3595
|
+
{ label: 'Audio files', types: [UCCX_ITEM_TYPE.PROMPT, UCCX_ITEM_TYPE.DOCUMENT] },
|
|
3596
|
+
{ label: 'Flows', types: [UCCX_ITEM_TYPE.SCRIPT] },
|
|
3597
|
+
{ label: 'Skill', types: [UCCX_ITEM_TYPE.SKILL] },
|
|
3598
|
+
{ label: 'Contact center users', types: [UCCX_ITEM_TYPE.RESOURCE] }
|
|
3599
|
+
];
|
|
3600
|
+
const IMPORT_PANEL_TITLE = 'Import Contact center';
|
|
3601
|
+
const IMPORT_PANEL_TOOLTIP = 'Contact centers detected in the connected UCCX environment, and where each one can migrate to.';
|
|
3602
|
+
const IMPORT_WIZARD_TITLE = 'Contact Center';
|
|
3603
|
+
/** Shown once a "requires review" contact center is picked. Dismissible. */
|
|
3604
|
+
const CUSTOMER_ASSIST_NOTICE = 'This contact center may also be supported by Customer Assist. Check compatibility before continuing.';
|
|
3605
|
+
/** Tooltip on the marker the picker puts next to those same contact centers. */
|
|
3606
|
+
const CUSTOMER_ASSIST_MARKER_TOOLTIP = 'May also be supported by Customer Assist.';
|
|
3607
|
+
|
|
3608
|
+
/**
|
|
3609
|
+
* Stand-in data used when `CcImportService.useMockData` is on.
|
|
3610
|
+
*
|
|
3611
|
+
* Shapes here mirror exactly what `CcImportService` produces from the real backend,
|
|
3612
|
+
* so switching over is a matter of flipping `useMockData` to false.
|
|
3613
|
+
*/
|
|
3614
|
+
const APPLICATION_NAMES = [
|
|
3615
|
+
'Operations', 'Sales', 'Support', 'Billing', 'Reception', 'Helpdesk', 'Retention',
|
|
3616
|
+
'Onboarding', 'Escalations', 'Emergency', 'Pharmacy', 'Appointments', 'Claims',
|
|
3617
|
+
'Collections', 'Dispatch', 'Front Desk', 'IT Service Desk', 'Loyalty', 'Orders', 'Returns'
|
|
3618
|
+
];
|
|
3619
|
+
/** One tab per group on the wizard's Overview step, in the order they are shown. */
|
|
3620
|
+
const ENTITY_GROUP_TEMPLATE = [
|
|
3621
|
+
{ label: 'Channel', suffixes: ['_CC'] },
|
|
3622
|
+
{ label: 'Queues', suffixes: ['_Queue'] },
|
|
3623
|
+
{ label: 'Audio files', suffixes: [' Welcome', ' Music On Hold', ' Closed Message'] },
|
|
3624
|
+
{ label: 'Flows', suffixes: ['_Flow'] },
|
|
3625
|
+
{ label: 'Skill', suffixes: ['_Skill'] },
|
|
3626
|
+
{ label: 'Contact center users', suffixes: [' Supervisor', ' Agent 1', ' Agent 2'] }
|
|
3627
|
+
];
|
|
3628
|
+
/**
|
|
3629
|
+
* The ten contact centers that still need a decision - the only ones the wizard
|
|
3630
|
+
* offers, so these are exactly the rows the picker shows, in this order. The flagged
|
|
3631
|
+
* three are "requires review" and carry the marker plus the advisory notice.
|
|
3632
|
+
*/
|
|
3633
|
+
const REVIEW_CONTACT_CENTERS = [
|
|
3634
|
+
{ name: 'Operations', requiresReview: true },
|
|
3635
|
+
{ name: 'Sales_inquiry' },
|
|
3636
|
+
{ name: 'Tech Support' },
|
|
3637
|
+
{ name: 'Tech_Info' },
|
|
3638
|
+
{ name: 'Finance', requiresReview: true },
|
|
3639
|
+
{ name: 'Innovation', requiresReview: true },
|
|
3640
|
+
{ name: 'Marketing' },
|
|
3641
|
+
{ name: 'Gen_Support' },
|
|
3642
|
+
{ name: 'Legal' },
|
|
3643
|
+
{ name: 'Sales Support' }
|
|
3644
|
+
];
|
|
3645
|
+
/** 100 contact centers: 70 migratable, 20 unsupported, 10 still to be imported. */
|
|
3646
|
+
function mockContactCenters() {
|
|
3647
|
+
const contactCenters = [];
|
|
3648
|
+
// 90 already-imported ones, split across the two destinations.
|
|
3649
|
+
for (let i = 0; i < 90; i++) {
|
|
3650
|
+
const name = `${APPLICATION_NAMES[i % APPLICATION_NAMES.length]}_${Math.floor(i / APPLICATION_NAMES.length) + 1}`;
|
|
3651
|
+
const compatibilityStatus = i < 70 ? 'migratable' : 'unsupported';
|
|
3652
|
+
contactCenters.push({
|
|
3653
|
+
applicationId: `app-${i + 1}`,
|
|
3654
|
+
applicationName: name,
|
|
3655
|
+
scriptName: `${name}_AA_Queue.aef`,
|
|
3656
|
+
compatibilityStatus,
|
|
3657
|
+
compatibilityScore: compatibilityStatus === 'migratable' ? 92 : 41,
|
|
3658
|
+
migrationState: 'migrated'
|
|
3659
|
+
});
|
|
3660
|
+
}
|
|
3661
|
+
REVIEW_CONTACT_CENTERS.forEach((contactCenter, i) => {
|
|
3662
|
+
const compatibilityStatus = contactCenter.requiresReview ? 'requires-review' : 'unsupported';
|
|
3663
|
+
contactCenters.push({
|
|
3664
|
+
applicationId: `app-${91 + i}`,
|
|
3665
|
+
applicationName: contactCenter.name,
|
|
3666
|
+
scriptName: `${contactCenter.name}_AA_Queue.aef`,
|
|
3667
|
+
compatibilityStatus,
|
|
3668
|
+
compatibilityScore: contactCenter.requiresReview ? 68 : 44,
|
|
3669
|
+
migrationState: 'not-migrated',
|
|
3670
|
+
customerAssistCapable: compatibilityStatus === 'requires-review'
|
|
3671
|
+
});
|
|
3672
|
+
});
|
|
3673
|
+
return contactCenters;
|
|
3674
|
+
}
|
|
3675
|
+
function mockContactCenterEntities(contactCenter) {
|
|
3676
|
+
const base = contactCenter.applicationName;
|
|
3677
|
+
return {
|
|
3678
|
+
applicationId: contactCenter.applicationId,
|
|
3679
|
+
groups: ENTITY_GROUP_TEMPLATE.map(group => ({
|
|
3680
|
+
label: group.label,
|
|
3681
|
+
items: group.suffixes.map(suffix => `${base}${suffix}`)
|
|
3682
|
+
}))
|
|
3683
|
+
};
|
|
3684
|
+
}
|
|
3685
|
+
|
|
3686
|
+
/** Simulated network latency for the mock responses, so loading states are exercised. */
|
|
3687
|
+
const MOCK_LATENCY_MS = 300;
|
|
3688
|
+
class CcImportService {
|
|
3689
|
+
constructor() {
|
|
3690
|
+
this.api = inject(APIService);
|
|
3691
|
+
this.dcpApi = inject(DcpApiService);
|
|
3692
|
+
/**
|
|
3693
|
+
* Answer everything from `mock/cc-import.mock.ts` instead of calling the backend.
|
|
3694
|
+
*
|
|
3695
|
+
* Note this is all-or-nothing: with it off, the contact-center list, the entity
|
|
3696
|
+
* overview and the import all hit real endpoints. Compatibility scoring is the
|
|
3697
|
+
* exception - see {@link resolveCompatibility}.
|
|
3698
|
+
*/
|
|
3699
|
+
this.useMockData = true;
|
|
3700
|
+
}
|
|
3701
|
+
setToken(token) {
|
|
3702
|
+
this.api.token = token;
|
|
3703
|
+
this.dcpApi.token = token;
|
|
3704
|
+
}
|
|
3705
|
+
setHost(host) {
|
|
3706
|
+
this.api.apiUrl = host;
|
|
3707
|
+
}
|
|
3708
|
+
/** Base URL of the dcp host, which serves the UCCX application list. */
|
|
3709
|
+
setDcpHost(dcpHost) {
|
|
3710
|
+
this.dcpApi.apiUrl = dcpHost;
|
|
3711
|
+
}
|
|
3712
|
+
/**
|
|
3713
|
+
* Every UCCX contact center Tuki can import.
|
|
3714
|
+
*
|
|
3715
|
+
* A "contact center" is a UCCX application. The list comes from the dcp
|
|
3716
|
+
* application cache; whether each one has already been imported is joined on from
|
|
3717
|
+
* the per-AEF-script call-flow migration states.
|
|
3718
|
+
*/
|
|
3719
|
+
fetchContactCenters(customerId) {
|
|
3720
|
+
if (this.useMockData) {
|
|
3721
|
+
return of(mockContactCenters()).pipe(delay(MOCK_LATENCY_MS));
|
|
3722
|
+
}
|
|
3723
|
+
return forkJoin({
|
|
3724
|
+
applications: this.dcpApi.fetch(API.UCCX.APPLICATION_NAMES(customerId)),
|
|
3725
|
+
callFlows: this.api.fetch(API.UCCX.CALL_FLOW_MIGRATION_STATUSES(customerId))
|
|
3726
|
+
}).pipe(map(({ applications, callFlows }) => this.toContactCenters(this.asArray(applications), this.asArray(callFlows))));
|
|
3727
|
+
}
|
|
3728
|
+
/**
|
|
3729
|
+
* Application-centric entity breakdown: everything Tuki will create on import.
|
|
3730
|
+
*
|
|
3731
|
+
* Note this only ever returns entities the backend has actually linked to the
|
|
3732
|
+
* application. Where that linkage is missing the groups come back empty rather
|
|
3733
|
+
* than padded with unrelated entities of the right type.
|
|
3734
|
+
*/
|
|
3735
|
+
fetchContactCenterEntities(customerId, contactCenter) {
|
|
3736
|
+
if (this.useMockData) {
|
|
3737
|
+
return of(mockContactCenterEntities(contactCenter)).pipe(delay(MOCK_LATENCY_MS));
|
|
3738
|
+
}
|
|
3739
|
+
return this.fetchApplicationItems(customerId, contactCenter.applicationName).pipe(map(items => ({
|
|
3740
|
+
applicationId: contactCenter.applicationId,
|
|
3741
|
+
groups: this.groupEntities(items)
|
|
3742
|
+
})));
|
|
3743
|
+
}
|
|
3744
|
+
/**
|
|
3745
|
+
* Kicks off the UCCX -> Webex Contact Center import of one contact center, as a
|
|
3746
|
+
* single migration unit: every entity of the application goes in one request.
|
|
3747
|
+
*
|
|
3748
|
+
* The endpoint is synchronous and answers with an XLSX tracker rather than a job
|
|
3749
|
+
* id - execution and progress tracking are defined in a separate ticket.
|
|
3750
|
+
*
|
|
3751
|
+
* @param siteId required by the backend when a Resource Group is in scope.
|
|
3752
|
+
* @param locationId required by the backend when a Trigger is in scope.
|
|
3753
|
+
*/
|
|
3754
|
+
importContactCenter(customerId, applicationId, siteId, locationId) {
|
|
3755
|
+
if (this.useMockData) {
|
|
3756
|
+
return of({ applicationId, accepted: true }).pipe(delay(MOCK_LATENCY_MS));
|
|
3757
|
+
}
|
|
3758
|
+
return this.fetchApplicationItems(customerId, applicationId).pipe(switchMap(items => {
|
|
3759
|
+
const payload = {
|
|
3760
|
+
uccxItemsList: items.length ? [items.map(item => (Object.assign(Object.assign({}, item), { migrate: true })))] : []
|
|
3761
|
+
};
|
|
3762
|
+
return this.api.post(API.UCCX.MIGRATE(customerId), payload, { siteId, locationId }, { responseType: 'blob' });
|
|
3763
|
+
}), map((report) => ({
|
|
3764
|
+
applicationId,
|
|
3765
|
+
accepted: true,
|
|
3766
|
+
report: report instanceof Blob ? report : undefined
|
|
3767
|
+
})));
|
|
3768
|
+
}
|
|
3769
|
+
/**
|
|
3770
|
+
* Every UCCX entity belonging to one application, gathered across the batches.
|
|
3771
|
+
*
|
|
3772
|
+
* UCCX batches hold one entity type each, so this reads them all and keeps the
|
|
3773
|
+
* items whose `applicationName` matches. The narrowing is done here rather than
|
|
3774
|
+
* through the endpoint's own `applicationName` param because that param answers
|
|
3775
|
+
* `[]` on dev2 even for items that plainly carry the name.
|
|
3776
|
+
*/
|
|
3777
|
+
fetchApplicationItems(customerId, applicationName) {
|
|
3778
|
+
return this.api.fetch(API.UCCX.BATCHES(customerId)).pipe(switchMap(response => {
|
|
3779
|
+
const batches = this.asArray(response);
|
|
3780
|
+
if (!batches.length) {
|
|
3781
|
+
return of([]);
|
|
3782
|
+
}
|
|
3783
|
+
return forkJoin(batches.map(batch => this.api.fetch(API.UCCX.BATCH_ITEMS(customerId, batch.id))
|
|
3784
|
+
.pipe(map((wrapper) => this.flattenItems(wrapper))))).pipe(map(perBatch => this.dedupeItems(perBatch.flat().filter(item => item.applicationName === applicationName))));
|
|
3785
|
+
}));
|
|
3786
|
+
}
|
|
3787
|
+
/** The items endpoint nests items one level; older responses come back flat. */
|
|
3788
|
+
flattenItems(wrapper) {
|
|
3789
|
+
var _a;
|
|
3790
|
+
const items = (_a = wrapper === null || wrapper === void 0 ? void 0 : wrapper.uccxItemsList) !== null && _a !== void 0 ? _a : [];
|
|
3791
|
+
const flattened = Array.isArray(items[0])
|
|
3792
|
+
? items.flat()
|
|
3793
|
+
: items;
|
|
3794
|
+
return flattened.filter(Boolean);
|
|
3795
|
+
}
|
|
3796
|
+
/** The same entity can be carried by more than one batch. */
|
|
3797
|
+
dedupeItems(items) {
|
|
3798
|
+
const seen = new Set();
|
|
3799
|
+
return items.filter(item => {
|
|
3800
|
+
const key = `${item.type}::${item.name}::${item.sourceUCCXIp}`;
|
|
3801
|
+
if (seen.has(key)) {
|
|
3802
|
+
return false;
|
|
3803
|
+
}
|
|
3804
|
+
seen.add(key);
|
|
3805
|
+
return true;
|
|
3806
|
+
});
|
|
3807
|
+
}
|
|
3808
|
+
groupEntities(items) {
|
|
3809
|
+
const remaining = new Map();
|
|
3810
|
+
items.forEach(item => {
|
|
3811
|
+
var _a;
|
|
3812
|
+
const names = (_a = remaining.get(item.type)) !== null && _a !== void 0 ? _a : [];
|
|
3813
|
+
names.push(item.name);
|
|
3814
|
+
remaining.set(item.type, names);
|
|
3815
|
+
});
|
|
3816
|
+
const groups = OVERVIEW_ENTITY_GROUPS.map(group => {
|
|
3817
|
+
const collected = [];
|
|
3818
|
+
group.types.forEach(type => {
|
|
3819
|
+
var _a;
|
|
3820
|
+
collected.push(...((_a = remaining.get(type)) !== null && _a !== void 0 ? _a : []));
|
|
3821
|
+
remaining.delete(type);
|
|
3822
|
+
});
|
|
3823
|
+
return { label: group.label, items: collected };
|
|
3824
|
+
});
|
|
3825
|
+
// Anything the backend returned that has no group of its own keeps its raw
|
|
3826
|
+
// type as a label, rather than being dropped from the overview.
|
|
3827
|
+
remaining.forEach((names, type) => groups.push({ label: type, items: names }));
|
|
3828
|
+
return groups;
|
|
3829
|
+
}
|
|
3830
|
+
toContactCenters(applications, callFlows) {
|
|
3831
|
+
return applications
|
|
3832
|
+
.filter(application => !!(application === null || application === void 0 ? void 0 : application.name))
|
|
3833
|
+
.map(application => {
|
|
3834
|
+
var _a;
|
|
3835
|
+
const uccxIp = (_a = application.uccx) === null || _a === void 0 ? void 0 : _a.host;
|
|
3836
|
+
const scriptName = this.toScriptName(application);
|
|
3837
|
+
const compatibilityStatus = this.resolveCompatibility(application);
|
|
3838
|
+
const contactCenter = {
|
|
3839
|
+
// UCCX identifies an application by name - it is what the entity
|
|
3840
|
+
// records link back to - so it doubles as the widget's key.
|
|
3841
|
+
applicationId: application.name,
|
|
3842
|
+
applicationName: application.name,
|
|
3843
|
+
scriptName,
|
|
3844
|
+
uccxIp,
|
|
3845
|
+
compatibilityStatus,
|
|
3846
|
+
migrationState: this.resolveMigrationState(application, scriptName, uccxIp, callFlows),
|
|
3847
|
+
// Per the ticket, "requires review" is exactly the set that can go
|
|
3848
|
+
// to either destination.
|
|
3849
|
+
customerAssistCapable: compatibilityStatus === 'requires-review'
|
|
3850
|
+
};
|
|
3851
|
+
return contactCenter;
|
|
3852
|
+
});
|
|
3853
|
+
}
|
|
3854
|
+
/** UCCX wraps the backing script as `SCRIPT[Foo.aef]`; the widget shows `Foo.aef`. */
|
|
3855
|
+
toScriptName(application) {
|
|
3856
|
+
var _a, _b, _c;
|
|
3857
|
+
const raw = (_c = (_a = application.scriptName) !== null && _a !== void 0 ? _a : (_b = application.aefFiles) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : '';
|
|
3858
|
+
return raw.replace(/^SCRIPT\[(.*)\]$/, '$1');
|
|
3859
|
+
}
|
|
3860
|
+
/**
|
|
3861
|
+
* Whether Tuki has already imported this contact center.
|
|
3862
|
+
*
|
|
3863
|
+
* The application record carries its own `migrationStatus`, but it is null
|
|
3864
|
+
* throughout dev2, so this falls back to the per-AEF-script call-flow state.
|
|
3865
|
+
*/
|
|
3866
|
+
resolveMigrationState(application, scriptName, uccxIp, callFlows) {
|
|
3867
|
+
if (application.migrationStatus) {
|
|
3868
|
+
return application.migrationStatus === CALL_FLOW_MIGRATED ? 'migrated' : 'not-migrated';
|
|
3869
|
+
}
|
|
3870
|
+
const callFlow = callFlows.find(flow => flow.scriptName === scriptName && (!uccxIp || flow.uccxIp === uccxIp));
|
|
3871
|
+
return (callFlow === null || callFlow === void 0 ? void 0 : callFlow.status) === CALL_FLOW_MIGRATED ? 'migrated' : 'not-migrated';
|
|
3872
|
+
}
|
|
3873
|
+
/**
|
|
3874
|
+
* Turns an AEF compatibility score into a status.
|
|
3875
|
+
*
|
|
3876
|
+
* The scoring API does not exist yet - the AEF step mapping is still a pending
|
|
3877
|
+
* input on the ticket - so when the backend sends no score every contact center
|
|
3878
|
+
* falls back to "requires review": the status that offers both destinations and
|
|
3879
|
+
* claims nothing about compatibility we have not actually measured.
|
|
3880
|
+
*
|
|
3881
|
+
* Once the backend returns `compatibilityScore`, the thresholds below take over
|
|
3882
|
+
* with no further change here.
|
|
3883
|
+
*/
|
|
3884
|
+
resolveCompatibility(application) {
|
|
3885
|
+
const score = application.compatibilityScore;
|
|
3886
|
+
if (typeof score !== 'number') {
|
|
3887
|
+
return 'requires-review';
|
|
3888
|
+
}
|
|
3889
|
+
if (score >= COMPATIBILITY_THRESHOLDS.migratable) {
|
|
3890
|
+
return 'migratable';
|
|
3891
|
+
}
|
|
3892
|
+
if (score >= COMPATIBILITY_THRESHOLDS.requiresReview) {
|
|
3893
|
+
return 'requires-review';
|
|
3894
|
+
}
|
|
3895
|
+
return 'unsupported';
|
|
3896
|
+
}
|
|
3897
|
+
asArray(value) {
|
|
3898
|
+
return Array.isArray(value) ? value : [];
|
|
3899
|
+
}
|
|
3900
|
+
}
|
|
3901
|
+
CcImportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3902
|
+
CcImportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportService, providedIn: 'root' });
|
|
3903
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportService, decorators: [{
|
|
3904
|
+
type: Injectable,
|
|
3905
|
+
args: [{
|
|
3906
|
+
providedIn: 'root'
|
|
3907
|
+
}]
|
|
3908
|
+
}] });
|
|
3909
|
+
|
|
3910
|
+
/**
|
|
3911
|
+
* "Import Contact center" panel: how many UCCX contact centers were detected, how many
|
|
3912
|
+
* have been imported, and an Import button that asks the host to open the import wizard.
|
|
3913
|
+
*/
|
|
3914
|
+
class ImportContactCenterPanelComponent {
|
|
3915
|
+
constructor() {
|
|
3916
|
+
/** Serve mock data instead of calling the UCCX migration API. */
|
|
3917
|
+
this.useMockData = true;
|
|
3918
|
+
/**
|
|
3919
|
+
* Asked for the import wizard, carrying the contact centers already loaded here so
|
|
3920
|
+
* the wizard opens without refetching them. The host renders
|
|
3921
|
+
* `cc-import-contact-center-wizard` as a page in response.
|
|
3922
|
+
*/
|
|
3923
|
+
this.importRequested = new EventEmitter();
|
|
3924
|
+
this.ccImportService = inject(CcImportService);
|
|
3925
|
+
this.title = IMPORT_PANEL_TITLE;
|
|
3926
|
+
this.tooltip = IMPORT_PANEL_TOOLTIP;
|
|
3927
|
+
this.segments = [];
|
|
3928
|
+
this.total = 0;
|
|
3929
|
+
this.loading = false;
|
|
3930
|
+
this.error = false;
|
|
3931
|
+
this.contactCenters = [];
|
|
3932
|
+
}
|
|
3933
|
+
ngOnInit() {
|
|
3934
|
+
// Render an empty donut up front so the template never reads unset chart options,
|
|
3935
|
+
// including when load() bails out because the widget has no credentials yet.
|
|
3936
|
+
this.buildViewModel();
|
|
3937
|
+
this.load();
|
|
3938
|
+
}
|
|
3939
|
+
ngOnChanges(changes) {
|
|
3940
|
+
const reloadTriggers = ['customerId', 'host', 'dcpHost', 'token', 'useMockData'];
|
|
3941
|
+
if (reloadTriggers.some(input => changes[input] && !changes[input].firstChange)) {
|
|
3942
|
+
this.load();
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
ngOnDestroy() {
|
|
3946
|
+
var _a;
|
|
3947
|
+
(_a = this.subscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
3948
|
+
}
|
|
3949
|
+
onImport() {
|
|
3950
|
+
this.importRequested.emit(this.contactCenters);
|
|
3951
|
+
}
|
|
3952
|
+
/** Call after an import has run so the donut picks up the new counts. */
|
|
3953
|
+
refresh() {
|
|
3954
|
+
this.load();
|
|
3955
|
+
}
|
|
3956
|
+
load() {
|
|
3957
|
+
var _a;
|
|
3958
|
+
const customerId = Number(this.customerId);
|
|
3959
|
+
this.ccImportService.useMockData = this.useMockData;
|
|
3960
|
+
if (!this.useMockData && (!customerId || !this.token)) {
|
|
3961
|
+
return;
|
|
3962
|
+
}
|
|
3963
|
+
if (this.host) {
|
|
3964
|
+
this.ccImportService.setHost(this.host);
|
|
3965
|
+
}
|
|
3966
|
+
if (this.dcpHost) {
|
|
3967
|
+
this.ccImportService.setDcpHost(this.dcpHost);
|
|
3968
|
+
}
|
|
3969
|
+
if (this.token) {
|
|
3970
|
+
this.ccImportService.setToken(this.token);
|
|
3971
|
+
}
|
|
3972
|
+
(_a = this.subscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
3973
|
+
this.loading = true;
|
|
3974
|
+
this.error = false;
|
|
3975
|
+
this.subscription = this.ccImportService.fetchContactCenters(customerId)
|
|
3976
|
+
.pipe(catchError(error => {
|
|
3977
|
+
console.error('Unable to load the contact centers', error);
|
|
3978
|
+
this.error = true;
|
|
3979
|
+
return of([]);
|
|
3980
|
+
}), finalize(() => this.loading = false))
|
|
3981
|
+
.subscribe(contactCenters => {
|
|
3982
|
+
this.contactCenters = contactCenters;
|
|
3983
|
+
this.buildViewModel();
|
|
3984
|
+
});
|
|
3985
|
+
}
|
|
3986
|
+
buildViewModel() {
|
|
3987
|
+
this.total = this.contactCenters.length;
|
|
3988
|
+
this.segments = IMPORT_PANEL_SLICES.map(slice => {
|
|
3989
|
+
const count = this.contactCenters.filter(slice.match).length;
|
|
3990
|
+
return {
|
|
3991
|
+
label: slice.label,
|
|
3992
|
+
color: slice.color,
|
|
3993
|
+
tooltip: slice.tooltip,
|
|
3994
|
+
count,
|
|
3995
|
+
percentage: this.total > 0 ? Math.round((count / this.total) * 100) : 0
|
|
3996
|
+
};
|
|
3997
|
+
});
|
|
3998
|
+
this.chartOptions = this.buildChartOptions();
|
|
3999
|
+
}
|
|
4000
|
+
buildChartOptions() {
|
|
4001
|
+
const charted = this.segments.filter(segment => segment.count > 0);
|
|
4002
|
+
const isEmpty = charted.length === 0;
|
|
4003
|
+
return {
|
|
4004
|
+
series: isEmpty ? [1] : charted.map(segment => segment.count),
|
|
4005
|
+
labels: isEmpty ? ['No contact centers'] : charted.map(segment => segment.label),
|
|
4006
|
+
colors: isEmpty ? [CHART_COLORS.webexContactCenter] : charted.map(segment => segment.color),
|
|
4007
|
+
chart: {
|
|
4008
|
+
type: 'donut',
|
|
4009
|
+
height: 150,
|
|
4010
|
+
width: 150,
|
|
4011
|
+
sparkline: { enabled: true }
|
|
4012
|
+
},
|
|
4013
|
+
legend: { show: false },
|
|
4014
|
+
plotOptions: {
|
|
4015
|
+
pie: {
|
|
4016
|
+
expandOnClick: false,
|
|
4017
|
+
donut: { size: '72%' }
|
|
4018
|
+
}
|
|
4019
|
+
},
|
|
4020
|
+
dataLabels: { enabled: false },
|
|
4021
|
+
tooltip: { enabled: !isEmpty },
|
|
4022
|
+
states: {
|
|
4023
|
+
active: { filter: { type: 'none', value: 0 } }
|
|
4024
|
+
}
|
|
4025
|
+
};
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
ImportContactCenterPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImportContactCenterPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4029
|
+
ImportContactCenterPanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ImportContactCenterPanelComponent, selector: "cc-import-contact-center-panel", inputs: { customerId: "customerId", host: "host", dcpHost: "dcpHost", token: "token", useMockData: "useMockData" }, outputs: { importRequested: "importRequested" }, usesOnChanges: true, ngImport: i0, template: "<tk-card [title]=\"title\" [dense]=\"true\">\r\n <ng-container ngProjectAs=\"card-title-adornment\">\r\n <span class=\"cc-import-panel__info\" [matTooltip]=\"tooltip\">\r\n <ng-container *ngTemplateOutlet=\"infoIcon\"></ng-container>\r\n </span>\r\n </ng-container>\r\n\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"cc-import-panel__body\" *ngIf=\"!loading && !error; else panelState\">\r\n <div class=\"cc-import-panel__chart\">\r\n <apx-chart\r\n [series]=\"chartOptions.series\"\r\n [chart]=\"chartOptions.chart\"\r\n [labels]=\"chartOptions.labels\"\r\n [colors]=\"chartOptions.colors\"\r\n [legend]=\"chartOptions.legend\"\r\n [plotOptions]=\"chartOptions.plotOptions\"\r\n [dataLabels]=\"chartOptions.dataLabels\"\r\n [tooltip]=\"chartOptions.tooltip\"\r\n [states]=\"chartOptions.states\"\r\n ></apx-chart>\r\n <div class=\"cc-import-panel__chart-center\">\r\n <span class=\"cc-import-panel__chart-total\">{{ total | number }}</span>\r\n <span class=\"cc-import-panel__chart-caption\">Contact Center</span>\r\n </div>\r\n </div>\r\n\r\n <ul class=\"cc-import-panel__legend\">\r\n <li class=\"cc-import-panel__legend-item\" *ngFor=\"let segment of segments\">\r\n <span class=\"cc-import-panel__legend-marker\" [style.backgroundColor]=\"segment.color\"></span>\r\n <span class=\"cc-import-panel__legend-label\">{{ segment.label }}</span>\r\n <span class=\"cc-import-panel__info\" [matTooltip]=\"segment.tooltip\">\r\n <ng-container *ngTemplateOutlet=\"infoIcon\"></ng-container>\r\n </span>\r\n <span class=\"cc-import-panel__legend-value\">{{ segment.count | number }} ({{ segment.percentage }}%)</span>\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <ng-template #panelState>\r\n <div class=\"cc-import-panel__state\" *ngIf=\"loading\">Loading contact centers\u2026</div>\r\n <div class=\"cc-import-panel__state cc-import-panel__state--error\" *ngIf=\"!loading && error\">\r\n Unable to load contact centers.\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"cc-import-panel__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"cc-import-panel__button\"\r\n [disabled]=\"loading || error\"\r\n (click)=\"onImport()\"\r\n >\r\n Import\r\n </button>\r\n </div>\r\n </ng-container>\r\n</tk-card>\r\n\r\n<ng-template #infoIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\r\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" stroke-width=\"1.2\" />\r\n <path d=\"M8 7.2v4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"5\" r=\"0.85\" fill=\"currentColor\" />\r\n </svg>\r\n</ng-template>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;box-sizing:border-box;font-family:Inter,Inter,sans-serif}.cc-import-panel__info{display:inline-flex;align-items:center;color:#636363;cursor:help}.cc-import-panel__body{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap;width:100%}.cc-import-panel__chart{position:relative;width:150px;height:150px;flex-shrink:0}.cc-import-panel__chart-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.cc-import-panel__chart-total{font-size:1.625rem;line-height:1.1;color:#252525}.cc-import-panel__chart-caption{font-size:.6875rem;color:#636363}.cc-import-panel__legend{display:flex;flex-direction:column;gap:.625rem;margin:0;padding:0;list-style:none;min-width:17.5rem;flex:1}.cc-import-panel__legend-item{display:flex;align-items:center;gap:.5rem;font-size:.75rem;color:#636363}.cc-import-panel__legend-marker{width:10px;height:10px;border-radius:2px;flex-shrink:0}.cc-import-panel__legend-label{color:#252525}.cc-import-panel__legend-value{margin-left:auto;white-space:nowrap}.cc-import-panel__state{font-size:.875rem;color:#636363}.cc-import-panel__state--error{color:#bc1e1b}.cc-import-panel__actions{display:flex;margin-top:auto}.cc-import-panel__button{display:inline-flex;align-items:center;gap:.25rem;padding:.5rem 1rem;background:#fff;border:1px solid rgba(0,0,0,.5019607843);border-radius:6.25rem;font-family:inherit;font-size:.875rem;font-weight:500;color:#000000f2;cursor:pointer;white-space:nowrap}.cc-import-panel__button:hover:not(:disabled){background:#ededed}.cc-import-panel__button:disabled{color:#babcc5;border-color:#dfe3e7;cursor:not-allowed}@media (max-width: 560px){.cc-import-panel__legend{min-width:0}}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i5.ChartComponent, selector: "apx-chart", inputs: ["chart", "annotations", "colors", "dataLabels", "series", "stroke", "labels", "legend", "markers", "noData", "fill", "tooltip", "plotOptions", "responsive", "xaxis", "yaxis", "forecastDataPoints", "grid", "states", "title", "subtitle", "theme", "autoUpdateSeries"] }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: CardComponent, selector: "tk-card", inputs: ["title", "dense"] }, { kind: "pipe", type: i1$1.DecimalPipe, name: "number" }] });
|
|
4030
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImportContactCenterPanelComponent, decorators: [{
|
|
4031
|
+
type: Component,
|
|
4032
|
+
args: [{ selector: 'cc-import-contact-center-panel', template: "<tk-card [title]=\"title\" [dense]=\"true\">\r\n <ng-container ngProjectAs=\"card-title-adornment\">\r\n <span class=\"cc-import-panel__info\" [matTooltip]=\"tooltip\">\r\n <ng-container *ngTemplateOutlet=\"infoIcon\"></ng-container>\r\n </span>\r\n </ng-container>\r\n\r\n <ng-container ngProjectAs=\"card-content\">\r\n <div class=\"cc-import-panel__body\" *ngIf=\"!loading && !error; else panelState\">\r\n <div class=\"cc-import-panel__chart\">\r\n <apx-chart\r\n [series]=\"chartOptions.series\"\r\n [chart]=\"chartOptions.chart\"\r\n [labels]=\"chartOptions.labels\"\r\n [colors]=\"chartOptions.colors\"\r\n [legend]=\"chartOptions.legend\"\r\n [plotOptions]=\"chartOptions.plotOptions\"\r\n [dataLabels]=\"chartOptions.dataLabels\"\r\n [tooltip]=\"chartOptions.tooltip\"\r\n [states]=\"chartOptions.states\"\r\n ></apx-chart>\r\n <div class=\"cc-import-panel__chart-center\">\r\n <span class=\"cc-import-panel__chart-total\">{{ total | number }}</span>\r\n <span class=\"cc-import-panel__chart-caption\">Contact Center</span>\r\n </div>\r\n </div>\r\n\r\n <ul class=\"cc-import-panel__legend\">\r\n <li class=\"cc-import-panel__legend-item\" *ngFor=\"let segment of segments\">\r\n <span class=\"cc-import-panel__legend-marker\" [style.backgroundColor]=\"segment.color\"></span>\r\n <span class=\"cc-import-panel__legend-label\">{{ segment.label }}</span>\r\n <span class=\"cc-import-panel__info\" [matTooltip]=\"segment.tooltip\">\r\n <ng-container *ngTemplateOutlet=\"infoIcon\"></ng-container>\r\n </span>\r\n <span class=\"cc-import-panel__legend-value\">{{ segment.count | number }} ({{ segment.percentage }}%)</span>\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <ng-template #panelState>\r\n <div class=\"cc-import-panel__state\" *ngIf=\"loading\">Loading contact centers\u2026</div>\r\n <div class=\"cc-import-panel__state cc-import-panel__state--error\" *ngIf=\"!loading && error\">\r\n Unable to load contact centers.\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"cc-import-panel__actions\">\r\n <button\r\n type=\"button\"\r\n class=\"cc-import-panel__button\"\r\n [disabled]=\"loading || error\"\r\n (click)=\"onImport()\"\r\n >\r\n Import\r\n </button>\r\n </div>\r\n </ng-container>\r\n</tk-card>\r\n\r\n<ng-template #infoIcon>\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\r\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" stroke-width=\"1.2\" />\r\n <path d=\"M8 7.2v4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"5\" r=\"0.85\" fill=\"currentColor\" />\r\n </svg>\r\n</ng-template>\r\n", styles: ["@import\"https://fonts.googleapis.com/css?family=Poppins:400,100,200,300,500,600,800,700,900\";@import\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap\";:host{display:block;box-sizing:border-box;font-family:Inter,Inter,sans-serif}.cc-import-panel__info{display:inline-flex;align-items:center;color:#636363;cursor:help}.cc-import-panel__body{display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap;width:100%}.cc-import-panel__chart{position:relative;width:150px;height:150px;flex-shrink:0}.cc-import-panel__chart-center{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none}.cc-import-panel__chart-total{font-size:1.625rem;line-height:1.1;color:#252525}.cc-import-panel__chart-caption{font-size:.6875rem;color:#636363}.cc-import-panel__legend{display:flex;flex-direction:column;gap:.625rem;margin:0;padding:0;list-style:none;min-width:17.5rem;flex:1}.cc-import-panel__legend-item{display:flex;align-items:center;gap:.5rem;font-size:.75rem;color:#636363}.cc-import-panel__legend-marker{width:10px;height:10px;border-radius:2px;flex-shrink:0}.cc-import-panel__legend-label{color:#252525}.cc-import-panel__legend-value{margin-left:auto;white-space:nowrap}.cc-import-panel__state{font-size:.875rem;color:#636363}.cc-import-panel__state--error{color:#bc1e1b}.cc-import-panel__actions{display:flex;margin-top:auto}.cc-import-panel__button{display:inline-flex;align-items:center;gap:.25rem;padding:.5rem 1rem;background:#fff;border:1px solid rgba(0,0,0,.5019607843);border-radius:6.25rem;font-family:inherit;font-size:.875rem;font-weight:500;color:#000000f2;cursor:pointer;white-space:nowrap}.cc-import-panel__button:hover:not(:disabled){background:#ededed}.cc-import-panel__button:disabled{color:#babcc5;border-color:#dfe3e7;cursor:not-allowed}@media (max-width: 560px){.cc-import-panel__legend{min-width:0}}\n"] }]
|
|
4033
|
+
}], propDecorators: { customerId: [{
|
|
4034
|
+
type: Input
|
|
4035
|
+
}], host: [{
|
|
4036
|
+
type: Input
|
|
4037
|
+
}], dcpHost: [{
|
|
4038
|
+
type: Input
|
|
4039
|
+
}], token: [{
|
|
4040
|
+
type: Input
|
|
4041
|
+
}], useMockData: [{
|
|
4042
|
+
type: Input
|
|
4043
|
+
}], importRequested: [{
|
|
4044
|
+
type: Output
|
|
4045
|
+
}] } });
|
|
4046
|
+
|
|
4047
|
+
/** The wizard's steps, in order. Index-aligned with the `mat-stepper` steps. */
|
|
4048
|
+
const IMPORT_WIZARD_STEPS = ['select', 'overview'];
|
|
4049
|
+
|
|
4050
|
+
/**
|
|
4051
|
+
* Full-page "Import contact center" wizard: pick a UCCX contact center, review the
|
|
4052
|
+
* entities Tuki will create for it, then start the import.
|
|
4053
|
+
*
|
|
4054
|
+
* Rendered as a page by the host app (like `tk-user-creation-wizard`), not as a dialog -
|
|
4055
|
+
* the host swaps it in when the panel's Import button is pressed and swaps it back out
|
|
4056
|
+
* on `cancel` / `imported`.
|
|
4057
|
+
*/
|
|
4058
|
+
class ImportContactCenterWizardComponent {
|
|
4059
|
+
constructor() {
|
|
4060
|
+
this.title = IMPORT_WIZARD_TITLE;
|
|
4061
|
+
/** Serve mock data instead of calling the UCCX migration API. */
|
|
4062
|
+
this.useMockData = true;
|
|
4063
|
+
/**
|
|
4064
|
+
* Contact centers the caller has already loaded (the panel has them), so the wizard
|
|
4065
|
+
* opens without a second round trip. Left unset, the wizard fetches them itself.
|
|
4066
|
+
*/
|
|
4067
|
+
this.contactCenters = null;
|
|
4068
|
+
this.cancel = new EventEmitter();
|
|
4069
|
+
this.imported = new EventEmitter();
|
|
4070
|
+
this.ccImportService = inject(CcImportService);
|
|
4071
|
+
this.subscriptions = new Subscription();
|
|
4072
|
+
this.customerAssistNotice = CUSTOMER_ASSIST_NOTICE;
|
|
4073
|
+
this.customerAssistMarkerTooltip = CUSTOMER_ASSIST_MARKER_TOOLTIP;
|
|
4074
|
+
this.selectedIndex = 0;
|
|
4075
|
+
/** Contact centers awaiting review - the ones there is something to import. */
|
|
4076
|
+
this.options = [];
|
|
4077
|
+
/** `options` narrowed by the picker's search box. */
|
|
4078
|
+
this.filteredOptions = [];
|
|
4079
|
+
this.searchTerm = '';
|
|
4080
|
+
this.selected = null;
|
|
4081
|
+
this.noticeDismissed = false;
|
|
4082
|
+
this.loading = false;
|
|
4083
|
+
this.error = false;
|
|
4084
|
+
this.entityGroups = [];
|
|
4085
|
+
/** Which entity group the Overview step's tab bar is showing. */
|
|
4086
|
+
this.activeGroupIndex = 0;
|
|
4087
|
+
this.entitiesLoading = false;
|
|
4088
|
+
this.entitiesError = false;
|
|
4089
|
+
this.importing = false;
|
|
4090
|
+
this.importError = false;
|
|
4091
|
+
}
|
|
4092
|
+
ngOnInit() {
|
|
4093
|
+
this.load();
|
|
4094
|
+
}
|
|
4095
|
+
ngOnChanges(changes) {
|
|
4096
|
+
const reloadTriggers = ['customerId', 'host', 'dcpHost', 'token', 'useMockData', 'contactCenters'];
|
|
4097
|
+
if (reloadTriggers.some(input => changes[input] && !changes[input].firstChange)) {
|
|
4098
|
+
this.load();
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
ngOnDestroy() {
|
|
4102
|
+
this.subscriptions.unsubscribe();
|
|
4103
|
+
}
|
|
4104
|
+
get canGoNext() {
|
|
4105
|
+
return !!this.selected;
|
|
4106
|
+
}
|
|
4107
|
+
/** The Customer Assist advisory, until the user dismisses it or picks something else. */
|
|
4108
|
+
get showCustomerAssistNotice() {
|
|
4109
|
+
var _a;
|
|
4110
|
+
return !!((_a = this.selected) === null || _a === void 0 ? void 0 : _a.customerAssistCapable) && !this.noticeDismissed;
|
|
4111
|
+
}
|
|
4112
|
+
get canImport() {
|
|
4113
|
+
return !!this.selected && !this.importing && !this.entitiesLoading && !this.entitiesError;
|
|
4114
|
+
}
|
|
4115
|
+
onCancel() {
|
|
4116
|
+
this.cancel.emit();
|
|
4117
|
+
}
|
|
4118
|
+
onSelect(applicationId) {
|
|
4119
|
+
var _a;
|
|
4120
|
+
const selected = (_a = this.options.find(option => option.applicationId === applicationId)) !== null && _a !== void 0 ? _a : null;
|
|
4121
|
+
if (selected === this.selected) {
|
|
4122
|
+
return;
|
|
4123
|
+
}
|
|
4124
|
+
this.selected = selected;
|
|
4125
|
+
this.noticeDismissed = false;
|
|
4126
|
+
// Entities belong to the previously selected contact center - drop them so the
|
|
4127
|
+
// overview step refetches for the new one.
|
|
4128
|
+
this.entityGroups = [];
|
|
4129
|
+
this.activeGroupIndex = 0;
|
|
4130
|
+
this.entitiesError = false;
|
|
4131
|
+
}
|
|
4132
|
+
get activeGroup() {
|
|
4133
|
+
return this.entityGroups[this.activeGroupIndex];
|
|
4134
|
+
}
|
|
4135
|
+
selectGroup(index) {
|
|
4136
|
+
this.activeGroupIndex = index;
|
|
4137
|
+
}
|
|
4138
|
+
dismissNotice() {
|
|
4139
|
+
this.noticeDismissed = true;
|
|
4140
|
+
}
|
|
4141
|
+
onSearch(event) {
|
|
4142
|
+
this.searchTerm = event.target.value;
|
|
4143
|
+
this.filter();
|
|
4144
|
+
}
|
|
4145
|
+
/** Resets the search box each time the picker's panel is closed. */
|
|
4146
|
+
onPanelToggle(opened) {
|
|
4147
|
+
if (!opened && this.searchTerm) {
|
|
4148
|
+
this.searchTerm = '';
|
|
4149
|
+
this.filter();
|
|
4150
|
+
}
|
|
4151
|
+
}
|
|
4152
|
+
onStepSelectionChange(event) {
|
|
4153
|
+
this.selectedIndex = event.selectedIndex;
|
|
4154
|
+
if (this.stepIdAt(event.selectedIndex) === 'overview') {
|
|
4155
|
+
this.loadEntities();
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
onNext(stepper) {
|
|
4159
|
+
if (this.canGoNext) {
|
|
4160
|
+
stepper.next();
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
onPrevious(stepper) {
|
|
4164
|
+
stepper.previous();
|
|
4165
|
+
}
|
|
4166
|
+
runImport() {
|
|
4167
|
+
if (!this.selected || this.importing) {
|
|
4168
|
+
return;
|
|
4169
|
+
}
|
|
4170
|
+
this.importing = true;
|
|
4171
|
+
this.importError = false;
|
|
4172
|
+
this.subscriptions.add(this.ccImportService.importContactCenter(Number(this.customerId), this.selected.applicationId)
|
|
4173
|
+
.pipe(catchError(error => {
|
|
4174
|
+
console.error('Unable to start the contact-center import', error);
|
|
4175
|
+
this.importError = true;
|
|
4176
|
+
return of(null);
|
|
4177
|
+
}), finalize(() => this.importing = false))
|
|
4178
|
+
.subscribe(result => {
|
|
4179
|
+
if (result) {
|
|
4180
|
+
this.imported.emit(result);
|
|
4181
|
+
}
|
|
4182
|
+
}));
|
|
4183
|
+
}
|
|
4184
|
+
stepIdAt(index) {
|
|
4185
|
+
return IMPORT_WIZARD_STEPS[index];
|
|
4186
|
+
}
|
|
4187
|
+
load() {
|
|
4188
|
+
this.ccImportService.useMockData = this.useMockData;
|
|
4189
|
+
if (this.host) {
|
|
4190
|
+
this.ccImportService.setHost(this.host);
|
|
4191
|
+
}
|
|
4192
|
+
if (this.dcpHost) {
|
|
4193
|
+
this.ccImportService.setDcpHost(this.dcpHost);
|
|
4194
|
+
}
|
|
4195
|
+
if (this.token) {
|
|
4196
|
+
this.ccImportService.setToken(this.token);
|
|
4197
|
+
}
|
|
4198
|
+
if (this.contactCenters) {
|
|
4199
|
+
this.setOptions(this.contactCenters);
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4202
|
+
const customerId = Number(this.customerId);
|
|
4203
|
+
if (!this.useMockData && (!customerId || !this.token)) {
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4206
|
+
this.loading = true;
|
|
4207
|
+
this.error = false;
|
|
4208
|
+
this.subscriptions.add(this.ccImportService.fetchContactCenters(customerId)
|
|
4209
|
+
.pipe(catchError(error => {
|
|
4210
|
+
console.error('Unable to load the contact centers', error);
|
|
4211
|
+
this.error = true;
|
|
4212
|
+
return of([]);
|
|
4213
|
+
}), finalize(() => this.loading = false))
|
|
4214
|
+
.subscribe(contactCenters => this.setOptions(contactCenters)));
|
|
4215
|
+
}
|
|
4216
|
+
setOptions(contactCenters) {
|
|
4217
|
+
// Left in source order on purpose - the picker shows them the way the backend
|
|
4218
|
+
// (and the mock) hands them over, not alphabetically.
|
|
4219
|
+
//
|
|
4220
|
+
// Eligible for a Webex Contact Center import: not imported yet, and either
|
|
4221
|
+
// unsupported on Customer Assist or reviewable for full feature coverage.
|
|
4222
|
+
this.options = contactCenters.filter(contactCenter => contactCenter.migrationState !== 'migrated'
|
|
4223
|
+
&& (contactCenter.compatibilityStatus === 'unsupported'
|
|
4224
|
+
|| contactCenter.compatibilityStatus === 'requires-review'));
|
|
4225
|
+
// A contact center selected before a reload may no longer be importable.
|
|
4226
|
+
if (this.selected && !this.options.some(option => { var _a; return option.applicationId === ((_a = this.selected) === null || _a === void 0 ? void 0 : _a.applicationId); })) {
|
|
4227
|
+
this.selected = null;
|
|
4228
|
+
this.entityGroups = [];
|
|
4229
|
+
this.activeGroupIndex = 0;
|
|
4230
|
+
}
|
|
4231
|
+
this.filter();
|
|
4232
|
+
}
|
|
4233
|
+
filter() {
|
|
4234
|
+
const needle = this.searchTerm.trim().toLowerCase();
|
|
4235
|
+
this.filteredOptions = needle
|
|
4236
|
+
? this.options.filter(option => option.applicationName.toLowerCase().includes(needle))
|
|
4237
|
+
: this.options;
|
|
4238
|
+
}
|
|
4239
|
+
loadEntities() {
|
|
4240
|
+
if (!this.selected || this.entityGroups.length || this.entitiesLoading) {
|
|
4241
|
+
return;
|
|
4242
|
+
}
|
|
4243
|
+
this.entitiesLoading = true;
|
|
4244
|
+
this.entitiesError = false;
|
|
4245
|
+
this.subscriptions.add(this.ccImportService.fetchContactCenterEntities(Number(this.customerId), this.selected)
|
|
4246
|
+
.pipe(catchError(error => {
|
|
4247
|
+
console.error('Unable to load the contact-center entities', error);
|
|
4248
|
+
this.entitiesError = true;
|
|
4249
|
+
return of(null);
|
|
4250
|
+
}), finalize(() => this.entitiesLoading = false))
|
|
4251
|
+
.subscribe(entities => {
|
|
4252
|
+
this.entityGroups = entities ? entities.groups : [];
|
|
4253
|
+
this.activeGroupIndex = 0;
|
|
4254
|
+
}));
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
ImportContactCenterWizardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImportContactCenterWizardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4258
|
+
ImportContactCenterWizardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ImportContactCenterWizardComponent, selector: "cc-import-contact-center-wizard", inputs: { title: "title", customerId: "customerId", host: "host", dcpHost: "dcpHost", token: "token", useMockData: "useMockData", contactCenters: "contactCenters" }, outputs: { cancel: "cancel", imported: "imported" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"move-user-stepper-container\" [attr.aria-busy]=\"importing\">\r\n <header class=\"move-user-header\">\r\n <div class=\"move-user-header__title\">{{ title }}</div>\r\n <div class=\"move-user-header__close\">\r\n <span class=\"app-icon cc-import-close-icon\" (click)=\"onCancel()\" role=\"button\" aria-label=\"Close\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M5 5L19 19M19 5L5 19\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </header>\r\n\r\n <div id=\"cc-import-stepper\">\r\n <mat-stepper\r\n #stepper\r\n [linear]=\"true\"\r\n labelPosition=\"bottom\"\r\n [selectedIndex]=\"selectedIndex\"\r\n (selectionChange)=\"onStepSelectionChange($event)\"\r\n >\r\n\r\n <!-- Step 1: pick the UCCX contact center -->\r\n <mat-step [completed]=\"canGoNext\">\r\n <ng-template matStepLabel>Select</ng-template>\r\n\r\n <div class=\"cc-import-notice\" *ngIf=\"showCustomerAssistNotice\" role=\"status\">\r\n <span class=\"cc-import-notice__icon\" aria-hidden=\"true\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <circle cx=\"8\" cy=\"8\" r=\"7\" fill=\"currentColor\" />\r\n <path d=\"M8 7.1v4.2\" stroke=\"#fff\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"4.8\" r=\"0.9\" fill=\"#fff\" />\r\n </svg>\r\n </span>\r\n <span class=\"cc-import-notice__text\">{{ customerAssistNotice }}</span>\r\n <button type=\"button\" class=\"cc-import-notice__close\" aria-label=\"Dismiss\" (click)=\"dismissNotice()\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M5 5L19 19M19 5L5 19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"step-title\">Step 1: Select contact center</div>\r\n\r\n <div class=\"move-user-tab-content-box\">\r\n <div class=\"cc-import-state\" *ngIf=\"loading\">Loading contact centers…</div>\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"!loading && error\">\r\n Unable to load contact centers.\r\n </div>\r\n\r\n <section class=\"cc-import-step-content\" *ngIf=\"!loading && !error\">\r\n <div class=\"cc-import-field\">\r\n <label class=\"cc-import-label\" for=\"cc-import-contact-center\">Contact center</label>\r\n\r\n <mat-form-field class=\"cc-import-select\" appearance=\"outline\">\r\n <mat-select\r\n id=\"cc-import-contact-center\"\r\n panelClass=\"cc-import-select-panel\"\r\n placeholder=\"Select contact center\"\r\n [disableOptionCentering]=\"true\"\r\n [value]=\"selected?.applicationId ?? null\"\r\n (selectionChange)=\"onSelect($event.value)\"\r\n (openedChange)=\"onPanelToggle($event)\"\r\n >\r\n <mat-select-trigger>{{ selected?.applicationName }}</mat-select-trigger>\r\n\r\n <!-- Search box pinned above the options. Keystrokes are stopped here so\r\n mat-select's own typeahead does not steal them. -->\r\n <div class=\"cc-import-select-search\" (click)=\"$event.stopPropagation()\">\r\n <span class=\"cc-import-select-search__icon\" aria-hidden=\"true\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <circle cx=\"7\" cy=\"7\" r=\"4.6\" stroke=\"currentColor\" stroke-width=\"1.4\" />\r\n <path d=\"M10.6 10.6L14 14\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\r\n </svg>\r\n </span>\r\n <input\r\n class=\"cc-import-select-search__input\"\r\n type=\"text\"\r\n autocomplete=\"off\"\r\n placeholder=\"Search\"\r\n aria-label=\"Search contact centers\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearch($event)\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.applicationId\">\r\n <div class=\"option-row\">\r\n <span class=\"name\">{{ option.applicationName }}</span>\r\n <span\r\n class=\"cc-import-option-marker\"\r\n *ngIf=\"option.customerAssistCapable\"\r\n [matTooltip]=\"customerAssistMarkerTooltip\"\r\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <path d=\"M8 2.2 14.6 13.4H1.4L8 2.2Z\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linejoin=\"round\" />\r\n <path d=\"M8 6.5v3\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"11.3\" r=\"0.7\" fill=\"currentColor\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <p class=\"cc-import-empty\" *ngIf=\"!options.length\">\r\n Every detected contact center has already been imported.\r\n </p>\r\n </div>\r\n </section>\r\n </div>\r\n </mat-step>\r\n\r\n <!-- Step 2: the entities Tuki will create for it -->\r\n <mat-step>\r\n <ng-template matStepLabel>Overview</ng-template>\r\n\r\n <div class=\"step-title\">Overview</div>\r\n\r\n <div class=\"move-user-tab-content-box\">\r\n <h3 class=\"cc-import-card-title\">Review Contact Center Settings</h3>\r\n <p class=\"cc-import-card-text\">\r\n Review the settings for your new Contact center to make sure everything is correct.<br />\r\n You can make changes at any time by clicking on the name of the contact center on the dedicated page.\r\n </p>\r\n\r\n <div class=\"cc-import-state\" *ngIf=\"entitiesLoading\">Loading entities…</div>\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"entitiesError\">\r\n Unable to load the related entities.\r\n </div>\r\n\r\n <ng-container *ngIf=\"!entitiesLoading && !entitiesError && entityGroups.length\">\r\n <div class=\"cc-import-tabs\" role=\"tablist\">\r\n <button\r\n type=\"button\"\r\n class=\"cc-import-tab\"\r\n *ngFor=\"let group of entityGroups; index as i\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"i === activeGroupIndex\"\r\n [class.cc-import-tab--active]=\"i === activeGroupIndex\"\r\n (click)=\"selectGroup(i)\"\r\n >\r\n {{ group.label }}\r\n </button>\r\n </div>\r\n\r\n <ul class=\"cc-import-items\" role=\"tabpanel\">\r\n <li class=\"cc-import-item\" *ngFor=\"let item of activeGroup?.items\">{{ item }}</li>\r\n <li class=\"cc-import-item cc-import-item--empty\" *ngIf=\"!activeGroup?.items?.length\">\r\n Nothing to create for {{ activeGroup?.label }}.\r\n </li>\r\n </ul>\r\n </ng-container>\r\n\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"importError\">\r\n Unable to start the import. Please try again.\r\n </div>\r\n </div>\r\n </mat-step>\r\n </mat-stepper>\r\n\r\n <div class=\"wizard-actions\">\r\n <ng-container [ngSwitch]=\"stepper.selectedIndex\">\r\n <ng-container *ngSwitchCase=\"0\">\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-primary\"\r\n type=\"button\"\r\n [disabled]=\"!canGoNext\"\r\n (click)=\"onNext(stepper)\"\r\n >\r\n Next\r\n </button>\r\n <button mat-button class=\"uc-btn uc-btn-secondary\" type=\"button\" (click)=\"onCancel()\">\r\n Cancel\r\n </button>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"1\">\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-primary\"\r\n type=\"button\"\r\n [disabled]=\"!canImport\"\r\n (click)=\"runImport()\"\r\n >\r\n <span class=\"uc-btn__inline-content\">\r\n <span class=\"uc-btn__spinner\" *ngIf=\"importing\" aria-hidden=\"true\"></span>\r\n <span>{{ importing ? 'Importing...' : 'Import' }}</span>\r\n </span>\r\n </button>\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-secondary\"\r\n type=\"button\"\r\n [disabled]=\"importing\"\r\n (click)=\"onPrevious(stepper)\"\r\n >\r\n Previous\r\n </button>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wizard-loading-overlay\" [class.wizard-loading-overlay--visible]=\"importing\" aria-hidden=\"true\"></div>\r\n</div>\r\n", styles: ["cc-import-contact-center-wizard{display:block;width:100%;min-height:100vh}.move-user-stepper-container{background-color:#f3f3f3;padding:0 0 16px;position:relative;overflow:hidden;box-sizing:border-box;min-height:100vh;display:flex;flex-direction:column}.move-user-header{background-color:#1170cf;height:45px;padding:1rem 1.5rem;display:flex;align-items:center;justify-content:space-between;color:#fff;font-size:18px;font-weight:500}.move-user-header__close{cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:0}.app-icon{height:20px;width:20px;display:block;cursor:pointer}.cc-import-close-icon{color:#fffffff2}#cc-import-stepper{display:flex;flex-direction:column;width:100%;flex:1 1 auto;min-height:0}#cc-import-stepper .mat-stepper-horizontal{margin:0 auto;width:100%;background-color:transparent;display:flex;flex-direction:column;flex:1 1 auto;min-height:0}#cc-import-stepper .mat-horizontal-stepper-header-container{margin:0 auto;width:800px}#cc-import-stepper .mat-step-icon{width:28px;height:28px;border:3px solid hsl(0,0%,50.2%)}#cc-import-stepper .mat-step-icon-selected{background-color:#c6c6c6!important;border-color:#19487d}#cc-import-stepper .mat-step-icon-state-number{background-color:#fff}#cc-import-stepper .mat-step-icon-state-edit,#cc-import-stepper .mat-step-header .mat-step-icon-state-done{background-color:#1170cf;border-color:#1170cf}#cc-import-stepper .mat-step-icon-content{display:none}#cc-import-stepper .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:first-child):before,#cc-import-stepper [dir=rtl] .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:last-child):before,#cc-import-stepper .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:last-child):after,#cc-import-stepper [dir=rtl] .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:first-child):after{border-top-width:3px!important}#cc-import-stepper .mat-horizontal-stepper-header:before,#cc-import-stepper .mat-horizontal-stepper-header:after,#cc-import-stepper .mat-stepper-horizontal-line{border-top-color:#1170cf!important;border-top-width:3px!important;border-top-style:solid!important}#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-stepper-horizontal-line,#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-horizontal-stepper-header:before,#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-horizontal-stepper-header:after{border-top-width:3px!important;background-color:#7b7b7b!important;border-top-color:#7b7b7b!important}#cc-import-stepper .mat-horizontal-content-container{padding:0!important;margin-top:3rem}#cc-import-stepper .mat-horizontal-stepper-content[aria-expanded=true]{padding-bottom:0}.step-title{font-size:26px;font-weight:500;width:70%;margin:0 auto 1rem;min-height:32px;display:flex;align-items:center}.wizard-actions{display:flex;flex-flow:row-reverse;justify-content:flex-start;align-items:center;margin:16px 16px 0 0;align-self:flex-end;gap:1rem;position:relative;z-index:30}.uc-btn{border-radius:50px!important;padding:8px 16px!important;min-width:80px!important;line-height:normal!important;cursor:pointer}.uc-btn__inline-content{display:inline-flex;align-items:center;gap:8px}.uc-btn__spinner{width:14px;height:14px;border:2px solid rgba(255,255,255,.5);border-top-color:#fff;border-radius:50%;animation:uc-btn-spin .7s linear infinite}@keyframes uc-btn-spin{to{transform:rotate(360deg)}}.uc-btn-primary{background-color:#000!important;color:#fff!important;border:1px solid black!important}.uc-btn-secondary{background-color:#fff!important;color:#000!important;border:1px solid black!important}.wizard-actions .uc-btn-primary.mat-button-disabled{background-color:#bbb;color:#fff;border:1px solid grey;cursor:default!important;opacity:.3}.move-user-tab-content-box{width:70%;margin:0 auto;background-color:#fff;min-height:350px;border:1px solid #c3c1c1;border-radius:8px;box-sizing:border-box;padding:25px}.wizard-loading-overlay{position:absolute;inset:0;background:rgba(243,243,243,.72);backdrop-filter:blur(1px);opacity:0;pointer-events:none;transition:opacity .18s ease;z-index:20}.wizard-loading-overlay--visible{opacity:1;pointer-events:auto}.cc-import-notice{width:70%;margin:0 auto 1rem;box-sizing:border-box;display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:4px;background-color:#e8f2fc;color:#2a2f3b;font-size:13px;line-height:1.4}.cc-import-notice__icon{display:flex;color:#1170cf;line-height:0}.cc-import-notice__text{flex:1}.cc-import-notice__close{background:none;border:none;padding:0;cursor:pointer;display:flex;color:#5a6172;line-height:0}.cc-import-step-content{display:flex;flex-direction:column;gap:20px;max-width:420px}.cc-import-field{display:flex;flex-direction:column;gap:10px}.cc-import-label{font-size:14px;font-weight:400;line-height:100%;letter-spacing:.1px;color:#2a2f3b}.cc-import-select{width:100%;max-width:333px}.cc-import-empty{margin:0;font-size:13px;color:#5a6172}.cc-import-state{font-size:14px;color:#5a6172}.cc-import-state--error{color:#c0392b}.cc-import-card-title{margin:0 0 8px;font-size:15px;font-weight:700;color:#2a2f3b}.cc-import-card-text{margin:0 0 22px;font-size:14px;line-height:1.6;color:#2a2f3b}.cc-import-tabs{display:flex;flex-wrap:wrap;gap:20px}.cc-import-tab{background:none;border:none;border-bottom:2px solid transparent;padding:0 0 8px;font:inherit;font-size:14px;color:#5a6172;cursor:pointer}.cc-import-tab--active{color:#000;font-weight:600;border-bottom-color:#000}.cc-import-items{list-style:none;margin:18px 0 0;padding:0;display:flex;flex-direction:column;gap:10px}.cc-import-item{font-size:14px;color:#2a2f3b}.cc-import-item--empty{color:#5a6172;font-style:italic}.cc-import-select .mat-form-field-wrapper{padding-bottom:0}.cc-import-select .mat-form-field-flex{align-items:center;height:32px;border:1px solid #767676;border-radius:6px;padding:0 12px}.cc-import-select .mat-form-field-outline,.cc-import-select .mat-form-field-outline-start,.cc-import-select .mat-form-field-outline-end,.cc-import-select .mat-form-field-outline-gap{display:none}.cc-import-select .mat-form-field-infix{width:100%;border-top:0;padding:0}.cc-import-select .mat-select-trigger{display:flex;align-items:center;justify-content:space-between;height:100%}.cc-import-select-panel .option-row{display:flex;justify-content:space-between;align-items:center;width:100%;gap:12px}.cc-import-select-panel .cc-import-option-marker{display:flex;color:#b26a00;line-height:0}.cc-import-select-search{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;margin:4px 8px 8px;padding:0 10px;height:30px;border:1px solid #c3c1c1;border-radius:50px;background-color:#fff}.cc-import-select-search__icon{display:flex;color:#5a6172;line-height:0}.cc-import-select-search__input{flex:1;border:none;outline:none;font:inherit;font-size:13px;color:#2a2f3b;background:transparent}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: i2$2.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i2$2.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i2$2.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["selectedIndex", "disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i3$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i1$4.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "component", type: i6.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "directive", type: i6.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i3.MatOption, selector: "mat-option", exportAs: ["matOption"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
4259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ImportContactCenterWizardComponent, decorators: [{
|
|
4260
|
+
type: Component,
|
|
4261
|
+
args: [{ selector: 'cc-import-contact-center-wizard', encapsulation: ViewEncapsulation.None, template: "<div class=\"move-user-stepper-container\" [attr.aria-busy]=\"importing\">\r\n <header class=\"move-user-header\">\r\n <div class=\"move-user-header__title\">{{ title }}</div>\r\n <div class=\"move-user-header__close\">\r\n <span class=\"app-icon cc-import-close-icon\" (click)=\"onCancel()\" role=\"button\" aria-label=\"Close\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M5 5L19 19M19 5L5 19\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </header>\r\n\r\n <div id=\"cc-import-stepper\">\r\n <mat-stepper\r\n #stepper\r\n [linear]=\"true\"\r\n labelPosition=\"bottom\"\r\n [selectedIndex]=\"selectedIndex\"\r\n (selectionChange)=\"onStepSelectionChange($event)\"\r\n >\r\n\r\n <!-- Step 1: pick the UCCX contact center -->\r\n <mat-step [completed]=\"canGoNext\">\r\n <ng-template matStepLabel>Select</ng-template>\r\n\r\n <div class=\"cc-import-notice\" *ngIf=\"showCustomerAssistNotice\" role=\"status\">\r\n <span class=\"cc-import-notice__icon\" aria-hidden=\"true\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <circle cx=\"8\" cy=\"8\" r=\"7\" fill=\"currentColor\" />\r\n <path d=\"M8 7.1v4.2\" stroke=\"#fff\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"4.8\" r=\"0.9\" fill=\"#fff\" />\r\n </svg>\r\n </span>\r\n <span class=\"cc-import-notice__text\">{{ customerAssistNotice }}</span>\r\n <button type=\"button\" class=\"cc-import-notice__close\" aria-label=\"Dismiss\" (click)=\"dismissNotice()\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M5 5L19 19M19 5L5 19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"step-title\">Step 1: Select contact center</div>\r\n\r\n <div class=\"move-user-tab-content-box\">\r\n <div class=\"cc-import-state\" *ngIf=\"loading\">Loading contact centers…</div>\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"!loading && error\">\r\n Unable to load contact centers.\r\n </div>\r\n\r\n <section class=\"cc-import-step-content\" *ngIf=\"!loading && !error\">\r\n <div class=\"cc-import-field\">\r\n <label class=\"cc-import-label\" for=\"cc-import-contact-center\">Contact center</label>\r\n\r\n <mat-form-field class=\"cc-import-select\" appearance=\"outline\">\r\n <mat-select\r\n id=\"cc-import-contact-center\"\r\n panelClass=\"cc-import-select-panel\"\r\n placeholder=\"Select contact center\"\r\n [disableOptionCentering]=\"true\"\r\n [value]=\"selected?.applicationId ?? null\"\r\n (selectionChange)=\"onSelect($event.value)\"\r\n (openedChange)=\"onPanelToggle($event)\"\r\n >\r\n <mat-select-trigger>{{ selected?.applicationName }}</mat-select-trigger>\r\n\r\n <!-- Search box pinned above the options. Keystrokes are stopped here so\r\n mat-select's own typeahead does not steal them. -->\r\n <div class=\"cc-import-select-search\" (click)=\"$event.stopPropagation()\">\r\n <span class=\"cc-import-select-search__icon\" aria-hidden=\"true\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <circle cx=\"7\" cy=\"7\" r=\"4.6\" stroke=\"currentColor\" stroke-width=\"1.4\" />\r\n <path d=\"M10.6 10.6L14 14\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\r\n </svg>\r\n </span>\r\n <input\r\n class=\"cc-import-select-search__input\"\r\n type=\"text\"\r\n autocomplete=\"off\"\r\n placeholder=\"Search\"\r\n aria-label=\"Search contact centers\"\r\n [value]=\"searchTerm\"\r\n (input)=\"onSearch($event)\"\r\n (keydown)=\"$event.stopPropagation()\"\r\n />\r\n </div>\r\n\r\n <mat-option *ngFor=\"let option of filteredOptions\" [value]=\"option.applicationId\">\r\n <div class=\"option-row\">\r\n <span class=\"name\">{{ option.applicationName }}</span>\r\n <span\r\n class=\"cc-import-option-marker\"\r\n *ngIf=\"option.customerAssistCapable\"\r\n [matTooltip]=\"customerAssistMarkerTooltip\"\r\n aria-hidden=\"true\"\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\r\n <path d=\"M8 2.2 14.6 13.4H1.4L8 2.2Z\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linejoin=\"round\" />\r\n <path d=\"M8 6.5v3\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linecap=\"round\" />\r\n <circle cx=\"8\" cy=\"11.3\" r=\"0.7\" fill=\"currentColor\" />\r\n </svg>\r\n </span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <p class=\"cc-import-empty\" *ngIf=\"!options.length\">\r\n Every detected contact center has already been imported.\r\n </p>\r\n </div>\r\n </section>\r\n </div>\r\n </mat-step>\r\n\r\n <!-- Step 2: the entities Tuki will create for it -->\r\n <mat-step>\r\n <ng-template matStepLabel>Overview</ng-template>\r\n\r\n <div class=\"step-title\">Overview</div>\r\n\r\n <div class=\"move-user-tab-content-box\">\r\n <h3 class=\"cc-import-card-title\">Review Contact Center Settings</h3>\r\n <p class=\"cc-import-card-text\">\r\n Review the settings for your new Contact center to make sure everything is correct.<br />\r\n You can make changes at any time by clicking on the name of the contact center on the dedicated page.\r\n </p>\r\n\r\n <div class=\"cc-import-state\" *ngIf=\"entitiesLoading\">Loading entities…</div>\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"entitiesError\">\r\n Unable to load the related entities.\r\n </div>\r\n\r\n <ng-container *ngIf=\"!entitiesLoading && !entitiesError && entityGroups.length\">\r\n <div class=\"cc-import-tabs\" role=\"tablist\">\r\n <button\r\n type=\"button\"\r\n class=\"cc-import-tab\"\r\n *ngFor=\"let group of entityGroups; index as i\"\r\n role=\"tab\"\r\n [attr.aria-selected]=\"i === activeGroupIndex\"\r\n [class.cc-import-tab--active]=\"i === activeGroupIndex\"\r\n (click)=\"selectGroup(i)\"\r\n >\r\n {{ group.label }}\r\n </button>\r\n </div>\r\n\r\n <ul class=\"cc-import-items\" role=\"tabpanel\">\r\n <li class=\"cc-import-item\" *ngFor=\"let item of activeGroup?.items\">{{ item }}</li>\r\n <li class=\"cc-import-item cc-import-item--empty\" *ngIf=\"!activeGroup?.items?.length\">\r\n Nothing to create for {{ activeGroup?.label }}.\r\n </li>\r\n </ul>\r\n </ng-container>\r\n\r\n <div class=\"cc-import-state cc-import-state--error\" *ngIf=\"importError\">\r\n Unable to start the import. Please try again.\r\n </div>\r\n </div>\r\n </mat-step>\r\n </mat-stepper>\r\n\r\n <div class=\"wizard-actions\">\r\n <ng-container [ngSwitch]=\"stepper.selectedIndex\">\r\n <ng-container *ngSwitchCase=\"0\">\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-primary\"\r\n type=\"button\"\r\n [disabled]=\"!canGoNext\"\r\n (click)=\"onNext(stepper)\"\r\n >\r\n Next\r\n </button>\r\n <button mat-button class=\"uc-btn uc-btn-secondary\" type=\"button\" (click)=\"onCancel()\">\r\n Cancel\r\n </button>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"1\">\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-primary\"\r\n type=\"button\"\r\n [disabled]=\"!canImport\"\r\n (click)=\"runImport()\"\r\n >\r\n <span class=\"uc-btn__inline-content\">\r\n <span class=\"uc-btn__spinner\" *ngIf=\"importing\" aria-hidden=\"true\"></span>\r\n <span>{{ importing ? 'Importing...' : 'Import' }}</span>\r\n </span>\r\n </button>\r\n <button\r\n mat-button\r\n class=\"uc-btn uc-btn-secondary\"\r\n type=\"button\"\r\n [disabled]=\"importing\"\r\n (click)=\"onPrevious(stepper)\"\r\n >\r\n Previous\r\n </button>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"wizard-loading-overlay\" [class.wizard-loading-overlay--visible]=\"importing\" aria-hidden=\"true\"></div>\r\n</div>\r\n", styles: ["cc-import-contact-center-wizard{display:block;width:100%;min-height:100vh}.move-user-stepper-container{background-color:#f3f3f3;padding:0 0 16px;position:relative;overflow:hidden;box-sizing:border-box;min-height:100vh;display:flex;flex-direction:column}.move-user-header{background-color:#1170cf;height:45px;padding:1rem 1.5rem;display:flex;align-items:center;justify-content:space-between;color:#fff;font-size:18px;font-weight:500}.move-user-header__close{cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:0}.app-icon{height:20px;width:20px;display:block;cursor:pointer}.cc-import-close-icon{color:#fffffff2}#cc-import-stepper{display:flex;flex-direction:column;width:100%;flex:1 1 auto;min-height:0}#cc-import-stepper .mat-stepper-horizontal{margin:0 auto;width:100%;background-color:transparent;display:flex;flex-direction:column;flex:1 1 auto;min-height:0}#cc-import-stepper .mat-horizontal-stepper-header-container{margin:0 auto;width:800px}#cc-import-stepper .mat-step-icon{width:28px;height:28px;border:3px solid hsl(0,0%,50.2%)}#cc-import-stepper .mat-step-icon-selected{background-color:#c6c6c6!important;border-color:#19487d}#cc-import-stepper .mat-step-icon-state-number{background-color:#fff}#cc-import-stepper .mat-step-icon-state-edit,#cc-import-stepper .mat-step-header .mat-step-icon-state-done{background-color:#1170cf;border-color:#1170cf}#cc-import-stepper .mat-step-icon-content{display:none}#cc-import-stepper .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:first-child):before,#cc-import-stepper [dir=rtl] .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:last-child):before,#cc-import-stepper .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:last-child):after,#cc-import-stepper [dir=rtl] .mat-stepper-label-position-bottom .mat-horizontal-stepper-header:not(:first-child):after{border-top-width:3px!important}#cc-import-stepper .mat-horizontal-stepper-header:before,#cc-import-stepper .mat-horizontal-stepper-header:after,#cc-import-stepper .mat-stepper-horizontal-line{border-top-color:#1170cf!important;border-top-width:3px!important;border-top-style:solid!important}#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-stepper-horizontal-line,#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-horizontal-stepper-header:before,#cc-import-stepper .mat-horizontal-stepper-header[aria-selected=true]~.mat-horizontal-stepper-header:after{border-top-width:3px!important;background-color:#7b7b7b!important;border-top-color:#7b7b7b!important}#cc-import-stepper .mat-horizontal-content-container{padding:0!important;margin-top:3rem}#cc-import-stepper .mat-horizontal-stepper-content[aria-expanded=true]{padding-bottom:0}.step-title{font-size:26px;font-weight:500;width:70%;margin:0 auto 1rem;min-height:32px;display:flex;align-items:center}.wizard-actions{display:flex;flex-flow:row-reverse;justify-content:flex-start;align-items:center;margin:16px 16px 0 0;align-self:flex-end;gap:1rem;position:relative;z-index:30}.uc-btn{border-radius:50px!important;padding:8px 16px!important;min-width:80px!important;line-height:normal!important;cursor:pointer}.uc-btn__inline-content{display:inline-flex;align-items:center;gap:8px}.uc-btn__spinner{width:14px;height:14px;border:2px solid rgba(255,255,255,.5);border-top-color:#fff;border-radius:50%;animation:uc-btn-spin .7s linear infinite}@keyframes uc-btn-spin{to{transform:rotate(360deg)}}.uc-btn-primary{background-color:#000!important;color:#fff!important;border:1px solid black!important}.uc-btn-secondary{background-color:#fff!important;color:#000!important;border:1px solid black!important}.wizard-actions .uc-btn-primary.mat-button-disabled{background-color:#bbb;color:#fff;border:1px solid grey;cursor:default!important;opacity:.3}.move-user-tab-content-box{width:70%;margin:0 auto;background-color:#fff;min-height:350px;border:1px solid #c3c1c1;border-radius:8px;box-sizing:border-box;padding:25px}.wizard-loading-overlay{position:absolute;inset:0;background:rgba(243,243,243,.72);backdrop-filter:blur(1px);opacity:0;pointer-events:none;transition:opacity .18s ease;z-index:20}.wizard-loading-overlay--visible{opacity:1;pointer-events:auto}.cc-import-notice{width:70%;margin:0 auto 1rem;box-sizing:border-box;display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:4px;background-color:#e8f2fc;color:#2a2f3b;font-size:13px;line-height:1.4}.cc-import-notice__icon{display:flex;color:#1170cf;line-height:0}.cc-import-notice__text{flex:1}.cc-import-notice__close{background:none;border:none;padding:0;cursor:pointer;display:flex;color:#5a6172;line-height:0}.cc-import-step-content{display:flex;flex-direction:column;gap:20px;max-width:420px}.cc-import-field{display:flex;flex-direction:column;gap:10px}.cc-import-label{font-size:14px;font-weight:400;line-height:100%;letter-spacing:.1px;color:#2a2f3b}.cc-import-select{width:100%;max-width:333px}.cc-import-empty{margin:0;font-size:13px;color:#5a6172}.cc-import-state{font-size:14px;color:#5a6172}.cc-import-state--error{color:#c0392b}.cc-import-card-title{margin:0 0 8px;font-size:15px;font-weight:700;color:#2a2f3b}.cc-import-card-text{margin:0 0 22px;font-size:14px;line-height:1.6;color:#2a2f3b}.cc-import-tabs{display:flex;flex-wrap:wrap;gap:20px}.cc-import-tab{background:none;border:none;border-bottom:2px solid transparent;padding:0 0 8px;font:inherit;font-size:14px;color:#5a6172;cursor:pointer}.cc-import-tab--active{color:#000;font-weight:600;border-bottom-color:#000}.cc-import-items{list-style:none;margin:18px 0 0;padding:0;display:flex;flex-direction:column;gap:10px}.cc-import-item{font-size:14px;color:#2a2f3b}.cc-import-item--empty{color:#5a6172;font-style:italic}.cc-import-select .mat-form-field-wrapper{padding-bottom:0}.cc-import-select .mat-form-field-flex{align-items:center;height:32px;border:1px solid #767676;border-radius:6px;padding:0 12px}.cc-import-select .mat-form-field-outline,.cc-import-select .mat-form-field-outline-start,.cc-import-select .mat-form-field-outline-end,.cc-import-select .mat-form-field-outline-gap{display:none}.cc-import-select .mat-form-field-infix{width:100%;border-top:0;padding:0}.cc-import-select .mat-select-trigger{display:flex;align-items:center;justify-content:space-between;height:100%}.cc-import-select-panel .option-row{display:flex;justify-content:space-between;align-items:center;width:100%;gap:12px}.cc-import-select-panel .cc-import-option-marker{display:flex;color:#b26a00;line-height:0}.cc-import-select-search{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;margin:4px 8px 8px;padding:0 10px;height:30px;border:1px solid #c3c1c1;border-radius:50px;background-color:#fff}.cc-import-select-search__icon{display:flex;color:#5a6172;line-height:0}.cc-import-select-search__input{flex:1;border:none;outline:none;font:inherit;font-size:13px;color:#2a2f3b;background:transparent}\n"] }]
|
|
4262
|
+
}], propDecorators: { title: [{
|
|
4263
|
+
type: Input
|
|
4264
|
+
}], customerId: [{
|
|
4265
|
+
type: Input
|
|
4266
|
+
}], host: [{
|
|
4267
|
+
type: Input
|
|
4268
|
+
}], dcpHost: [{
|
|
4269
|
+
type: Input
|
|
4270
|
+
}], token: [{
|
|
4271
|
+
type: Input
|
|
4272
|
+
}], useMockData: [{
|
|
4273
|
+
type: Input
|
|
4274
|
+
}], contactCenters: [{
|
|
4275
|
+
type: Input
|
|
4276
|
+
}], cancel: [{
|
|
4277
|
+
type: Output
|
|
4278
|
+
}], imported: [{
|
|
4279
|
+
type: Output
|
|
4280
|
+
}] } });
|
|
4281
|
+
|
|
4282
|
+
class CcImportModule {
|
|
4283
|
+
}
|
|
4284
|
+
CcImportModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
4285
|
+
CcImportModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: CcImportModule, declarations: [ImportContactCenterPanelComponent,
|
|
4286
|
+
ImportContactCenterWizardComponent], imports: [CommonModule,
|
|
4287
|
+
HttpClientModule,
|
|
4288
|
+
NgApexchartsModule,
|
|
4289
|
+
MatStepperModule,
|
|
4290
|
+
SharedModule], exports: [ImportContactCenterPanelComponent,
|
|
4291
|
+
ImportContactCenterWizardComponent] });
|
|
4292
|
+
CcImportModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportModule, imports: [CommonModule,
|
|
4293
|
+
HttpClientModule,
|
|
4294
|
+
NgApexchartsModule,
|
|
4295
|
+
MatStepperModule,
|
|
4296
|
+
SharedModule] });
|
|
4297
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CcImportModule, decorators: [{
|
|
4298
|
+
type: NgModule,
|
|
4299
|
+
args: [{
|
|
4300
|
+
declarations: [
|
|
4301
|
+
ImportContactCenterPanelComponent,
|
|
4302
|
+
ImportContactCenterWizardComponent
|
|
4303
|
+
],
|
|
4304
|
+
imports: [
|
|
4305
|
+
CommonModule,
|
|
4306
|
+
HttpClientModule,
|
|
4307
|
+
NgApexchartsModule,
|
|
4308
|
+
MatStepperModule,
|
|
4309
|
+
SharedModule
|
|
4310
|
+
],
|
|
4311
|
+
exports: [
|
|
4312
|
+
ImportContactCenterPanelComponent,
|
|
4313
|
+
ImportContactCenterWizardComponent
|
|
4314
|
+
]
|
|
4315
|
+
}]
|
|
4316
|
+
}] });
|
|
4317
|
+
|
|
3447
4318
|
/**
|
|
3448
4319
|
* Generated bundle index. Do not edit.
|
|
3449
4320
|
*/
|
|
3450
4321
|
|
|
3451
|
-
export { CcReadinessModule, LicencesRequirementComponent, SummaryGridComponent, WxCCFlowchartModule, WxCCFlowchartPageComponent };
|
|
4322
|
+
export { CALL_FLOW_MIGRATED, CHART_COLORS, COMPATIBILITY_THRESHOLDS, CUSTOMER_ASSIST_MARKER_TOOLTIP, CUSTOMER_ASSIST_NOTICE, CcImportModule, CcImportService, CcReadinessModule, IMPORT_PANEL_SLICES, IMPORT_PANEL_TITLE, IMPORT_PANEL_TOOLTIP, IMPORT_WIZARD_STEPS, IMPORT_WIZARD_TITLE, ImportContactCenterPanelComponent, ImportContactCenterWizardComponent, LicencesRequirementComponent, OVERVIEW_ENTITY_GROUPS, SummaryGridComponent, UCCX_ITEM_TYPE, WxCCFlowchartModule, WxCCFlowchartPageComponent };
|
|
3452
4323
|
//# sourceMappingURL=tuki-io-tuki-widgets-contact-center.mjs.map
|