{"version":3,"file":"main.ce7134a0891e0867a3dc.js","mappings":"AAEA","sources":["webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-add-edit-dialog.component.css","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-grouped-row.component.css","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.component.css","webpack://calpine-client-portal/./src/app/administration/users/users.component.css","webpack://calpine-client-portal/./src/app/app.component.css","webpack://calpine-client-portal/./src/app/dynamic-scheduling/help-schedule/help-schedule.component.css","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.component.css","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.component.css","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/dynamic-scheduling.component.css","webpack://calpine-client-portal/./src/app/home/home.component.css","webpack://calpine-client-portal/./src/app/shared/breadcrumb/breadcrumb.component.css","webpack://calpine-client-portal/./src/app/shared/datepicker/datepicker-popup.component.css","webpack://calpine-client-portal/./src/app/shared/footer/footer.component.css","webpack://calpine-client-portal/./src/app/shared/nav-menu/nav-menu.component.css","webpack://calpine-client-portal/./src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.component.css","webpack://calpine-client-portal/./src/app/shared/pager/pager.component.css","webpack://calpine-client-portal/./src/app/user-management/shared/user-management.component.css","webpack://calpine-client-portal/./src/assets/Blue/Administration-blue.jpg","webpack://calpine-client-portal/./src/assets/Blue/Billing-blue.jpg","webpack://calpine-client-portal/./src/assets/Blue/Impersonate-blue.jpg","webpack://calpine-client-portal/./src/assets/Blue/Power-Manager-blue.jpg","webpack://calpine-client-portal/./src/assets/Blue/Reports-blue.jpg","webpack://calpine-client-portal/./src/assets/Gray/Administration-gray.jpg","webpack://calpine-client-portal/./src/assets/Gray/Billing-gray.jpg","webpack://calpine-client-portal/./src/assets/Gray/Impersonate-gray.jpg","webpack://calpine-client-portal/./src/assets/Gray/Power-Manager-gray.jpg","webpack://calpine-client-portal/./src/assets/Gray/Reports-gray.jpg","webpack://calpine-client-portal/./src/assets/Gray/Reports-grayed-out.jpg","webpack://calpine-client-portal/./src/assets/home_background.jpg","webpack://calpine-client-portal/./src/assets/nes_bg.jpg","webpack://calpine-client-portal/./node_modules/moment-timezone/node_modules/moment/locale/ sync ^\\.\\/.*$","webpack://calpine-client-portal/./node_modules/moment/locale/ sync ^\\.\\/.*$","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-add-edit-dialog.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-grouped-row.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-remove-dialog.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-roles.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/send-welcome-email-dialog.component.html","webpack://calpine-client-portal/./src/app/administration/users/users-remove-dialog.component.html","webpack://calpine-client-portal/./src/app/administration/users/users.component.html","webpack://calpine-client-portal/./src/app/authentication/session-timeout.component.html","webpack://calpine-client-portal/./src/app/billing/invoice-n-payment/invoice-download-error-dialog.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/dynamic-scheduling.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/help-schedule/help-schedule.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload-error-dialog.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-header.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-search-bar.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-table.component.html","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-unavailable.component.html","webpack://calpine-client-portal/./src/app/home/contact-us/contact-us.component.html","webpack://calpine-client-portal/./src/app/home/home.component.html","webpack://calpine-client-portal/./src/app/home/terms-conditions/terms-conditions.component.html","webpack://calpine-client-portal/./src/app/shared/breadcrumb/breadcrumb.component.html","webpack://calpine-client-portal/./src/app/shared/datepicker/datepicker-popup.component.html","webpack://calpine-client-portal/./src/app/shared/document-download/document-download-list.component.html","webpack://calpine-client-portal/./src/app/shared/error/forbidden.component.html","webpack://calpine-client-portal/./src/app/shared/error/http-code-exception-button.component.html","webpack://calpine-client-portal/./src/app/shared/error/not-found.component.html","webpack://calpine-client-portal/./src/app/shared/error/unauthorized-access.component.html","webpack://calpine-client-portal/./src/app/shared/footer/footer.component.html","webpack://calpine-client-portal/./src/app/shared/grid/grid.boolean-filter.component.html","webpack://calpine-client-portal/./src/app/shared/grid/grid.date-filter.component.html","webpack://calpine-client-portal/./src/app/shared/modal/popup.component.html","webpack://calpine-client-portal/./src/app/shared/multiselect-dropdown/multiselect-dropdown.html","webpack://calpine-client-portal/./src/app/shared/nav-menu/nav-menu.component.html","webpack://calpine-client-portal/./src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.component.html","webpack://calpine-client-portal/./src/app/shared/outdated-browser/outdated-browser.component.html","webpack://calpine-client-portal/./src/app/shared/pager/pager.component.html","webpack://calpine-client-portal/./src/app/user-management/password/cancel-password-reset-request.component.html","webpack://calpine-client-portal/./src/app/user-management/password/change-password.component.html","webpack://calpine-client-portal/./src/app/user-management/password/confirm-email.component.html","webpack://calpine-client-portal/./src/app/user-management/password/confirm-password.component.html","webpack://calpine-client-portal/./src/app/user-management/password/confirmation-message.component.html","webpack://calpine-client-portal/./src/app/user-management/password/forgot-password.component.html","webpack://calpine-client-portal/./src/app/user-management/profile/user-profile-details.component.html","webpack://calpine-client-portal/./src/app/user-management/profile/user-profile.component.html","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-add-edit-dialog.component.css?1757","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-grouped-row.component.css?c1ef","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.component.css?f2d4","webpack://calpine-client-portal/./src/app/administration/users/users.component.css?c7dd","webpack://calpine-client-portal/./src/app/app.component.css?f33d","webpack://calpine-client-portal/./src/app/dynamic-scheduling/help-schedule/help-schedule.component.css?670f","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.component.css?bbfc","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.component.css?8dc5","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/dynamic-scheduling.component.css?80e0","webpack://calpine-client-portal/./src/app/home/home.component.css?546d","webpack://calpine-client-portal/./src/app/shared/breadcrumb/breadcrumb.component.css?c6b6","webpack://calpine-client-portal/./src/app/shared/datepicker/datepicker-popup.component.css?b8f4","webpack://calpine-client-portal/./src/app/shared/footer/footer.component.css?5c42","webpack://calpine-client-portal/./src/app/shared/nav-menu/nav-menu.component.css?84ce","webpack://calpine-client-portal/./src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.component.css?3490","webpack://calpine-client-portal/./src/app/shared/pager/pager.component.css?c800","webpack://calpine-client-portal/./src/app/user-management/shared/user-management.component.css?0e02","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-user-edit-delete-button.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-add-edit-dialog.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-grouped-row.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-remove-dialog.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users-roles.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.model.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/counterparty-users.service.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/send-welcome-email-dialog.component.ts","webpack://calpine-client-portal/./src/app/administration/counterparty-users/send-welcome-email-header-button.component.ts","webpack://calpine-client-portal/./src/app/administration/users/add-new-user-header-button.component.ts","webpack://calpine-client-portal/./src/app/administration/users/users-remove-dialog.component.ts","webpack://calpine-client-portal/./src/app/administration/users/users.component.ts","webpack://calpine-client-portal/./src/app/administration/users/users.service.ts","webpack://calpine-client-portal/./src/app/app.configuration.ts","webpack://calpine-client-portal/./src/app/authentication/auth-guard.service.ts","webpack://calpine-client-portal/./src/app/authentication/authentication.service.ts","webpack://calpine-client-portal/./src/app/billing/billing-account-summary.service.ts","webpack://calpine-client-portal/./src/app/billing/billing-account.model.ts","webpack://calpine-client-portal/./src/app/billing/checkbox.service.ts","webpack://calpine-client-portal/./src/app/billing/invoice-n-payment/invoice-download-error-dialog.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/he-range.ts","webpack://calpine-client-portal/./src/app/shared/app-globals.component.ts","webpack://calpine-client-portal/./src/app/shared/datepicker/datepicker-format.token.ts","webpack://calpine-client-portal/./src/app/shared/datepicker/datepicker-popup.component.ts","webpack://calpine-client-portal/./src/app/shared/datepicker/ngb-datepicker-custom-formatter.ts","webpack://calpine-client-portal/./src/app/shared/directives/tooltip.component.ts","webpack://calpine-client-portal/./src/app/shared/document-download/document-download-list.component.ts","webpack://calpine-client-portal/./src/app/shared/edit-delete-button/users-edit-delete-button.component.ts","webpack://calpine-client-portal/./src/app/shared/error/forbidden.component.ts","webpack://calpine-client-portal/./src/app/shared/error/not-found.component.ts","webpack://calpine-client-portal/./src/app/shared/error/unauthorized-access.component.ts","webpack://calpine-client-portal/./src/app/shared/grid/grid.boolean-filter.component.ts","webpack://calpine-client-portal/./src/app/shared/grid/grid.date-filter.component.ts","webpack://calpine-client-portal/./src/app/shared/grid/ag-grid.model.ts","webpack://calpine-client-portal/./src/app/shared/grid/grid.service.ts","webpack://calpine-client-portal/./src/app/shared/impersonate-button/user-impersonate-view-buttons.component.ts","webpack://calpine-client-portal/./src/app/shared/multiselect-dropdown/multiselect-dropdown.ts","webpack://calpine-client-portal/./src/app/shared/pager/pager.component.ts","webpack://calpine-client-portal/./src/app/shared/services/api-gateway.service.ts","webpack://calpine-client-portal/./src/app/shared/services/download-file.service.ts","webpack://calpine-client-portal/./src/app/shared/services/logged-in-user.service.ts","webpack://calpine-client-portal/./src/app/shared/services/user-role.service.ts","webpack://calpine-client-portal/./src/app/shared/directives/autofocus.directive.ts","webpack://calpine-client-portal/./src/app/shared/directives/fixed-element-horizontal-scroll.directive.ts","webpack://calpine-client-portal/./src/app/shared/error/http-error-handler.service.ts","webpack://calpine-client-portal/./src/app/shared/error/exception-handler.service.ts","webpack://calpine-client-portal/./src/app/shared/directives/user-role-link-check.directive.ts","webpack://calpine-client-portal/./src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.component.ts","webpack://calpine-client-portal/./src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.routing.ts","webpack://calpine-client-portal/./src/app/shared/breadcrumb/breadcrumb.component.ts","webpack://calpine-client-portal/./src/app/shared/error/http-code-exception-button.component.ts","webpack://calpine-client-portal/./src/app/shared/shared.module.ts","webpack://calpine-client-portal/./src/app/shared/typeahead/cp-typeahead.component.ts","webpack://calpine-client-portal/./src/app/authentication/id-token.component.ts","webpack://calpine-client-portal/./src/app/app.routes.ts","webpack://calpine-client-portal/./src/app/app.component.ts","webpack://calpine-client-portal/./src/app/user-management/shared/logout.model.ts","webpack://calpine-client-portal/./src/app/shared/nav-menu/nav-menu.component.ts","webpack://calpine-client-portal/./src/app/shared/footer/footer.component.ts","webpack://calpine-client-portal/./src/app/authentication/session-timeout.component.ts","webpack://calpine-client-portal/./src/app/shared/modal/popup.component.ts","webpack://calpine-client-portal/./src/app/shared/outdated-browser/outdated-browser.component.ts","webpack://calpine-client-portal/./src/app/user-management/profile/user-profile.component.ts","webpack://calpine-client-portal/./src/app/user-management/profile/user-profile-details.component.ts","webpack://calpine-client-portal/./src/app/user-management/shared/forgot-password.model.ts","webpack://calpine-client-portal/./src/app/user-management/password/forgot-password.component.ts","webpack://calpine-client-portal/./src/app/user-management/shared/account-messages.service.ts","webpack://calpine-client-portal/./src/app/user-management/shared/confirm-password.model.ts","webpack://calpine-client-portal/./src/app/user-management/password/confirm-password.component.ts","webpack://calpine-client-portal/./src/app/user-management/shared/change-password.model.ts","webpack://calpine-client-portal/./src/app/user-management/password/change-password.component.ts","webpack://calpine-client-portal/./src/app/user-management/shared/confirm-email.model.ts","webpack://calpine-client-portal/./src/app/user-management/password/confirm-email.component.ts","webpack://calpine-client-portal/./src/app/user-management/password/cancel-password-reset-request.component.ts","webpack://calpine-client-portal/./src/app/authentication/login.component.ts","webpack://calpine-client-portal/./src/app/user-management/user-management.routing.ts","webpack://calpine-client-portal/./src/app/shared/directives/equal-validator.directive.ts","webpack://calpine-client-portal/./src/app/user-management/password/confirmation-message.component.ts","webpack://calpine-client-portal/./src/app/user-management/user-management.module.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/dynamic-scheduling.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-validation.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.reducer.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.model.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-filter.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload-error-dialog.component.ts","webpack://calpine-client-portal/./src/app/shared/services/event.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-upload/schedule-upload.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/help-schedule/help-schedule.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-header.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-search-bar.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-list-table.component.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/shared/schedule-unavailable.component.ts","webpack://calpine-client-portal/./src/app/authentication/schedule-upload-guard.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/dynamic-scheduling.routing.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/dynamic-scheduling.module.ts","webpack://calpine-client-portal/./src/app/home/contact-us/contact-us.component.ts","webpack://calpine-client-portal/./src/app/home/home.component.ts","webpack://calpine-client-portal/./src/app/home/terms-conditions/terms-conditions.component.ts","webpack://calpine-client-portal/./src/app/home/home.routing.ts","webpack://calpine-client-portal/./src/app/home/home.module.ts","webpack://calpine-client-portal/./src/app/app.service.ts","webpack://calpine-client-portal/./src/app/dynamic-scheduling/schedule-archive/schedule-archive.reducer.ts","webpack://calpine-client-portal/./src/app/app.module.ts","webpack://calpine-client-portal/./src/main.ts","webpack://calpine-client-portal/webpack/bootstrap","webpack://calpine-client-portal/webpack/runtime/chunk loaded","webpack://calpine-client-portal/webpack/runtime/compat get default export","webpack://calpine-client-portal/webpack/runtime/define property getters","webpack://calpine-client-portal/webpack/runtime/ensure chunk","webpack://calpine-client-portal/webpack/runtime/get javascript chunk filename","webpack://calpine-client-portal/webpack/runtime/global","webpack://calpine-client-portal/webpack/runtime/hasOwnProperty shorthand","webpack://calpine-client-portal/webpack/runtime/load script","webpack://calpine-client-portal/webpack/runtime/make namespace object","webpack://calpine-client-portal/webpack/runtime/node module decorator","webpack://calpine-client-portal/webpack/runtime/runtimeId","webpack://calpine-client-portal/webpack/runtime/publicPath","webpack://calpine-client-portal/webpack/runtime/jsonp chunk loading","webpack://calpine-client-portal/webpack/runtime/nonce","webpack://calpine-client-portal/webpack/startup"],"sourcesContent":["// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".modal-content {\\r\\n height: 800px;\\r\\n width: 1200px;\\r\\n}\\r\\n\\r\\n.modal-dialog {\\r\\n max-width: 1200px;\\r\\n}\\r\\n\\r\\n.accordion {\\r\\n cursor: pointer;\\r\\n padding: 18px;\\r\\n width: 100%;\\r\\n border: none;\\r\\n text-align: left;\\r\\n outline: none;\\r\\n font: 16px \\\"Open Sans\\\", sans-serif;\\r\\n transition: 0.4s;\\r\\n margin: auto;\\r\\n}\\r\\n.accordion:after {\\r\\n content: '\\\\002B';\\r\\n font-weight: bold;\\r\\n float: right;\\r\\n margin-left: 5px;\\r\\n}\\r\\n.active:after {\\r\\n content: \\\"\\\\2212\\\";\\r\\n}\\r\\n.panel {\\r\\n padding: 0 18px;\\r\\n background-color: white;\\r\\n max-height: 0;\\r\\n overflow: hidden;\\r\\n transition: max-height 0.2s ease-out;\\r\\n}\\r\\nselect.form-control {\\r\\n height: 50px !important;\\r\\n}\\r\\n#user-controls input[type='checkbox'] {\\r\\n position: relative;\\r\\n left: 0px;\\r\\n visibility:visible\\r\\n}\\r\\n.disabled-impersonate {\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.row\\r\\n{\\r\\n margin-bottom: 10px;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/administration/counterparty-users/counterparty-users-add-edit-dialog.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,aAAa;IACb,aAAa;AACjB;;AAEA;IACI,iBAAiB;AACrB;;AAEA;IACI,eAAe;IACf,aAAa;IACb,WAAW;IACX,YAAY;IACZ,gBAAgB;IAChB,aAAa;IACb,kCAAkC;IAClC,gBAAgB;IAChB,YAAY;AAChB;AACA;IACI,gBAAgB;IAChB,iBAAiB;IACjB,YAAY;IACZ,gBAAgB;AACpB;AACA;IACI,gBAAgB;AACpB;AACA;IACI,eAAe;IACf,uBAAuB;IACvB,aAAa;IACb,gBAAgB;IAChB,oCAAoC;AACxC;AACA;IACI,uBAAuB;AAC3B;AACA;IACI,kBAAkB;IAClB,SAAS;IACT;AACJ;AACA;IACI,aAAa;AACjB;;AAEA;;IAEI,mBAAmB;AACvB\",\"sourcesContent\":[\".modal-content {\\r\\n height: 800px;\\r\\n width: 1200px;\\r\\n}\\r\\n\\r\\n.modal-dialog {\\r\\n max-width: 1200px;\\r\\n}\\r\\n\\r\\n.accordion {\\r\\n cursor: pointer;\\r\\n padding: 18px;\\r\\n width: 100%;\\r\\n border: none;\\r\\n text-align: left;\\r\\n outline: none;\\r\\n font: 16px \\\"Open Sans\\\", sans-serif;\\r\\n transition: 0.4s;\\r\\n margin: auto;\\r\\n}\\r\\n.accordion:after {\\r\\n content: '\\\\002B';\\r\\n font-weight: bold;\\r\\n float: right;\\r\\n margin-left: 5px;\\r\\n}\\r\\n.active:after {\\r\\n content: \\\"\\\\2212\\\";\\r\\n}\\r\\n.panel {\\r\\n padding: 0 18px;\\r\\n background-color: white;\\r\\n max-height: 0;\\r\\n overflow: hidden;\\r\\n transition: max-height 0.2s ease-out;\\r\\n}\\r\\nselect.form-control {\\r\\n height: 50px !important;\\r\\n}\\r\\n#user-controls input[type='checkbox'] {\\r\\n position: relative;\\r\\n left: 0px;\\r\\n visibility:visible\\r\\n}\\r\\n.disabled-impersonate {\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.row\\r\\n{\\r\\n margin-bottom: 10px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n.counterparty-users-row-preload-spinner {\\r\\n left: 50%;\\r\\n top: 10%;\\r\\n position: absolute;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/administration/counterparty-users/counterparty-users-grouped-row.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,YAAY;IACZ,iBAAiB;IACjB,eAAe;AACnB;AACA;IACI,SAAS;IACT,QAAQ;IACR,kBAAkB;AACtB;AACA;IACI,mBAAmB;IACnB,eAAe;AACnB\",\"sourcesContent\":[\".counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n.counterparty-users-row-preload-spinner {\\r\\n left: 50%;\\r\\n top: 10%;\\r\\n position: absolute;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".counter-party-top-row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n}\\r\\n.counter-party-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n}\\r\\n.counter-party-title-text{\\r\\n vertical-align:central;\\r\\n}\\r\\n\\r\\n.counter-party-title-Row {\\r\\n margin-top:-5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color:white;\\r\\n}\\r\\n\\r\\n.counter-party-schedule-button{\\r\\n background-color: #0088CC;\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.counterparty-padding {\\r\\n padding-top: 15px;\\r\\n padding-right: 10px;\\r\\n padding-left: 10px;\\r\\n height: 76vh;\\r\\n}\\r\\n\\r\\n.counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n\\r\\n.counter-party-column-align-center {\\r\\n padding: 4px 2px 4px 2px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n .counterparty-label {\\r\\n padding-top: 7px;\\r\\n}\\r\\n.counterparty-group{\\r\\n margin-top: 15px;\\r\\n}\\r\\n.cancel-user-add{\\r\\n color: rgb(44,174,39);\\r\\n}\\r\\n.modal-title-description{\\r\\n color: white;\\r\\n}\\r\\n.salutation-select{\\r\\n margin-top: -16px;\\r\\n}\\r\\n.salutation-select label{\\r\\n margin-bottom: 3px;\\r\\n}\\r\\n.add-user-label{\\r\\n color: rgb(117, 117, 117);\\r\\n background-color: transparent;\\r\\n}\\r\\n.validation-red{\\r\\n color: #fa005e;\\r\\n}\\r\\n.add-user-email-label{\\r\\n line-height: 25px;\\r\\n}\\r\\n.edit-salutation-select{\\r\\n margin-top: 16px;\\r\\n height: 100%;\\r\\n}\\r\\n/* Don't show the X for IE on the add-user dialog typeahead*/\\r\\ntypeahead input::-ms-clear{\\r\\n display: none;\\r\\n}\\r\\n.add-user-portal-admin{\\r\\n padding-top: 40px;\\r\\n}\\r\\n.counterparty-user-buttons{\\r\\n display: inline;\\r\\n}\\r\\n.edit-user-scroll-area{\\r\\n overflow-y: scroll;\\r\\n max-height: 600px;\\r\\n overflow-x: hidden;\\r\\n margin: -15px;\\r\\n}\\r\\n\\r\\n.cp-user-grid-size{\\r\\n width: 100%;\\r\\n height: 85%;\\r\\n}\\r\\n\\r\\n.welcome-email-header-button{\\r\\n height: 94%;\\r\\n margin-top: 2px;\\r\\n margin-left: -6px;\\r\\n background-color: #0088CC;\\r\\n color: #ffffff;\\r\\n text-align: center; \\r\\n border-width: 0px; \\r\\n}\\r\\n\\r\\n.counter-party-footer-overlap{\\r\\n height:780px;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span {\\r\\n display: inline-block;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span.ag-group-value {\\r\\n width: 98%;\\r\\n margin-top: 5px;\\r\\n}\\r\\n\\r\\n.counterparty-users-preload-spinner {\\r\\n left: 47%;\\r\\n height: 50px;\\r\\n position: absolute;\\r\\n top: 100px;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/administration/counterparty-users/counterparty-users.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,gBAAgB;IAChB,mCAAmC;AACvC;AACA;IACI,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;AACjB;AACA;IACI,sBAAsB;AAC1B;;AAEA;IACI,eAAe;IACf,mCAAmC;IACnC,sBAAsB;AAC1B;;AAEA;IACI,yBAAyB;IACzB,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,iBAAiB;AACrB;;AAEA;IACI,iBAAiB;IACjB,mBAAmB;IACnB,kBAAkB;IAClB,YAAY;AAChB;;AAEA;IACI,YAAY;IACZ,iBAAiB;IACjB,eAAe;AACnB;;AAEA;IACI,wBAAwB;IACxB,iBAAiB;AACrB;;CAEC;IACG,gBAAgB;AACpB;AACA;IACI,gBAAgB;AACpB;AACA;IACI,qBAAqB;AACzB;AACA;IACI,YAAY;AAChB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,kBAAkB;AACtB;AACA;IACI,yBAAyB;IACzB,6BAA6B;AACjC;AACA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;IAChB,YAAY;AAChB;AACA,4DAA4D;AAC5D;IACI,aAAa;AACjB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,eAAe;AACnB;AACA;IACI,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;IAClB,aAAa;AACjB;;AAEA;IACI,WAAW;IACX,WAAW;AACf;;AAEA;IACI,WAAW;IACX,eAAe;IACf,iBAAiB;IACjB,yBAAyB;IACzB,cAAc;IACd,kBAAkB;IAClB,iBAAiB;AACrB;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,qBAAqB;AACzB;;AAEA;IACI,UAAU;IACV,eAAe;AACnB;;AAEA;IACI,SAAS;IACT,YAAY;IACZ,kBAAkB;IAClB,UAAU;AACd;AACA;IACI,mBAAmB;IACnB,eAAe;AACnB\",\"sourcesContent\":[\".counter-party-top-row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n}\\r\\n.counter-party-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n}\\r\\n.counter-party-title-text{\\r\\n vertical-align:central;\\r\\n}\\r\\n\\r\\n.counter-party-title-Row {\\r\\n margin-top:-5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color:white;\\r\\n}\\r\\n\\r\\n.counter-party-schedule-button{\\r\\n background-color: #0088CC;\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.counterparty-padding {\\r\\n padding-top: 15px;\\r\\n padding-right: 10px;\\r\\n padding-left: 10px;\\r\\n height: 76vh;\\r\\n}\\r\\n\\r\\n.counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n\\r\\n.counter-party-column-align-center {\\r\\n padding: 4px 2px 4px 2px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n .counterparty-label {\\r\\n padding-top: 7px;\\r\\n}\\r\\n.counterparty-group{\\r\\n margin-top: 15px;\\r\\n}\\r\\n.cancel-user-add{\\r\\n color: rgb(44,174,39);\\r\\n}\\r\\n.modal-title-description{\\r\\n color: white;\\r\\n}\\r\\n.salutation-select{\\r\\n margin-top: -16px;\\r\\n}\\r\\n.salutation-select label{\\r\\n margin-bottom: 3px;\\r\\n}\\r\\n.add-user-label{\\r\\n color: rgb(117, 117, 117);\\r\\n background-color: transparent;\\r\\n}\\r\\n.validation-red{\\r\\n color: #fa005e;\\r\\n}\\r\\n.add-user-email-label{\\r\\n line-height: 25px;\\r\\n}\\r\\n.edit-salutation-select{\\r\\n margin-top: 16px;\\r\\n height: 100%;\\r\\n}\\r\\n/* Don't show the X for IE on the add-user dialog typeahead*/\\r\\ntypeahead input::-ms-clear{\\r\\n display: none;\\r\\n}\\r\\n.add-user-portal-admin{\\r\\n padding-top: 40px;\\r\\n}\\r\\n.counterparty-user-buttons{\\r\\n display: inline;\\r\\n}\\r\\n.edit-user-scroll-area{\\r\\n overflow-y: scroll;\\r\\n max-height: 600px;\\r\\n overflow-x: hidden;\\r\\n margin: -15px;\\r\\n}\\r\\n\\r\\n.cp-user-grid-size{\\r\\n width: 100%;\\r\\n height: 85%;\\r\\n}\\r\\n\\r\\n.welcome-email-header-button{\\r\\n height: 94%;\\r\\n margin-top: 2px;\\r\\n margin-left: -6px;\\r\\n background-color: #0088CC;\\r\\n color: #ffffff;\\r\\n text-align: center; \\r\\n border-width: 0px; \\r\\n}\\r\\n\\r\\n.counter-party-footer-overlap{\\r\\n height:780px;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span {\\r\\n display: inline-block;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span.ag-group-value {\\r\\n width: 98%;\\r\\n margin-top: 5px;\\r\\n}\\r\\n\\r\\n.counterparty-users-preload-spinner {\\r\\n left: 47%;\\r\\n height: 50px;\\r\\n position: absolute;\\r\\n top: 100px;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".counter-party-top-row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n}\\r\\n.counter-party-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n.counter-party-title-text{\\r\\n vertical-align:central;\\r\\n}\\r\\n\\r\\n.counter-party-title-Row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color: white;\\r\\n}\\r\\n\\r\\n.counter-party-schedule-button{\\r\\n background-color: #0088CC;\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n padding-top: 15px;\\r\\n}\\r\\n\\r\\n.users-padding {\\r\\n padding-top: 15px;\\r\\n padding-right: 10px;\\r\\n padding-left: 10px;\\r\\n height: 76vh;\\r\\n}\\r\\n\\r\\n.counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n\\r\\n.counter-party-column-align-center {\\r\\n padding: 4px 2px 4px 2px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n .counterparty-label {\\r\\n padding-top: 7px;\\r\\n}\\r\\n.counterparty-group{\\r\\n margin-top: 15px;\\r\\n}\\r\\n.cancel-user-add{\\r\\n color: rgb(44,174,39);\\r\\n}\\r\\n.modal-title-description{\\r\\n color: white;\\r\\n}\\r\\n.salutation-select{\\r\\n margin-top: -16px;\\r\\n}\\r\\n.salutation-select label{\\r\\n margin-bottom: 3px;\\r\\n}\\r\\n.add-user-label{\\r\\n color: rgb(117, 117, 117);\\r\\n background-color: transparent;\\r\\n}\\r\\n.validation-red{\\r\\n color: #fa005e;\\r\\n}\\r\\n.add-user-email-label{\\r\\n line-height: 25px;\\r\\n}\\r\\n.edit-salutation-select{\\r\\n margin-top: 16px;\\r\\n}\\r\\n/* Don't show the X for IE on the add-user dialog typeahead*/\\r\\ntypeahead input::-ms-clear{\\r\\n display: none;\\r\\n}\\r\\n.add-user-portal-admin{\\r\\n padding-top: 40px;\\r\\n}\\r\\n.counterparty-user-buttons{\\r\\n display: inline;\\r\\n}\\r\\n.edit-user-scroll-area{\\r\\n overflow-y: scroll;\\r\\n max-height: 600px;\\r\\n overflow-x: hidden;\\r\\n margin: -15px;\\r\\n}\\r\\n\\r\\n.cp-user-grid-size{\\r\\n width: 100%;\\r\\n height: 94%;\\r\\n}\\r\\n\\r\\n.welcome-email-header-button{\\r\\n height: 94%;\\r\\n margin-top: 2px;\\r\\n margin-left: -6px;\\r\\n background-color: #0088CC;\\r\\n color: #ffffff;\\r\\n text-align: center; \\r\\n border-width: 0px; \\r\\n}\\r\\n\\r\\n.counter-party-footer-overlap{\\r\\n height:700px;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span {\\r\\n display: inline-block;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span.ag-group-value {\\r\\n width: 98%;\\r\\n margin-top: 5px;\\r\\n}\\r\\n\\r\\n.counterparty-users-preload-spinner {\\r\\n left: 47%;\\r\\n height: 50px;\\r\\n position: absolute;\\r\\n top: 100px;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/administration/users/users.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,gBAAgB;IAChB,mCAAmC;AACvC;AACA;IACI,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;IACb,kBAAkB;AACtB;AACA;IACI,sBAAsB;AAC1B;;AAEA;IACI,gBAAgB;IAChB,mCAAmC;IACnC,uBAAuB;AAC3B;;AAEA;IACI,yBAAyB;IACzB,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,iBAAiB;IACjB,iBAAiB;AACrB;;AAEA;IACI,iBAAiB;IACjB,mBAAmB;IACnB,kBAAkB;IAClB,YAAY;AAChB;;AAEA;IACI,YAAY;IACZ,iBAAiB;IACjB,eAAe;AACnB;;AAEA;IACI,wBAAwB;IACxB,iBAAiB;AACrB;;CAEC;IACG,gBAAgB;AACpB;AACA;IACI,gBAAgB;AACpB;AACA;IACI,qBAAqB;AACzB;AACA;IACI,YAAY;AAChB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,kBAAkB;AACtB;AACA;IACI,yBAAyB;IACzB,6BAA6B;AACjC;AACA;IACI,cAAc;AAClB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;AACpB;AACA,4DAA4D;AAC5D;IACI,aAAa;AACjB;AACA;IACI,iBAAiB;AACrB;AACA;IACI,eAAe;AACnB;AACA;IACI,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;IAClB,aAAa;AACjB;;AAEA;IACI,WAAW;IACX,WAAW;AACf;;AAEA;IACI,WAAW;IACX,eAAe;IACf,iBAAiB;IACjB,yBAAyB;IACzB,cAAc;IACd,kBAAkB;IAClB,iBAAiB;AACrB;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,qBAAqB;AACzB;;AAEA;IACI,UAAU;IACV,eAAe;AACnB;;AAEA;IACI,SAAS;IACT,YAAY;IACZ,kBAAkB;IAClB,UAAU;AACd;AACA;IACI,mBAAmB;IACnB,eAAe;AACnB\",\"sourcesContent\":[\".counter-party-top-row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n}\\r\\n.counter-party-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n.counter-party-title-text{\\r\\n vertical-align:central;\\r\\n}\\r\\n\\r\\n.counter-party-title-Row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color: white;\\r\\n}\\r\\n\\r\\n.counter-party-schedule-button{\\r\\n background-color: #0088CC;\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n padding-top: 15px;\\r\\n}\\r\\n\\r\\n.users-padding {\\r\\n padding-top: 15px;\\r\\n padding-right: 10px;\\r\\n padding-left: 10px;\\r\\n height: 76vh;\\r\\n}\\r\\n\\r\\n.counterparty-row-text {\\r\\n float: right;\\r\\n margin-left: 10px;\\r\\n margin-top: 8px;\\r\\n}\\r\\n\\r\\n.counter-party-column-align-center {\\r\\n padding: 4px 2px 4px 2px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n .counterparty-label {\\r\\n padding-top: 7px;\\r\\n}\\r\\n.counterparty-group{\\r\\n margin-top: 15px;\\r\\n}\\r\\n.cancel-user-add{\\r\\n color: rgb(44,174,39);\\r\\n}\\r\\n.modal-title-description{\\r\\n color: white;\\r\\n}\\r\\n.salutation-select{\\r\\n margin-top: -16px;\\r\\n}\\r\\n.salutation-select label{\\r\\n margin-bottom: 3px;\\r\\n}\\r\\n.add-user-label{\\r\\n color: rgb(117, 117, 117);\\r\\n background-color: transparent;\\r\\n}\\r\\n.validation-red{\\r\\n color: #fa005e;\\r\\n}\\r\\n.add-user-email-label{\\r\\n line-height: 25px;\\r\\n}\\r\\n.edit-salutation-select{\\r\\n margin-top: 16px;\\r\\n}\\r\\n/* Don't show the X for IE on the add-user dialog typeahead*/\\r\\ntypeahead input::-ms-clear{\\r\\n display: none;\\r\\n}\\r\\n.add-user-portal-admin{\\r\\n padding-top: 40px;\\r\\n}\\r\\n.counterparty-user-buttons{\\r\\n display: inline;\\r\\n}\\r\\n.edit-user-scroll-area{\\r\\n overflow-y: scroll;\\r\\n max-height: 600px;\\r\\n overflow-x: hidden;\\r\\n margin: -15px;\\r\\n}\\r\\n\\r\\n.cp-user-grid-size{\\r\\n width: 100%;\\r\\n height: 94%;\\r\\n}\\r\\n\\r\\n.welcome-email-header-button{\\r\\n height: 94%;\\r\\n margin-top: 2px;\\r\\n margin-left: -6px;\\r\\n background-color: #0088CC;\\r\\n color: #ffffff;\\r\\n text-align: center; \\r\\n border-width: 0px; \\r\\n}\\r\\n\\r\\n.counter-party-footer-overlap{\\r\\n height:700px;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span {\\r\\n display: inline-block;\\r\\n}\\r\\n\\r\\n.ag-row-group-indent-0 span.ag-group-value {\\r\\n width: 98%;\\r\\n margin-top: 5px;\\r\\n}\\r\\n\\r\\n.counterparty-users-preload-spinner {\\r\\n left: 47%;\\r\\n height: 50px;\\r\\n position: absolute;\\r\\n top: 100px;\\r\\n}\\r\\ninput.counterparty-checkbox[type=checkbox] {\\r\\n visibility: visible;\\r\\n position: unset;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/api.js\";\nimport ___CSS_LOADER_GET_URL_IMPORT___ from \"../../node_modules/css-loader/dist/runtime/getUrl.js\";\nimport ___CSS_LOADER_URL_IMPORT_0___ from \"../assets/nes_bg.jpg\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(//fonts.googleapis.com/css?family=Open+Sans);\"]);\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(//fonts.googleapis.com/css?family=Open+Sans:300);\"]);\n___CSS_LOADER_EXPORT___.push([module.id, \"@import url(//fonts.googleapis.com/css?family=Oswald);\"]);\nvar ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/* Shared CSS Accross site*/\\r\\nselect {\\r\\n /* Override MDB display none */\\r\\n display: unset;\\r\\n}\\r\\n.word-break-break-all{\\r\\n word-break: break-all;\\r\\n}\\r\\n.margin-horizontal-none{\\r\\n margin-left: 0px;\\r\\n margin-right: 0px;\\r\\n}\\r\\n.margin-vertical-none{\\r\\n margin-top: 0;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.margin-bottom-none{\\r\\n margin-bottom: 0 !important;\\r\\n}\\r\\n.horizontal-padding-none{\\r\\n padding-right: 0 !important;\\r\\n padding-left: 0 !important;\\r\\n}\\r\\n.vertical-padding-none{\\r\\n padding-top: 0 !important;\\r\\n padding-bottom: 0 !important;\\r\\n}\\r\\n.padding-none{\\r\\n padding: 0 !important;\\r\\n}\\r\\n.margin-none{\\r\\n margin: 0 !important;\\r\\n}\\r\\n.margin-bottom-lg{\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n.margin-right-lg{\\r\\n margin-right: 10px !important;\\r\\n}\\r\\n.vertical-align-bottom\\r\\n.inline-block {\\r\\n display: inline-block;\\r\\n}\\r\\n.display-inline{\\r\\n display: inline;\\r\\n}\\r\\n.hidden{\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.all-caps{\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n/* apply this to a wrapper div. Probably want full-height as well */\\r\\n.vertical-align-bottom {\\r\\n position: relative;\\r\\n}\\r\\n.vertical-align-bottom::before {\\r\\n content: \\\" \\\";\\r\\n display: inline-block;\\r\\n height: 100%;\\r\\n width: 1%;\\r\\n vertical-align: bottom;\\r\\n}\\r\\n.vertical-align-bottom * {\\r\\n display: inline-block;\\r\\n vertical-align: bottom;\\r\\n}\\r\\n.vertical-align-middle{\\r\\n vertical-align: middle;\\r\\n}\\r\\n\\r\\n.full-height {\\r\\n height: 100%;\\r\\n}\\r\\n.full-width {\\r\\n width: 100%;\\r\\n}\\r\\n.text-center {\\r\\n text-align: center;\\r\\n}\\r\\n.text-italic {\\r\\n font-style: italic;\\r\\n}\\r\\n.text-bold {\\r\\n font-weight: 700;\\r\\n}\\r\\n.text-light-grey {\\r\\n color: #b2b4b8;\\r\\n}\\r\\n.text-uppercase {\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n.text-small {\\r\\n font-size: .8rem;\\r\\n}\\r\\n\\r\\n.clickable{\\r\\n cursor: pointer;\\r\\n}\\r\\n.not-clickable{\\r\\n cursor: default !important;\\r\\n}\\r\\n.btn-transparent{\\r\\n background-color: transparent;\\r\\n box-shadow: none;\\r\\n}\\r\\n.btn-concrete{\\r\\n background-color:#F2F2F2 ;\\r\\n}\\r\\n\\r\\n/* App component styling */\\r\\nhtml {\\r\\n height: 100%;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n*,\\r\\n*:before,\\r\\n*:after {\\r\\n box-sizing: inherit;\\r\\n}\\r\\n\\r\\n\\r\\nbody {\\r\\n position: relative;\\r\\n margin: 0;\\r\\n min-height: 100%;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color:#3F474D;\\r\\n background-color:#F2F2F2; \\r\\n}\\r\\n.hide-scrollbar {\\r\\n overflow-y: hidden; /* Hide vertical scrollbar */\\r\\n}\\r\\n.hide-scrollbar::-webkit-scrollbar {\\r\\n display: none;\\r\\n}\\r\\n.add-scrollbar {\\r\\n overflow: scroll;\\r\\n}\\r\\n.app-container {\\r\\n margin: 0 auto;\\r\\n padding-top: 127px;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n min-height: 100vh;\\r\\n}\\r\\n\\r\\n.app-container-all-but-home {\\r\\n margin: 0 auto;\\r\\n padding-top: 127px;\\r\\n min-height: 100vh;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n.app-container-for-home {\\r\\n margin: 0 auto;\\r\\n padding-top: 82px;\\r\\n min-height: 100vh;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n/**\\r\\n * Footer Styles\\r\\n */\\r\\n\\r\\nfooter-component {\\r\\n position: relative;\\r\\n right: 0;\\r\\n bottom: 0;\\r\\n left: 0;\\r\\n}\\r\\n\\r\\nfooter.page-footer {\\r\\n padding-top: 20px;\\r\\n background-color: #1a1a1a;\\r\\n color: #B0ACA6;\\r\\n font-size: 12px;\\r\\n margin-top: -75px; /* negative value of footer height */\\r\\n height: 75px;\\r\\n clear: both;\\r\\n}\\r\\n\\r\\nfooter.page-footer a{\\r\\n color: #B0ACA6;\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\nfooter.page-footer img {\\r\\n height: 40px;\\r\\n}\\r\\n\\r\\n.nes-footer-logo{\\r\\n opacity: .25;\\r\\n}\\r\\n/* Modal dialog\\r\\n*/\\r\\n.modal-top{\\r\\n padding-top: 10%;\\r\\n}\\r\\n\\r\\n.modal-header {\\r\\n padding:9px 15px;\\r\\n border-bottom:1px solid #eee;\\r\\n background-color: #0099CC; \\r\\n }\\r\\n\\r\\n.modal-title{\\r\\n font-weight: bold\\r\\n}\\r\\n\\r\\n/* to set equal height of div row containing different height child rows/divs*/\\r\\n.row-eq-height {\\r\\n display: -webkit-box;\\r\\n display: -webkit-flex;\\r\\n display: -ms-flexbox;\\r\\n display: flex;\\r\\n}\\r\\n\\r\\n.height-30px{\\r\\n height: 30px;\\r\\n}\\r\\n\\r\\n.body-background-image {\\r\\n /* Location of the image */\\r\\n background-image: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \");\\r\\n /* Background image is centered vertically and horizontally at all times */\\r\\n background-position: center center;\\r\\n /* Background image doesn't tile */\\r\\n background-repeat: no-repeat;\\r\\n /* Background image is fixed in the viewport so that it doesn't move when \\r\\n the content's height is greater than the image's height */\\r\\n background-attachment: fixed;\\r\\n /* This is what makes the background image rescale based on the container's size */\\r\\n background-size: cover;\\r\\n /* Set a background color that will be displayed while the background image is loading */\\r\\n background-color: #464646;\\r\\n}\\r\\n\\r\\n.nes-logo {\\r\\n height:50px;\\r\\n width:50px;\\r\\n}\\r\\n\\r\\n.div-box-shadow{\\r\\n box-shadow: 5px 5px 2px #dddddd;\\r\\n}\\r\\n\\r\\n.have-questions-box {\\r\\n background-color:#F9F9F9;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em; \\r\\n}\\r\\n\\r\\n\\r\\n/* Colors */\\r\\n.bg-color-light-gray-1{\\r\\n background-color:#F9F9F9;\\r\\n}\\r\\n\\r\\n.bg-color-light-gray-2{\\r\\n background-color:#F2F2F2;\\r\\n}\\r\\n\\r\\n.bg-color-dark-gray-1{\\r\\n background-color:#585961;\\r\\n}\\r\\n.bg-color-dark-gray-2{\\r\\n background-color:#3F474D;\\r\\n}\\r\\n.bg-color-blue{\\r\\n background-color:#00AEEF;\\r\\n}\\r\\n.text-medium-gray{\\r\\n color:#939BA1;\\r\\n}\\r\\n\\r\\n.text-dark-gray{\\r\\n color:#5E5F67;\\r\\n}\\r\\n.text-medium-green{\\r\\n color: #70AD47;\\r\\n}\\r\\n.text-light-green{\\r\\n color: #B4D88B;\\r\\n}\\r\\n.text-blue{\\r\\n color:#00AEEF !important;\\r\\n}\\r\\n.text-orange{\\r\\n color:#E95713;\\r\\n}\\r\\n.text-red{\\r\\n color:#fa005e;\\r\\n}\\r\\n.loading-indicator {\\r\\n position: absolute;\\r\\n width: 100%;\\r\\n /*height: 100%;*/\\r\\n background: white;\\r\\n top:0%;\\r\\n left:0%;\\r\\n}\\r\\n.loading-indicator .fa-refresh:before {\\r\\n color: blue;\\r\\n}\\r\\n\\r\\n\\r\\n/*////////////////\\r\\n///// Buttons ///\\r\\n//////////////*/\\r\\n.button-green{\\r\\n background: #B4D88B;\\r\\n padding: 8.5px 17px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 12px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n border-color: transparent;\\r\\n }\\r\\n.button-green:hover {\\r\\n background: #CEE1B8;\\r\\n color: #fff;\\r\\n }\\r\\n.button-green:active {\\r\\n background: #DAE6CB;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.button-red{\\r\\n background: #EE1849;\\r\\n padding: 8.5px 22px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 12px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n border-color: transparent;\\r\\n }\\r\\n.button-red:hover {\\r\\n background: #E85073;\\r\\n color: #fff;\\r\\n }\\r\\n.button-red:active {\\r\\n background: #E89CAE;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n\\r\\n.reset-button, .reset-button:hover{\\r\\n background-color: #F2F2F2;\\r\\n color: #3F474D !important; \\r\\n}\\r\\n\\r\\n/* Typography */\\r\\n\\r\\n.font-heading{\\r\\n font-size:24px;\\r\\n font-weight:bold;\\r\\n line-height: 1;\\r\\n color: #3F474D;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-titlebar{\\r\\n font-size:20px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color: #5E5F67;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-subheading{\\r\\n font-size:16px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color: #585961;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-body{\\r\\n font-size: 14px;\\r\\n font-weight:normal;\\r\\n color:#3F474D;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-caption{\\r\\n font-size:12px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color:#585961;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n/* Exception Pages */\\r\\n.ButtonNav {\\r\\n background: #939BA1;\\r\\n padding: 16px 80px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 16px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n }\\r\\n \\r\\n.ButtonNav:hover {\\r\\n background: #A4A6A8;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.ButtonNav:active {\\r\\n background: #B3B3B3;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.exception-page-btn-home-width {\\r\\n padding: 16px 118px;\\r\\n}\\r\\n\\r\\n.color-white{\\r\\n color: #ffffff !important;\\r\\n}\\r\\n\\r\\n.exception-page-http-code{\\r\\n font-size: 48px;\\r\\n font-weight: 700;\\r\\n font-style: normal;\\r\\n padding-bottom: 12px;\\r\\n}\\r\\n\\r\\n.exception-page-http-message{\\r\\n font-weight: bold;\\r\\n font-style: normal;\\r\\n}\\r\\n\\r\\n.exception-page-button-row-spacing{\\r\\n margin-top:15px;\\r\\n}\\r\\n\\r\\n@media (min-width: 1280px) {\\r\\n .exception-page-white-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 40%;\\r\\n position: fixed;\\r\\n top: 48%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n }\\r\\n}\\r\\n\\r\\n/*Calpine style typography \\r\\n https://app.frontify.com/d/c7zJIyYFDWm5/ces-portal-style-guide#/basics/typography */\\r\\n\\r\\n.calpine-paragraph-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n}\\r\\n\\r\\n.calpine-paragraph-bold-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.calpine-paragraph-link-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #006699;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n text-decoration: underline;\\r\\n}\\r\\n\\r\\n.calpine-heading-h2-text{\\r\\n font-family: 'Oswald', sans-serif;\\r\\n font-size: 34px;\\r\\n color: #006699;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 1.3;\\r\\n font-weight: 400;\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n.calpine-heading-h6-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 16px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 1.6;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n/*Calpine style typography */\\r\\n\\r\\na:link {\\r\\n color: #006699;\\r\\n}\\r\\n\\r\\n.calpine-limeade {\\r\\n color: #5AAD00;\\r\\n}\\r\\n\\r\\n.calpine-allports {\\r\\n color: #006699;\\r\\n}\\r\\n\\r\\n.calpine-lochmara {\\r\\n color: #0088CC;\\r\\n}\\r\\n\\r\\n.calpine-background-lochmara {\\r\\n background-color: #0088CC;\\r\\n}\\r\\n\\r\\n/*ag-grid*/\\r\\n.ag-filter select {\\r\\n display: inline;\\r\\n}\\r\\n.ag-filter input[type=text] {\\r\\n width: 170px;\\r\\n margin: 6px 4px 4px 4px;\\r\\n height: 1.1rem;\\r\\n}\\r\\n.ag-header-cell-label {\\r\\n white-space: normal;\\r\\n}\\r\\n.ag-filter [type=\\\"checkbox\\\"]:not(:checked),\\r\\n.ag-filter [type=\\\"checkbox\\\"]:checked {\\r\\n position: relative;\\r\\n left: 0px;\\r\\n visibility: visible;\\r\\n margin-left: 5px;\\r\\n}\\r\\n\\r\\n.ag-virtual-list-container {\\r\\n overflow: visible;\\r\\n}\\r\\n.ag-set-filter-item {\\r\\n padding-right: 10px;\\r\\n}\\r\\n\\r\\n.ag-filter-apply-panel {\\r\\n display: flex;\\r\\n justify-content: space-between; /* Pushes 'Clear' to the left and 'Apply' to the right */\\r\\n gap: 12px; /* Adds clean spacing if they wrap */\\r\\n padding: 10px 12px; /* Adds padding inside the container base */\\r\\n border-top: 1px solid #e2e8f0; /* Optional: Adds a subtle separator line above buttons */\\r\\n}\\r\\n\\r\\n/* Style BOTH buttons globally */\\r\\n.ag-standard-button {\\r\\n font-family: inherit;\\r\\n font-size: 13px;\\r\\n font-weight: 500;\\r\\n padding: 6px 16px;\\r\\n border-radius: 4px;\\r\\n cursor: pointer;\\r\\n transition: all 0.2s ease;\\r\\n border: 1px solid transparent;\\r\\n}\\r\\n\\r\\n/* Preload spinner like signup*/\\r\\n.preload-spinner {\\r\\n border: 8px solid #818285;\\r\\n border-radius: 50%;\\r\\n border-top: 8px solid #0088CC;\\r\\n width: 50px;\\r\\n height: 50px;\\r\\n -webkit-animation: spin 1s linear infinite;\\r\\n animation: spin 1s linear infinite;\\r\\n box-sizing: content-box !important;\\r\\n}\\r\\n@-webkit-keyframes spin {\\r\\n 0% {\\r\\n -webkit-transform: rotate(0deg);\\r\\n }\\r\\n\\r\\n 100% {\\r\\n -webkit-transform: rotate(360deg);\\r\\n }\\r\\n}\\r\\n\\r\\n@keyframes spin {\\r\\n 0% {\\r\\n transform: rotate(0deg);\\r\\n }\\r\\n\\r\\n 100% {\\r\\n transform: rotate(360deg);\\r\\n }\\r\\n}\\r\\n\\r\\n.grid-size {\\r\\n width: 98%;\\r\\n height: 85%;\\r\\n}\\r\\n\\r\\n#ui-datepicker-div select {\\r\\n display: inline;\\r\\n}\\r\\n\\r\\n.ag-header-active {\\r\\n background-color: transparent !important;\\r\\n}\\r\\n\\r\\n.ag-header-icon {\\r\\n color: white !important;\\r\\n}\\r\\n/******************/\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/app.component.css\"],\"names\":[],\"mappings\":\"AAIA,2BAA2B;AAC3B;IACI,8BAA8B;IAC9B,cAAc;AAClB;AACA;IACI,qBAAqB;AACzB;AACA;IACI,gBAAgB;IAChB,iBAAiB;AACrB;AACA;IACI,aAAa;IACb,gBAAgB;AACpB;AACA;IACI,2BAA2B;AAC/B;AACA;IACI,2BAA2B;IAC3B,0BAA0B;AAC9B;AACA;IACI,yBAAyB;IACzB,4BAA4B;AAChC;AACA;IACI,qBAAqB;AACzB;AACA;IACI,oBAAoB;AACxB;AACA;IACI,mBAAmB;AACvB;AACA;IACI,6BAA6B;AACjC;AACA;;IAEI,qBAAqB;AACzB;AACA;IACI,eAAe;AACnB;AACA;IACI,aAAa;AACjB;;AAEA;IACI,yBAAyB;AAC7B;;AAEA,mEAAmE;AACnE;EACE,kBAAkB;AACpB;AACA;EACE,YAAY;EACZ,qBAAqB;EACrB,YAAY;EACZ,SAAS;EACT,sBAAsB;AACxB;AACA;EACE,qBAAqB;EACrB,sBAAsB;AACxB;AACA;IACI,sBAAsB;AAC1B;;AAEA;IACI,YAAY;AAChB;AACA;IACI,WAAW;AACf;AACA;IACI,kBAAkB;AACtB;AACA;IACI,kBAAkB;AACtB;AACA;IACI,gBAAgB;AACpB;AACA;IACI,cAAc;AAClB;AACA;IACI,yBAAyB;AAC7B;;AAEA;IACI,gBAAgB;AACpB;;AAEA;IACI,eAAe;AACnB;AACA;IACI,0BAA0B;AAC9B;AACA;IACI,6BAA6B;IAC7B,gBAAgB;AACpB;AACA;IACI,yBAAyB;AAC7B;;AAEA,0BAA0B;AAC1B;EACE,YAAY;EACZ,sBAAsB;AACxB;;AAEA;;;EAGE,mBAAmB;AACrB;;;AAGA;IACI,kBAAkB;IAClB,SAAS;IACT,gBAAgB;IAChB,oCAAoC;IACpC,eAAe;IACf,aAAa;IACb,wBAAwB;AAC5B;AACA;IACI,kBAAkB,EAAE,4BAA4B;AACpD;AACA;IACI,aAAa;AACjB;AACA;IACI,gBAAgB;AACpB;AACA;IACI,cAAc;IACd,kBAAkB;IAClB,oBAAoB,EAAE,oGAAoG;IAC1H,kBAAkB;IAClB,iBAAiB;AACrB;;AAEA;EACE,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,oBAAoB,EAAE,oGAAoG;EAC1H,kBAAkB;AACpB;;AAEA;EACE,cAAc;EACd,iBAAiB;EACjB,iBAAiB;EACjB,oBAAoB,EAAE,oGAAoG;EAC1H,kBAAkB;AACpB;;AAEA;;EAEE;;AAEF;EACE,kBAAkB;EAClB,QAAQ;EACR,SAAS;EACT,OAAO;AACT;;AAEA;IACI,iBAAiB;IACjB,yBAAyB;IACzB,cAAc;IACd,eAAe;IACf,iBAAiB,EAAE,oCAAoC;IACvD,YAAY;IACZ,WAAW;AACf;;AAEA;IACI,cAAc;IACd,eAAe;AACnB;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,YAAY;AAChB;AACA;CACC;AACD;IACI,gBAAgB;AACpB;;AAEA;IACI,gBAAgB;IAChB,4BAA4B;IAC5B,yBAAyB;CAC5B;;AAED;IACI;AACJ;;AAEA,8EAA8E;AAC9E;EACE,oBAAoB;EACpB,qBAAqB;EACrB,oBAAoB;EACpB,aAAa;AACf;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,0BAA0B;IAC1B,yDAA2C;IAC3C,0EAA0E;IAC1E,kCAAkC;IAClC,kCAAkC;IAClC,4BAA4B;IAC5B;8DAC0D;IAC1D,4BAA4B;EAC9B,kFAAkF;IAChF,sBAAsB;EACxB,wFAAwF;IACtF,yBAAyB;AAC7B;;AAEA;IACI,WAAW;IACX,UAAU;AACd;;AAEA;IACI,+BAA+B;AACnC;;AAEA;IACI,wBAAwB;IACxB,eAAe;IACf,kBAAkB;AACtB;;;AAGA,WAAW;AACX;IACI,wBAAwB;AAC5B;;AAEA;IACI,wBAAwB;AAC5B;;AAEA;IACI,wBAAwB;AAC5B;AACA;IACI,wBAAwB;AAC5B;AACA;IACI,wBAAwB;AAC5B;AACA;CACC,aAAa;AACd;;AAEA;IACI,aAAa;AACjB;AACA;IACI,cAAc;AAClB;AACA;IACI,cAAc;AAClB;AACA;IACI,wBAAwB;AAC5B;AACA;IACI,aAAa;AACjB;AACA;IACI,aAAa;AACjB;AACA;EACE,kBAAkB;EAClB,WAAW;EACX,gBAAgB;EAChB,iBAAiB;EACjB,MAAM;EACN,OAAO;AACT;AACA;IACI,WAAW;AACf;;;AAGA;;eAEe;AACf;GACG,mBAAmB;GACnB,mBAAmB;GACnB,kBAAkB;GAClB,cAAc;GACd,eAAe;GACf,kCAAkC;GAClC,qBAAqB;GACrB,sBAAsB;GACtB,yBAAyB;GACzB;AACH;GACG,mBAAmB;GACnB,WAAW;GACX;AACH;GACG,mBAAmB;GACnB,WAAW;GACX;;AAEH;GACG,mBAAmB;GACnB,mBAAmB;GACnB,kBAAkB;GAClB,cAAc;GACd,eAAe;GACf,kCAAkC;GAClC,qBAAqB;GACrB,sBAAsB;GACtB,yBAAyB;GACzB;AACH;GACG,mBAAmB;GACnB,WAAW;GACX;AACH;GACG,mBAAmB;GACnB,WAAW;GACX;;;AAGH;IACI,yBAAyB;IACzB,yBAAyB;AAC7B;;AAEA,eAAe;;AAEf;IACI,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,oCAAoC;AACxC;;AAEA;IACI,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,cAAc;IACd,oCAAoC;AACxC;;AAEA;IACI,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,cAAc;IACd,oCAAoC;AACxC;;AAEA;IACI,eAAe;IACf,kBAAkB;IAClB,aAAa;IACb,oCAAoC;AACxC;;AAEA;IACI,cAAc;IACd,kBAAkB;IAClB,cAAc;IACd,aAAa;IACb,oCAAoC;AACxC;;AAEA,oBAAoB;AACpB;GACG,mBAAmB;GACnB,kBAAkB;GAClB,kBAAkB;GAClB,cAAc;GACd,eAAe;GACf,kCAAkC;GAClC,qBAAqB;GACrB,sBAAsB;GACtB;;AAEH;GACG,mBAAmB;GACnB,WAAW;GACX;;AAEH;GACG,mBAAmB;GACnB,WAAW;GACX;;AAEH;IACI,mBAAmB;AACvB;;AAEA;IACI,yBAAyB;AAC7B;;AAEA;IACI,eAAe;IACf,gBAAgB;IAChB,kBAAkB;IAClB,oBAAoB;AACxB;;AAEA;IACI,iBAAiB;IACjB,kBAAkB;AACtB;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI;QACI,eAAe;QACf,qBAAqB;QACrB,kBAAkB;QAClB,wBAAwB;QACxB,kBAAkB;QAClB,UAAU;QACV,eAAe;QACf,QAAQ;QACR,SAAS;QACT,wCAAwC;QACxC,gCAAgC;IACpC;AACJ;;AAEA;uFACuF;;AAEvF;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,wBAAwB;IACxB,mBAAmB;AACvB;;AAEA;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,wBAAwB;IACxB,mBAAmB;IACnB,gBAAgB;AACpB;;AAEA;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,wBAAwB;IACxB,mBAAmB;IACnB,0BAA0B;AAC9B;;AAEA;IACI,iCAAiC;IACjC,eAAe;IACf,cAAc;IACd,wBAAwB;IACxB,gBAAgB;IAChB,gBAAgB;IAChB,yBAAyB;AAC7B;;AAEA;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,wBAAwB;IACxB,gBAAgB;IAChB,gBAAgB;AACpB;;AAEA,4BAA4B;;AAE5B;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,yBAAyB;AAC7B;;AAEA,UAAU;AACV;IACI,eAAe;AACnB;AACA;IACI,YAAY;IACZ,uBAAuB;IACvB,cAAc;AAClB;AACA;IACI,mBAAmB;AACvB;AACA;;EAEE,kBAAkB;EAClB,SAAS;EACT,mBAAmB;EACnB,gBAAgB;AAClB;;AAEA;IACI,iBAAiB;AACrB;AACA;IACI,mBAAmB;AACvB;;AAEA;IACI,aAAa;IACb,8BAA8B,EAAE,wDAAwD;IACxF,SAAS,EAAE,oCAAoC;IAC/C,kBAAkB,EAAE,2CAA2C;IAC/D,6BAA6B,EAAE,yDAAyD;AAC5F;;AAEA,gCAAgC;AAChC;IACI,oBAAoB;IACpB,eAAe;IACf,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,yBAAyB;IACzB,6BAA6B;AACjC;;AAEA,+BAA+B;AAC/B;IACI,yBAAyB;IACzB,kBAAkB;IAClB,6BAA6B;IAC7B,WAAW;IACX,YAAY;IACZ,0CAA0C;IAC1C,kCAAkC;IAClC,kCAAkC;AACtC;AACA;IACI;QACI,+BAA+B;IACnC;;IAEA;QACI,iCAAiC;IACrC;AACJ;;AAEA;IACI;QACI,uBAAuB;IAC3B;;IAEA;QACI,yBAAyB;IAC7B;AACJ;;AAEA;IACI,UAAU;IACV,WAAW;AACf;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,wCAAwC;AAC5C;;AAEA;IACI,uBAAuB;AAC3B;AACA,mBAAmB\",\"sourcesContent\":[\"@import url(//fonts.googleapis.com/css?family=Open+Sans);\\r\\n@import url(//fonts.googleapis.com/css?family=Open+Sans:300); \\r\\n@import url(//fonts.googleapis.com/css?family=Oswald);\\r\\n\\r\\n/* Shared CSS Accross site*/\\r\\nselect {\\r\\n /* Override MDB display none */\\r\\n display: unset;\\r\\n}\\r\\n.word-break-break-all{\\r\\n word-break: break-all;\\r\\n}\\r\\n.margin-horizontal-none{\\r\\n margin-left: 0px;\\r\\n margin-right: 0px;\\r\\n}\\r\\n.margin-vertical-none{\\r\\n margin-top: 0;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.margin-bottom-none{\\r\\n margin-bottom: 0 !important;\\r\\n}\\r\\n.horizontal-padding-none{\\r\\n padding-right: 0 !important;\\r\\n padding-left: 0 !important;\\r\\n}\\r\\n.vertical-padding-none{\\r\\n padding-top: 0 !important;\\r\\n padding-bottom: 0 !important;\\r\\n}\\r\\n.padding-none{\\r\\n padding: 0 !important;\\r\\n}\\r\\n.margin-none{\\r\\n margin: 0 !important;\\r\\n}\\r\\n.margin-bottom-lg{\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n.margin-right-lg{\\r\\n margin-right: 10px !important;\\r\\n}\\r\\n.vertical-align-bottom\\r\\n.inline-block {\\r\\n display: inline-block;\\r\\n}\\r\\n.display-inline{\\r\\n display: inline;\\r\\n}\\r\\n.hidden{\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.all-caps{\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n/* apply this to a wrapper div. Probably want full-height as well */\\r\\n.vertical-align-bottom {\\r\\n position: relative;\\r\\n}\\r\\n.vertical-align-bottom::before {\\r\\n content: \\\" \\\";\\r\\n display: inline-block;\\r\\n height: 100%;\\r\\n width: 1%;\\r\\n vertical-align: bottom;\\r\\n}\\r\\n.vertical-align-bottom * {\\r\\n display: inline-block;\\r\\n vertical-align: bottom;\\r\\n}\\r\\n.vertical-align-middle{\\r\\n vertical-align: middle;\\r\\n}\\r\\n\\r\\n.full-height {\\r\\n height: 100%;\\r\\n}\\r\\n.full-width {\\r\\n width: 100%;\\r\\n}\\r\\n.text-center {\\r\\n text-align: center;\\r\\n}\\r\\n.text-italic {\\r\\n font-style: italic;\\r\\n}\\r\\n.text-bold {\\r\\n font-weight: 700;\\r\\n}\\r\\n.text-light-grey {\\r\\n color: #b2b4b8;\\r\\n}\\r\\n.text-uppercase {\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n.text-small {\\r\\n font-size: .8rem;\\r\\n}\\r\\n\\r\\n.clickable{\\r\\n cursor: pointer;\\r\\n}\\r\\n.not-clickable{\\r\\n cursor: default !important;\\r\\n}\\r\\n.btn-transparent{\\r\\n background-color: transparent;\\r\\n box-shadow: none;\\r\\n}\\r\\n.btn-concrete{\\r\\n background-color:#F2F2F2 ;\\r\\n}\\r\\n\\r\\n/* App component styling */\\r\\nhtml {\\r\\n height: 100%;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n*,\\r\\n*:before,\\r\\n*:after {\\r\\n box-sizing: inherit;\\r\\n}\\r\\n\\r\\n\\r\\nbody {\\r\\n position: relative;\\r\\n margin: 0;\\r\\n min-height: 100%;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color:#3F474D;\\r\\n background-color:#F2F2F2; \\r\\n}\\r\\n.hide-scrollbar {\\r\\n overflow-y: hidden; /* Hide vertical scrollbar */\\r\\n}\\r\\n.hide-scrollbar::-webkit-scrollbar {\\r\\n display: none;\\r\\n}\\r\\n.add-scrollbar {\\r\\n overflow: scroll;\\r\\n}\\r\\n.app-container {\\r\\n margin: 0 auto;\\r\\n padding-top: 127px;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n min-height: 100vh;\\r\\n}\\r\\n\\r\\n.app-container-all-but-home {\\r\\n margin: 0 auto;\\r\\n padding-top: 127px;\\r\\n min-height: 100vh;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n.app-container-for-home {\\r\\n margin: 0 auto;\\r\\n padding-top: 82px;\\r\\n min-height: 100vh;\\r\\n padding-bottom: 75px; /* Pushes the footer down. Helps with element inspection where footer was overlapping rest of DOM */\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n/**\\r\\n * Footer Styles\\r\\n */\\r\\n\\r\\nfooter-component {\\r\\n position: relative;\\r\\n right: 0;\\r\\n bottom: 0;\\r\\n left: 0;\\r\\n}\\r\\n\\r\\nfooter.page-footer {\\r\\n padding-top: 20px;\\r\\n background-color: #1a1a1a;\\r\\n color: #B0ACA6;\\r\\n font-size: 12px;\\r\\n margin-top: -75px; /* negative value of footer height */\\r\\n height: 75px;\\r\\n clear: both;\\r\\n}\\r\\n\\r\\nfooter.page-footer a{\\r\\n color: #B0ACA6;\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\nfooter.page-footer img {\\r\\n height: 40px;\\r\\n}\\r\\n\\r\\n.nes-footer-logo{\\r\\n opacity: .25;\\r\\n}\\r\\n/* Modal dialog\\r\\n*/\\r\\n.modal-top{\\r\\n padding-top: 10%;\\r\\n}\\r\\n\\r\\n.modal-header {\\r\\n padding:9px 15px;\\r\\n border-bottom:1px solid #eee;\\r\\n background-color: #0099CC; \\r\\n }\\r\\n\\r\\n.modal-title{\\r\\n font-weight: bold\\r\\n}\\r\\n\\r\\n/* to set equal height of div row containing different height child rows/divs*/\\r\\n.row-eq-height {\\r\\n display: -webkit-box;\\r\\n display: -webkit-flex;\\r\\n display: -ms-flexbox;\\r\\n display: flex;\\r\\n}\\r\\n\\r\\n.height-30px{\\r\\n height: 30px;\\r\\n}\\r\\n\\r\\n.body-background-image {\\r\\n /* Location of the image */\\r\\n background-image: url(../assets/nes_bg.jpg);\\r\\n /* Background image is centered vertically and horizontally at all times */\\r\\n background-position: center center;\\r\\n /* Background image doesn't tile */\\r\\n background-repeat: no-repeat;\\r\\n /* Background image is fixed in the viewport so that it doesn't move when \\r\\n the content's height is greater than the image's height */\\r\\n background-attachment: fixed;\\r\\n /* This is what makes the background image rescale based on the container's size */\\r\\n background-size: cover;\\r\\n /* Set a background color that will be displayed while the background image is loading */\\r\\n background-color: #464646;\\r\\n}\\r\\n\\r\\n.nes-logo {\\r\\n height:50px;\\r\\n width:50px;\\r\\n}\\r\\n\\r\\n.div-box-shadow{\\r\\n box-shadow: 5px 5px 2px #dddddd;\\r\\n}\\r\\n\\r\\n.have-questions-box {\\r\\n background-color:#F9F9F9;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em; \\r\\n}\\r\\n\\r\\n\\r\\n/* Colors */\\r\\n.bg-color-light-gray-1{\\r\\n background-color:#F9F9F9;\\r\\n}\\r\\n\\r\\n.bg-color-light-gray-2{\\r\\n background-color:#F2F2F2;\\r\\n}\\r\\n\\r\\n.bg-color-dark-gray-1{\\r\\n background-color:#585961;\\r\\n}\\r\\n.bg-color-dark-gray-2{\\r\\n background-color:#3F474D;\\r\\n}\\r\\n.bg-color-blue{\\r\\n background-color:#00AEEF;\\r\\n}\\r\\n.text-medium-gray{\\r\\n color:#939BA1;\\r\\n}\\r\\n\\r\\n.text-dark-gray{\\r\\n color:#5E5F67;\\r\\n}\\r\\n.text-medium-green{\\r\\n color: #70AD47;\\r\\n}\\r\\n.text-light-green{\\r\\n color: #B4D88B;\\r\\n}\\r\\n.text-blue{\\r\\n color:#00AEEF !important;\\r\\n}\\r\\n.text-orange{\\r\\n color:#E95713;\\r\\n}\\r\\n.text-red{\\r\\n color:#fa005e;\\r\\n}\\r\\n.loading-indicator {\\r\\n position: absolute;\\r\\n width: 100%;\\r\\n /*height: 100%;*/\\r\\n background: white;\\r\\n top:0%;\\r\\n left:0%;\\r\\n}\\r\\n.loading-indicator .fa-refresh:before {\\r\\n color: blue;\\r\\n}\\r\\n\\r\\n\\r\\n/*////////////////\\r\\n///// Buttons ///\\r\\n//////////////*/\\r\\n.button-green{\\r\\n background: #B4D88B;\\r\\n padding: 8.5px 17px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 12px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n border-color: transparent;\\r\\n }\\r\\n.button-green:hover {\\r\\n background: #CEE1B8;\\r\\n color: #fff;\\r\\n }\\r\\n.button-green:active {\\r\\n background: #DAE6CB;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.button-red{\\r\\n background: #EE1849;\\r\\n padding: 8.5px 22px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 12px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n border-color: transparent;\\r\\n }\\r\\n.button-red:hover {\\r\\n background: #E85073;\\r\\n color: #fff;\\r\\n }\\r\\n.button-red:active {\\r\\n background: #E89CAE;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n\\r\\n.reset-button, .reset-button:hover{\\r\\n background-color: #F2F2F2;\\r\\n color: #3F474D !important; \\r\\n}\\r\\n\\r\\n/* Typography */\\r\\n\\r\\n.font-heading{\\r\\n font-size:24px;\\r\\n font-weight:bold;\\r\\n line-height: 1;\\r\\n color: #3F474D;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-titlebar{\\r\\n font-size:20px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color: #5E5F67;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-subheading{\\r\\n font-size:16px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color: #585961;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-body{\\r\\n font-size: 14px;\\r\\n font-weight:normal;\\r\\n color:#3F474D;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n.font-caption{\\r\\n font-size:12px;\\r\\n font-weight:normal;\\r\\n line-height: 1;\\r\\n color:#585961;\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n}\\r\\n\\r\\n/* Exception Pages */\\r\\n.ButtonNav {\\r\\n background: #939BA1;\\r\\n padding: 16px 80px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 16px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n }\\r\\n \\r\\n.ButtonNav:hover {\\r\\n background: #A4A6A8;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.ButtonNav:active {\\r\\n background: #B3B3B3;\\r\\n color: #fff;\\r\\n }\\r\\n\\r\\n.exception-page-btn-home-width {\\r\\n padding: 16px 118px;\\r\\n}\\r\\n\\r\\n.color-white{\\r\\n color: #ffffff !important;\\r\\n}\\r\\n\\r\\n.exception-page-http-code{\\r\\n font-size: 48px;\\r\\n font-weight: 700;\\r\\n font-style: normal;\\r\\n padding-bottom: 12px;\\r\\n}\\r\\n\\r\\n.exception-page-http-message{\\r\\n font-weight: bold;\\r\\n font-style: normal;\\r\\n}\\r\\n\\r\\n.exception-page-button-row-spacing{\\r\\n margin-top:15px;\\r\\n}\\r\\n\\r\\n@media (min-width: 1280px) {\\r\\n .exception-page-white-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 40%;\\r\\n position: fixed;\\r\\n top: 48%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n }\\r\\n}\\r\\n\\r\\n/*Calpine style typography \\r\\n https://app.frontify.com/d/c7zJIyYFDWm5/ces-portal-style-guide#/basics/typography */\\r\\n\\r\\n.calpine-paragraph-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n}\\r\\n\\r\\n.calpine-paragraph-bold-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.calpine-paragraph-link-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 14px;\\r\\n color: #006699;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 22.4px;\\r\\n text-decoration: underline;\\r\\n}\\r\\n\\r\\n.calpine-heading-h2-text{\\r\\n font-family: 'Oswald', sans-serif;\\r\\n font-size: 34px;\\r\\n color: #006699;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 1.3;\\r\\n font-weight: 400;\\r\\n text-transform: uppercase;\\r\\n}\\r\\n\\r\\n.calpine-heading-h6-text{\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 16px;\\r\\n color: #4D4D4D;\\r\\n background-color:#FFFFFF;\\r\\n line-height: 1.6;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n/*Calpine style typography */\\r\\n\\r\\na:link {\\r\\n color: #006699;\\r\\n}\\r\\n\\r\\n.calpine-limeade {\\r\\n color: #5AAD00;\\r\\n}\\r\\n\\r\\n.calpine-allports {\\r\\n color: #006699;\\r\\n}\\r\\n\\r\\n.calpine-lochmara {\\r\\n color: #0088CC;\\r\\n}\\r\\n\\r\\n.calpine-background-lochmara {\\r\\n background-color: #0088CC;\\r\\n}\\r\\n\\r\\n/*ag-grid*/\\r\\n.ag-filter select {\\r\\n display: inline;\\r\\n}\\r\\n.ag-filter input[type=text] {\\r\\n width: 170px;\\r\\n margin: 6px 4px 4px 4px;\\r\\n height: 1.1rem;\\r\\n}\\r\\n.ag-header-cell-label {\\r\\n white-space: normal;\\r\\n}\\r\\n.ag-filter [type=\\\"checkbox\\\"]:not(:checked),\\r\\n.ag-filter [type=\\\"checkbox\\\"]:checked {\\r\\n position: relative;\\r\\n left: 0px;\\r\\n visibility: visible;\\r\\n margin-left: 5px;\\r\\n}\\r\\n\\r\\n.ag-virtual-list-container {\\r\\n overflow: visible;\\r\\n}\\r\\n.ag-set-filter-item {\\r\\n padding-right: 10px;\\r\\n}\\r\\n\\r\\n.ag-filter-apply-panel {\\r\\n display: flex;\\r\\n justify-content: space-between; /* Pushes 'Clear' to the left and 'Apply' to the right */\\r\\n gap: 12px; /* Adds clean spacing if they wrap */\\r\\n padding: 10px 12px; /* Adds padding inside the container base */\\r\\n border-top: 1px solid #e2e8f0; /* Optional: Adds a subtle separator line above buttons */\\r\\n}\\r\\n\\r\\n/* Style BOTH buttons globally */\\r\\n.ag-standard-button {\\r\\n font-family: inherit;\\r\\n font-size: 13px;\\r\\n font-weight: 500;\\r\\n padding: 6px 16px;\\r\\n border-radius: 4px;\\r\\n cursor: pointer;\\r\\n transition: all 0.2s ease;\\r\\n border: 1px solid transparent;\\r\\n}\\r\\n\\r\\n/* Preload spinner like signup*/\\r\\n.preload-spinner {\\r\\n border: 8px solid #818285;\\r\\n border-radius: 50%;\\r\\n border-top: 8px solid #0088CC;\\r\\n width: 50px;\\r\\n height: 50px;\\r\\n -webkit-animation: spin 1s linear infinite;\\r\\n animation: spin 1s linear infinite;\\r\\n box-sizing: content-box !important;\\r\\n}\\r\\n@-webkit-keyframes spin {\\r\\n 0% {\\r\\n -webkit-transform: rotate(0deg);\\r\\n }\\r\\n\\r\\n 100% {\\r\\n -webkit-transform: rotate(360deg);\\r\\n }\\r\\n}\\r\\n\\r\\n@keyframes spin {\\r\\n 0% {\\r\\n transform: rotate(0deg);\\r\\n }\\r\\n\\r\\n 100% {\\r\\n transform: rotate(360deg);\\r\\n }\\r\\n}\\r\\n\\r\\n.grid-size {\\r\\n width: 98%;\\r\\n height: 85%;\\r\\n}\\r\\n\\r\\n#ui-datepicker-div select {\\r\\n display: inline;\\r\\n}\\r\\n\\r\\n.ag-header-active {\\r\\n background-color: transparent !important;\\r\\n}\\r\\n\\r\\n.ag-header-icon {\\r\\n color: white !important;\\r\\n}\\r\\n/******************/\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".active-blue-tab {\\r\\n color: #0026ff;\\r\\n}\\r\\n.active-black-tab {\\r\\n color: #000000;\\r\\n}\\r\\n.blue-breadCrumb-color{\\r\\n color:#00AEEF;\\r\\n}\\r\\n\\r\\n.fa-lg{\\r\\n font-size: 2.5em;\\r\\n margin-top: 15px;\\r\\n margin-bottom: 5px;\\r\\n}\\r\\n\\r\\n.fa-help{\\r\\n margin-top: 15px;\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n\\r\\n.help-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n}\\r\\n.help-title-text{\\r\\n vertical-align:central;\\r\\n margin-top:15px;\\r\\n margin-bottom:15px;\\r\\n}\\r\\n\\r\\n.help-title-Row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color: white;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n\\r\\n.help-schedule-button{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.help-white-div-background {\\r\\n border-radius: 0px;\\r\\n background-color: #ffffff;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em;\\r\\n}\\r\\n\\r\\n.grey-bottom-border{\\r\\n border-bottom: 2px solid darkgray;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/dynamic-scheduling/help-schedule/help-schedule.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,cAAc;AAClB;AACA;IACI,cAAc;AAClB;AACA;IACI,aAAa;AACjB;;AAEA;IACI,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;AACtB;;AAEA;IACI,gBAAgB;IAChB,mBAAmB;AACvB;;AAEA;IACI,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;AACjB;AACA;IACI,sBAAsB;IACtB,eAAe;IACf,kBAAkB;AACtB;;AAEA;IACI,gBAAgB;IAChB,mCAAmC;IACnC,uBAAuB;IACvB,kBAAkB;AACtB;;AAEA;IACI,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,iBAAiB;AACrB;;AAEA;IACI,kBAAkB;IAClB,yBAAyB;IACzB,eAAe;IACf,kBAAkB;AACtB;;AAEA;IACI,iCAAiC;AACrC\",\"sourcesContent\":[\".active-blue-tab {\\r\\n color: #0026ff;\\r\\n}\\r\\n.active-black-tab {\\r\\n color: #000000;\\r\\n}\\r\\n.blue-breadCrumb-color{\\r\\n color:#00AEEF;\\r\\n}\\r\\n\\r\\n.fa-lg{\\r\\n font-size: 2.5em;\\r\\n margin-top: 15px;\\r\\n margin-bottom: 5px;\\r\\n}\\r\\n\\r\\n.fa-help{\\r\\n margin-top: 15px;\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n\\r\\n.help-title{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n}\\r\\n.help-title-text{\\r\\n vertical-align:central;\\r\\n margin-top:15px;\\r\\n margin-bottom:15px;\\r\\n}\\r\\n\\r\\n.help-title-Row {\\r\\n margin-top: -5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n background-color: white;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n\\r\\n.help-schedule-button{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.help-white-div-background {\\r\\n border-radius: 0px;\\r\\n background-color: #ffffff;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em;\\r\\n}\\r\\n\\r\\n.grey-bottom-border{\\r\\n border-bottom: 2px solid darkgray;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".fa-schedule-archive{\\r\\n margin-top: 15px;\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n\\r\\n.schedule-archive-page-icon{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.schedule-paging-container{\\r\\n padding-top:30px;\\r\\n}\\r\\n\\r\\n.schedule-archive-spinner-top {\\r\\n padding-top: 125px;\\r\\n}\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/dynamic-scheduling/schedule-archive/schedule-archive.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,gBAAgB;IAChB,mBAAmB;AACvB;;AAEA;IACI,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,iBAAiB;AACrB;;AAEA;IACI,gBAAgB;AACpB;;AAEA;IACI,kBAAkB;AACtB\",\"sourcesContent\":[\".fa-schedule-archive{\\r\\n margin-top: 15px;\\r\\n margin-bottom: 10px;\\r\\n}\\r\\n\\r\\n.schedule-archive-page-icon{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n}\\r\\n\\r\\n.schedule-paging-container{\\r\\n padding-top:30px;\\r\\n}\\r\\n\\r\\n.schedule-archive-spinner-top {\\r\\n padding-top: 125px;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"/*/////////////////////////////\\r\\n/ Welcome bar /\\r\\n////////////////////////////*/\\r\\n.schedule-upload-button{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n cursor: pointer;\\r\\n}\\r\\n.schedule-upload-button-disabled {\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align: center;\\r\\n background-color: lightgrey;\\r\\n pointer-events: none;\\r\\n}\\r\\n.schedule-upload-help-button{\\r\\n color: #00AEEF;\\r\\n background-color: white;\\r\\n vertical-align:top;\\r\\n position:absolute;\\r\\n right:0px;\\r\\n}\\r\\n.schedule-upload-help-button-icon{\\r\\n padding-left: 5px;\\r\\n}\\r\\n.fa-lg{\\r\\n font-size: 2.5em;\\r\\n margin-top: 15px;\\r\\n margin-bottom: 5px;\\r\\n}\\r\\n.dynamic-scheduling-welcome{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n.dynamic-scheduling-welcome-row {\\r\\n margin-top:-5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n margin-bottom: 0px;\\r\\n background-color: white;\\r\\n}\\r\\n.light-text{\\r\\n color: rgb(189,195, 199);\\r\\n}\\r\\n.schedule-upload-progress-bar {\\r\\n margin: 0;\\r\\n}\\r\\n.schedule-upload-progress-area {\\r\\n background-color: rgb(249,249,249);\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Dashboard\\r\\n /\\r\\n////////////////////////////*/\\r\\n.validation-area{\\r\\n background-color: rgb(249,249,249);\\r\\n height:330px;\\r\\n}\\r\\n.validation-area-title{\\r\\n margin: 10px 0 0 30px;\\r\\n height: 30px;\\r\\n}\\r\\n.validation-errors-summary-card{\\r\\n padding: 25px;\\r\\n margin: 15px 25px 25px 25px;\\r\\n height: 250px;\\r\\n overflow-y: scroll;\\r\\n \\r\\n}\\r\\n.review-button{\\r\\n color: red !important;\\r\\n}\\r\\n.review-button:hover{\\r\\n background-color: #F9F9F9;\\r\\n}\\r\\n\\r\\n.validation-error-stripe{\\r\\n border-left: 5px solid rgb(244, 70, 65);\\r\\n}\\r\\n.validation-warning-stripe{\\r\\n border-left: 5px solid rgb(237,174,73);\\r\\n}\\r\\n.validation-neutral-stripe {\\r\\n border-left: 5px solid;\\r\\n}\\r\\n.validation-success-stripe{\\r\\n border-left: 5px solid;\\r\\n}\\r\\n.summary-cards{\\r\\n margin-top: 15px;\\r\\n margin-left: 35px;\\r\\n}\\r\\n.summary-count-card{\\r\\n height: 110px;\\r\\n padding: 10px 10px 15px 30px;\\r\\n margin: 0 30px 30px 0px;\\r\\n cursor: pointer;\\r\\n}\\r\\n.summary-count-label{\\r\\n height: 40px;\\r\\n}\\r\\n.validation-count > span{\\r\\n font-size: 2em;\\r\\n margin-left: 20px;\\r\\n margin-top: 5px;\\r\\n padding-top: 5px;\\r\\n}\\r\\n.validation-count > * {\\r\\n float: left;\\r\\n display: block;\\r\\n}\\r\\n\\r\\n.validation-asterisk-big{\\r\\n color: rgb(244, 70, 65);\\r\\n font-size: 2em;\\r\\n margin-top: -10px;\\r\\n}\\r\\n.invalid-allegro-points{\\r\\n padding-left: 30px;\\r\\n}\\r\\n.invalid-allegro-points li{\\r\\n list-style-type: disc;\\r\\n}\\r\\n\\r\\n.validation-error-color{\\r\\n color: rgb(244, 70, 65);\\r\\n}\\r\\n.validation-warning-color{\\r\\n color: rgb(237,174,73) !important;\\r\\n}\\r\\n.validation-neutral-color {\\r\\n color: rgb(20, 181, 240);\\r\\n}\\r\\n.validation-success-color{\\r\\n color: rgb(180, 216, 139);\\r\\n}\\r\\n\\r\\n.validation-hour-count-card{\\r\\n height: 110px;\\r\\n min-width: 80px;\\r\\n /*max-width: 120px;*/\\r\\n text-align: center;\\r\\n cursor: pointer;\\r\\n box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);\\r\\n border-radius: 2px;\\r\\n}\\r\\n.limit-warning-count-upper{\\r\\n background-color: rgb(240,189,107);\\r\\n color: white;\\r\\n height: 60%;\\r\\n padding: 10px;\\r\\n}\\r\\n.limit-warning-count-upper span {\\r\\n font-size: 2em;\\r\\n}\\r\\n.limit-warning-count-lower{\\r\\n background-color: rgb(237,174,73);\\r\\n height: 40%;\\r\\n}\\r\\n.limit-error-count-upper{\\r\\n background-color: rgb(246,104,100);\\r\\n color: white;\\r\\n height: 60%;\\r\\n padding: 10px;\\r\\n}\\r\\n.limit-error-count-upper span{\\r\\n font-size: 2em;\\r\\n}\\r\\n.limit-error-count-lower{\\r\\n background-color: rgb(244,70,65);\\r\\n height: 40%;\\r\\n}\\r\\n.hourly-validation-container{\\r\\n padding-right: 30px !important;\\r\\n}\\r\\n.limit-warning-card{\\r\\n margin-right: 10px;\\r\\n}\\r\\n.below-fixed-card{\\r\\n margin-left: 10px;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Schedule header and search bar/\\r\\n////////////////////////////*/\\r\\n.schedule-search-bar{\\r\\n padding-right: 50px;\\r\\n padding-left: 20px;\\r\\n padding-top: 15px;\\r\\n padding-bottom: 15px;\\r\\n/* height: 65px;*/\\r\\n top:82px;\\r\\n z-index: 1020;\\r\\n}\\r\\n.schedule-export{\\r\\n z-index: 1021;\\r\\n}\\r\\n.dropdown-scrollbar{\\r\\n max-height: 250px;\\r\\n overflow-y: scroll;\\r\\n}\\r\\n.clear-customer-search{\\r\\n background-color: rgb(244,70,65) !important;\\r\\n color: white;\\r\\n border-radius: 0;\\r\\n}\\r\\n\\r\\n.schedule-search-bar button{\\r\\n/* padding: 3px 10px;*/\\r\\n}\\r\\n.schedule-search-box{\\r\\n width: 300px;\\r\\n background-color: white;\\r\\n vertical-align: middle;\\r\\n}\\r\\n.schedule-search-box input {\\r\\n padding-left: 10px;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n.schedule-search-icon {\\r\\n padding-left: 30px;\\r\\n padding-right: 30px;\\r\\n}\\r\\n\\r\\n.he-grey{\\r\\n color: rgb(191,193,194);\\r\\n}\\r\\n.schedule-header{\\r\\n background-color: black;\\r\\n color: white;\\r\\n border-style: none;\\r\\n /*If an overflow scroll bar is used, add 17px to the right padding for the scrollbar in the table body to properly line up the headers*/\\r\\n padding: 0px 30px 0 35px; \\r\\n}\\r\\n.schedule-header table{\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.schedule-header td.schedule-header-cell {\\r\\n border-style: none;\\r\\n font-weight: bold;\\r\\n vertical-align: bottom;\\r\\n border-left: 1px solid #3F474D;\\r\\n border-right: 1px solid #3F474D;\\r\\n padding-top:5px;\\r\\n color: white;\\r\\n background-color: black;\\r\\n}\\r\\n\\r\\n\\r\\n/* have to undo mdb */\\r\\n.header-filter a{\\r\\n margin-left: 0;\\r\\n}\\r\\n.schedule-header .he-table-cell{\\r\\n padding-left: 0;\\r\\n padding-right: 0;\\r\\n}\\r\\n.he-table-cell{\\r\\n text-align: center;\\r\\n padding-left: 0 !important; /* Have to overwrite bootstrap, it's a tight fit*/\\r\\n padding-right: 0 !important;\\r\\n}\\r\\n\\r\\n.schedule-upload-table .he-table-cell{\\r\\n width:2.6%;\\r\\n}\\r\\n\\r\\n\\r\\n.schedule-upload-table .customer-table-cell{\\r\\n width: 15%;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n/* the next two need to sum to the third */\\r\\n.flowdate-table-cell{\\r\\n width: 7.6%;\\r\\n}\\r\\n.schedule-label-table-cell{\\r\\n width: 15%;\\r\\n}\\r\\n.flowdate-table-header{\\r\\n width: 22.6%;\\r\\n}\\r\\n.flowdate-header-text{\\r\\n width: 33.6283185%;\\r\\n}\\r\\n.flowdate-header-filter{\\r\\n width: 66.37168141%; /* 15/22.6 */\\r\\n}\\r\\n.filter-button{\\r\\n padding: 4px 6px 4px 6px;\\r\\n margin-bottom: -5px !important;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Archive Tables /\\r\\n////////////////////////////*/\\r\\ntd.schedule-table-cell-gray-bg{\\r\\n /* This gives the td the same color background and border as the body background */\\r\\n background-color:#F2F2F2;\\r\\n border-color:#F2F2F2;\\r\\n}\\r\\n\\r\\n.scrollable-schedule-container{\\r\\n width:100%;\\r\\n overflow-x:auto;\\r\\n}\\r\\n.scrollable-schedule-content{\\r\\n min-width:1900px;\\r\\n overflow-y:hidden;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .final-table-cell{\\r\\n width: 2.4%;\\r\\n}\\r\\n.schedule-archive-table .timestamp-table-cell{\\r\\n width: 5.5%;\\r\\n}\\r\\n.schedule-archive-table .customer-table-cell{\\r\\n width: 7%;\\r\\n word-wrap: break-word;\\r\\n word-break: break-all;\\r\\n}\\r\\n.schedule-archive-table .flowdate-table-cell{\\r\\n width: 4.3%;\\r\\n}\\r\\n.schedule-archive-table .schedule-label-table-cell{\\r\\n width:6.7%;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .he-table-cell{\\r\\n width:2.4%;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .dow-table-cell{\\r\\n width: 3.4%;\\r\\n}\\r\\n.schedule-archive-table .submitter-table-cell{\\r\\n width:13.1%;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n.schedule-timestamp{\\r\\n text-align: center;\\r\\n}\\r\\n.schedule-timestamp-month{\\r\\n font-size:14px;\\r\\n font-weight:bold;\\r\\n}\\r\\n.schedule-timestamp-day{\\r\\n font-size:18px;\\r\\n font-weight:bold;\\r\\n}\\r\\n.schedule-timestamp-year{\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Schedule Tables /\\r\\n////////////////////////////*/\\r\\n.schedule-lock i{\\r\\n font-size: 1.75em;\\r\\n}\\r\\n.schedule-lock .fa-pencil{\\r\\n color: #5aad00;\\r\\n}\\r\\n\\r\\n.schedule-upload-area{\\r\\n padding: 0 30px 30px 35px;\\r\\n margin-bottom: -10px; \\r\\n box-sizing: border-box;\\r\\n}\\r\\n.schedule-grey{\\r\\n color: rgb(66,74,80);\\r\\n}\\r\\n.validation-asterisk{\\r\\n padding-left: 20px;\\r\\n color: rgb(244, 70, 65);\\r\\n font-size: 1.3em;\\r\\n}\\r\\n\\r\\ntd.hourly-validation-error, .hourly-validation-error td{\\r\\n border-bottom: 10px solid rgb(244, 70, 65) !important;\\r\\n}\\r\\n.hourly-validation-warning{\\r\\n border-bottom: 10px solid rgb(252,186,77) !important;\\r\\n}\\r\\n.he-table-cell{\\r\\n width:2.6%;\\r\\n text-align: center;\\r\\n padding-left: 0 !important; /* Have to overwrite bootstrap, it's a tight fit*/\\r\\n padding-right: 0 !important;\\r\\n}\\r\\n/* force every HE cell in the customer to be 46px. Otherwise, it would be impossible to format all the \\r\\n highlighting due to the limit/fixed warning border only sometimes being present */\\r\\n.customer-he-cell{\\r\\n height: 46px;\\r\\n}\\r\\n.he-table-cell > div > div{\\r\\n padding-top: 12px;\\r\\n padding-bottom: 12px;\\r\\n}\\r\\n\\r\\n/* padding changes when the dirty highlight is present*/\\r\\n.he-table-cell.he-highlight-dirty > div > div {\\r\\n padding-top: 9px;\\r\\n padding-bottom: 14px;\\r\\n}\\r\\n/* input height if validation border is NOT present*/\\r\\n.he-highlight-active .edit-he-input,\\r\\n.he-highlight-active .edit-he-input\\r\\n {\\r\\n height: 42px;\\r\\n padding-bottom: 7px;\\r\\n}\\r\\n/* input height if border is present*/\\r\\n.he-highlight-active.hourly-validation-error .edit-he-input,\\r\\n.he-highlight-active.hourly-validation-warning .edit-he-input\\r\\n {\\r\\n height: 36px;\\r\\n padding-bottom: 2px;\\r\\n}\\r\\n/* highlight box height if border is not present */\\r\\n.he-highlight-active > div,\\r\\n.he-highlight-dirty > div{\\r\\n height: 45px;\\r\\n}\\r\\n/* highlight box height if boder IS present*/\\r\\n.he-highlight-active.hourly-validation-warning > div, .he-highlight-active.hourly-validation-error > div,\\r\\n.he-highlight-dirty.hourly-validation-warning > div, .he-highlight-dirty.hourly-validation-error > div{\\r\\n height: 40px;\\r\\n}\\r\\n/*Actual highlighting*/\\r\\n.he-highlight-active > div{\\r\\n border: 2px solid rgb(0,176,238) !important;\\r\\n /*height: 45px;*/\\r\\n}\\r\\n.he-highlight-dirty > div{\\r\\n border: 3px solid rgb(88,173,75) !important;\\r\\n /*height: 45px;*/\\r\\n}\\r\\n.he-highlight-error {\\r\\n border: 3px solid rgb(255,0,56) !important;\\r\\n}\\r\\n.he-highlight-active input.middle:focus {\\r\\n outline-width: 0;\\r\\n}\\r\\n.save-schedules-btn{\\r\\n /* this is all copied from mdb .fixed-action-btn - the associated mdb JS was erroring with zone js for unknown reasons */\\r\\n bottom: 45px; \\r\\n right: 24px;\\r\\n position: fixed;\\r\\n margin-bottom: 0;\\r\\n z-index: 998;\\r\\n}\\r\\n.save-schedules-btn.active{\\r\\n background-color:transparent;\\r\\n}\\r\\n\\r\\n.uploaded-schedule-table{\\r\\n box-sizing: border-box;\\r\\n background-color: white;\\r\\n}\\r\\n.dashed-line {\\r\\n border-width: 1px;\\r\\n border-style: dashed;\\r\\n border-color: gainsboro;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.schedule-upload-card{\\r\\n padding: 30px 30px 30px 30px;\\r\\n}\\r\\n\\r\\n.hour-validation-count{\\r\\n width: 30px;\\r\\n height: 30px;\\r\\n color: white;\\r\\n -moz-border-radius: 15px;\\r\\n -webkit-border-radius: 15px;\\r\\n border-radius: 15px;\\r\\n display: block;\\r\\n text-align: center;\\r\\n vertical-align: middle;\\r\\n display: inline-block;\\r\\n padding-top: 5px;\\r\\n}\\r\\n.hour-error-count{\\r\\n background-color: rgb(244, 70, 65);\\r\\n margin-left: -10px;\\r\\n} \\r\\n.hour-warning-count{\\r\\n background-color: rgb(252,186,77);\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// Tooltips //\\r\\n////////////////////////////*/\\r\\n\\r\\n.dyn-schedule-tooltip-error .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color: rgb(246,104,100) !important;\\r\\n\\r\\n}\\r\\n.dyn-schedule-tooltip-error .tooltip-arrow{\\r\\n border-top-color: rgb(246,104,100) !important;\\r\\n}\\r\\n\\r\\n.dyn-schedule-tooltip-warning .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color: rgb(240,189,107) !important;\\r\\n}\\r\\n.dyn-schedule-tooltip-warning .tooltip-arrow{\\r\\n border-top-color: rgb(240,189,107) !important;\\r\\n}\\r\\n\\r\\n.dyn-schedule-tooltip-he-truncation .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color:#3F474D;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// Error Splashscreen //\\r\\n////////////////////////////*/\\r\\n\\r\\n.error-card {\\r\\n max-width: 500px;\\r\\n width: 85%;\\r\\n text-align: center;\\r\\n margin: 0 auto;\\r\\n margin-top: 75px; \\r\\n}\\r\\n.error-card-container {\\r\\n padding: 50px;\\r\\n}\\r\\n.error-btn {\\r\\n background: #939BA1 !important;\\r\\n margin-bottom: 2px;\\r\\n width: 80%;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// High Warning Dialog //\\r\\n////////////////////////////*/\\r\\n\\r\\n.dialog-header {\\r\\n background-color: RGB(0,174,239) !important;\\r\\n}\\r\\n.modal-title {\\r\\n color: white;\\r\\n}\\r\\n\\r\\n\\r\\n/*///////////////////////////////////////////\\r\\n// Dashboard and Search fixed to top //\\r\\n//////////////////////////////////////////*/\\r\\n.fixed-schedule-upload-dashboard{\\r\\n width:100%;\\r\\n top:127px;\\r\\n position:fixed; \\r\\n z-index: 1020;\\r\\n}\\r\\n\\r\\n.schedule-upload-list-db-expanded{\\r\\n padding-top:585px; \\r\\n}\\r\\n.schedule-upload-list-db-collapsed{\\r\\n padding-top:245px;\\r\\n}\\r\\n\\r\\n.schedule-upload-container .schedule-header {\\r\\n width: 100%; \\r\\n z-index:1020; \\r\\n position:fixed;\\r\\n /* top:617px; */\\r\\n}\\r\\n.schedule-upload-area{\\r\\n min-height:300px;\\r\\n}\\r\\n\\r\\n.schedule-archive-container .schedule-header {\\r\\n width: 100%; \\r\\n z-index:1020; \\r\\n position:fixed;\\r\\n min-width: 1900px;\\r\\n}\\r\\n\\r\\n.schedule-archive-list{\\r\\n padding-top:225px;\\r\\n}\\r\\n\\r\\n\\r\\n/* DATEPICKER */\\r\\n.ui-datepicker{\\r\\n z-index: 1020 !important;\\r\\n}\\r\\n\\r\\n.schedule-date-filter-input-box{\\r\\n background-color:white;\\r\\n vertical-align: middle;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n\\r\\n.schedule-date-filter-input-box input {\\r\\n font-weight: normal;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n.schedule-date-range-filter-container{\\r\\n padding-left: 15px;\\r\\n padding-right: 15px;\\r\\n width:500px;\\r\\n height:60px;\\r\\n}\\r\\n\\r\\n.daterange-clear-btn{\\r\\n padding-top:15px;\\r\\n}\\r\\n\\r\\n.schedule-preload-spinner-top {\\r\\n padding-top: 250px;\\r\\n}\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/dynamic-scheduling/schedule-upload/schedule-upload.component.css\"],\"names\":[],\"mappings\":\"AAAA;;6BAE6B;AAC7B;IACI,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,iBAAiB;IACjB,eAAe;AACnB;AACA;IACI,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,kBAAkB;IAClB,2BAA2B;IAC3B,oBAAoB;AACxB;AACA;IACI,cAAc;IACd,uBAAuB;IACvB,kBAAkB;IAClB,iBAAiB;IACjB,SAAS;AACb;AACA;IACI,iBAAiB;AACrB;AACA;IACI,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;AACtB;AACA;IACI,sBAAsB;IACtB,kBAAkB;IAClB,iBAAiB;IACjB,aAAa;IACb,kBAAkB;AACtB;AACA;IACI,eAAe;IACf,mCAAmC;IACnC,kBAAkB;IAClB,uBAAuB;AAC3B;AACA;IACI,wBAAwB;AAC5B;AACA;IACI,SAAS;AACb;AACA;IACI,kCAAkC;AACtC;;AAEA;;;6BAG6B;AAC7B;IACI,kCAAkC;IAClC,YAAY;AAChB;AACA;IACI,qBAAqB;IACrB,YAAY;AAChB;AACA;IACI,aAAa;IACb,2BAA2B;IAC3B,aAAa;IACb,kBAAkB;;AAEtB;AACA;IACI,qBAAqB;AACzB;AACA;IACI,yBAAyB;AAC7B;;AAEA;IACI,uCAAuC;AAC3C;AACA;IACI,sCAAsC;AAC1C;AACA;IACI,sBAAsB;AAC1B;AACA;IACI,sBAAsB;AAC1B;AACA;IACI,gBAAgB;IAChB,iBAAiB;AACrB;AACA;IACI,aAAa;IACb,4BAA4B;IAC5B,uBAAuB;IACvB,eAAe;AACnB;AACA;IACI,YAAY;AAChB;AACA;IACI,cAAc;IACd,iBAAiB;IACjB,eAAe;IACf,gBAAgB;AACpB;AACA;IACI,WAAW;IACX,cAAc;AAClB;;AAEA;IACI,uBAAuB;IACvB,cAAc;IACd,iBAAiB;AACrB;AACA;IACI,kBAAkB;AACtB;AACA;IACI,qBAAqB;AACzB;;AAEA;IACI,uBAAuB;AAC3B;AACA;IACI,iCAAiC;AACrC;AACA;IACI,wBAAwB;AAC5B;AACA;IACI,yBAAyB;AAC7B;;AAEA;IACI,aAAa;IACb,eAAe;IACf,oBAAoB;IACpB,kBAAkB;IAClB,eAAe;IACf,oEAAoE;IACpE,kBAAkB;AACtB;AACA;IACI,kCAAkC;IAClC,YAAY;IACZ,WAAW;IACX,aAAa;AACjB;AACA;IACI,cAAc;AAClB;AACA;IACI,iCAAiC;IACjC,WAAW;AACf;AACA;IACI,kCAAkC;IAClC,YAAY;IACZ,WAAW;IACX,aAAa;AACjB;AACA;IACI,cAAc;AAClB;AACA;IACI,gCAAgC;IAChC,WAAW;AACf;AACA;IACI,8BAA8B;AAClC;AACA;IACI,kBAAkB;AACtB;AACA;IACI,iBAAiB;AACrB;;AAEA;;6BAE6B;AAC7B;IACI,mBAAmB;IACnB,kBAAkB;IAClB,iBAAiB;IACjB,oBAAoB;AACxB,oBAAoB;IAChB,QAAQ;IACR,aAAa;AACjB;AACA;IACI,aAAa;AACjB;AACA;IACI,iBAAiB;IACjB,kBAAkB;AACtB;AACA;IACI,2CAA2C;IAC3C,YAAY;IACZ,gBAAgB;AACpB;;AAEA;AACA,yBAAyB;AACzB;AACA;IACI,YAAY;IACZ,uBAAuB;IACvB,sBAAsB;AAC1B;AACA;IACI,kBAAkB;IAClB,sBAAsB;AAC1B;;AAEA;IACI,kBAAkB;IAClB,mBAAmB;AACvB;;AAEA;IACI,uBAAuB;AAC3B;AACA;IACI,uBAAuB;IACvB,YAAY;IACZ,kBAAkB;IAClB,uIAAuI;IACvI,wBAAwB;AAC5B;AACA;IACI,gBAAgB;AACpB;AACA;IACI,kBAAkB;IAClB,iBAAiB;IACjB,sBAAsB;IACtB,8BAA8B;IAC9B,+BAA+B;IAC/B,eAAe;IACf,YAAY;IACZ,uBAAuB;AAC3B;;;AAGA,qBAAqB;AACrB;IACI,cAAc;AAClB;AACA;IACI,eAAe;IACf,gBAAgB;AACpB;AACA;IACI,kBAAkB;IAClB,0BAA0B,EAAE,iDAAiD;IAC7E,2BAA2B;AAC/B;;AAEA;IACI,UAAU;AACd;;;AAGA;IACI,UAAU;AACd;;;;;AAKA,0CAA0C;AAC1C;IACI,WAAW;AACf;AACA;IACI,UAAU;AACd;AACA;IACI,YAAY;AAChB;AACA;IACI,kBAAkB;AACtB;AACA;IACI,mBAAmB,EAAE,iBAAiB;AAC1C;AACA;IACI,wBAAwB;IACxB,8BAA8B;AAClC;;;;AAIA;;6BAE6B;AAC7B;IACI,kFAAkF;IAClF,wBAAwB;IACxB,oBAAoB;AACxB;;AAEA;IACI,UAAU;IACV,eAAe;AACnB;AACA;IACI,gBAAgB;IAChB,iBAAiB;AACrB;;AAEA;IACI,WAAW;AACf;AACA;IACI,WAAW;AACf;AACA;IACI,SAAS;IACT,qBAAqB;IACrB,qBAAqB;AACzB;AACA;IACI,WAAW;AACf;AACA;IACI,UAAU;AACd;;AAEA;IACI,UAAU;AACd;;AAEA;IACI,WAAW;AACf;AACA;IACI,WAAW;AACf;;;;;AAKA;IACI,kBAAkB;AACtB;AACA;IACI,cAAc;IACd,gBAAgB;AACpB;AACA;IACI,cAAc;IACd,gBAAgB;AACpB;AACA;IACI,gBAAgB;AACpB;;;AAGA;;6BAE6B;AAC7B;IACI,iBAAiB;AACrB;AACA;IACI,cAAc;AAClB;;AAEA;IACI,yBAAyB;IACzB,oBAAoB;IACpB,sBAAsB;AAC1B;AACA;IACI,oBAAoB;AACxB;AACA;IACI,kBAAkB;IAClB,uBAAuB;IACvB,gBAAgB;AACpB;;AAEA;IACI,qDAAqD;AACzD;AACA;IACI,oDAAoD;AACxD;AACA;IACI,UAAU;IACV,kBAAkB;IAClB,0BAA0B,EAAE,iDAAiD;IAC7E,2BAA2B;AAC/B;AACA;qFACqF;AACrF;IACI,YAAY;AAChB;AACA;IACI,iBAAiB;IACjB,oBAAoB;AACxB;;AAEA,uDAAuD;AACvD;IACI,gBAAgB;IAChB,oBAAoB;AACxB;AACA,oDAAoD;AACpD;;;IAGI,YAAY;IACZ,mBAAmB;AACvB;AACA,qCAAqC;AACrC;;;IAGI,YAAY;IACZ,mBAAmB;AACvB;AACA,kDAAkD;AAClD;;IAEI,YAAY;AAChB;AACA,4CAA4C;AAC5C;;IAEI,YAAY;AAChB;AACA,sBAAsB;AACtB;IACI,2CAA2C;IAC3C,gBAAgB;AACpB;AACA;IACI,2CAA2C;KAC1C,gBAAgB;AACrB;AACA;IACI,0CAA0C;AAC9C;AACA;IACI,gBAAgB;AACpB;AACA;IACI,wHAAwH;IACxH,YAAY;IACZ,WAAW;IACX,eAAe;IACf,gBAAgB;IAChB,YAAY;AAChB;AACA;IACI,4BAA4B;AAChC;;AAEA;IACI,sBAAsB;IACtB,uBAAuB;AAC3B;AACA;IACI,iBAAiB;IACjB,oBAAoB;IACpB,uBAAuB;IACvB,gBAAgB;AACpB;AACA;IACI,4BAA4B;AAChC;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,wBAAwB;IACxB,2BAA2B;IAC3B,mBAAmB;IACnB,cAAc;IACd,kBAAkB;IAClB,sBAAsB;IACtB,qBAAqB;IACrB,gBAAgB;AACpB;AACA;IACI,kCAAkC;IAClC,kBAAkB;AACtB;AACA;IACI,iCAAiC;AACrC;;AAEA;;6BAE6B;;AAE7B;IACI,uBAAuB;IACvB,6CAA6C;;AAEjD;AACA;IACI,6CAA6C;AACjD;;AAEA;IACI,uBAAuB;IACvB,6CAA6C;AACjD;AACA;IACI,6CAA6C;AACjD;;AAEA;IACI,uBAAuB;IACvB,wBAAwB;AAC5B;;AAEA;;6BAE6B;;AAE7B;IACI,gBAAgB;IAChB,UAAU;IACV,kBAAkB;IAClB,cAAc;IACd,gBAAgB;AACpB;AACA;IACI,aAAa;AACjB;AACA;GACG,8BAA8B;GAC9B,kBAAkB;GAClB,UAAU;AACb;;AAEA;;6BAE6B;;AAE7B;IACI,2CAA2C;AAC/C;AACA;IACI,YAAY;AAChB;;;AAGA;;2CAE2C;AAC3C;IACI,UAAU;IACV,SAAS;IACT,cAAc;IACd,aAAa;AACjB;;AAEA;IACI,iBAAiB;AACrB;AACA;GACG,iBAAiB;AACpB;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,cAAc;CACjB,iBAAiB;AAClB;AACA;CACC,gBAAgB;AACjB;;AAEA;IACI,WAAW;IACX,YAAY;IACZ,cAAc;IACd,iBAAiB;AACrB;;AAEA;IACI,iBAAiB;AACrB;;;AAGA,eAAe;AACf;IACI,wBAAwB;AAC5B;;AAEA;IACI,sBAAsB;IACtB,sBAAsB;IACtB,gBAAgB;AACpB;;AAEA;IACI,mBAAmB;IACnB,sBAAsB;AAC1B;;AAEA;IACI,kBAAkB;IAClB,mBAAmB;IACnB,WAAW;IACX,WAAW;AACf;;AAEA;IACI,gBAAgB;AACpB;;AAEA;IACI,kBAAkB;AACtB\",\"sourcesContent\":[\"/*/////////////////////////////\\r\\n/ Welcome bar /\\r\\n////////////////////////////*/\\r\\n.schedule-upload-button{\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align:center;\\r\\n cursor: pointer;\\r\\n}\\r\\n.schedule-upload-button-disabled {\\r\\n color: white;\\r\\n height: 100px;\\r\\n width: 100px;\\r\\n text-align: center;\\r\\n background-color: lightgrey;\\r\\n pointer-events: none;\\r\\n}\\r\\n.schedule-upload-help-button{\\r\\n color: #00AEEF;\\r\\n background-color: white;\\r\\n vertical-align:top;\\r\\n position:absolute;\\r\\n right:0px;\\r\\n}\\r\\n.schedule-upload-help-button-icon{\\r\\n padding-left: 5px;\\r\\n}\\r\\n.fa-lg{\\r\\n font-size: 2.5em;\\r\\n margin-top: 15px;\\r\\n margin-bottom: 5px;\\r\\n}\\r\\n.dynamic-scheduling-welcome{\\r\\n vertical-align: middle;\\r\\n padding-left: 30px;\\r\\n padding-top: 20px;\\r\\n height: 100px;\\r\\n margin-bottom: 0px;\\r\\n}\\r\\n.dynamic-scheduling-welcome-row {\\r\\n margin-top:-5px;\\r\\n border-top: 5px solid rgb(66,74,80);\\r\\n margin-bottom: 0px;\\r\\n background-color: white;\\r\\n}\\r\\n.light-text{\\r\\n color: rgb(189,195, 199);\\r\\n}\\r\\n.schedule-upload-progress-bar {\\r\\n margin: 0;\\r\\n}\\r\\n.schedule-upload-progress-area {\\r\\n background-color: rgb(249,249,249);\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Dashboard\\r\\n /\\r\\n////////////////////////////*/\\r\\n.validation-area{\\r\\n background-color: rgb(249,249,249);\\r\\n height:330px;\\r\\n}\\r\\n.validation-area-title{\\r\\n margin: 10px 0 0 30px;\\r\\n height: 30px;\\r\\n}\\r\\n.validation-errors-summary-card{\\r\\n padding: 25px;\\r\\n margin: 15px 25px 25px 25px;\\r\\n height: 250px;\\r\\n overflow-y: scroll;\\r\\n \\r\\n}\\r\\n.review-button{\\r\\n color: red !important;\\r\\n}\\r\\n.review-button:hover{\\r\\n background-color: #F9F9F9;\\r\\n}\\r\\n\\r\\n.validation-error-stripe{\\r\\n border-left: 5px solid rgb(244, 70, 65);\\r\\n}\\r\\n.validation-warning-stripe{\\r\\n border-left: 5px solid rgb(237,174,73);\\r\\n}\\r\\n.validation-neutral-stripe {\\r\\n border-left: 5px solid;\\r\\n}\\r\\n.validation-success-stripe{\\r\\n border-left: 5px solid;\\r\\n}\\r\\n.summary-cards{\\r\\n margin-top: 15px;\\r\\n margin-left: 35px;\\r\\n}\\r\\n.summary-count-card{\\r\\n height: 110px;\\r\\n padding: 10px 10px 15px 30px;\\r\\n margin: 0 30px 30px 0px;\\r\\n cursor: pointer;\\r\\n}\\r\\n.summary-count-label{\\r\\n height: 40px;\\r\\n}\\r\\n.validation-count > span{\\r\\n font-size: 2em;\\r\\n margin-left: 20px;\\r\\n margin-top: 5px;\\r\\n padding-top: 5px;\\r\\n}\\r\\n.validation-count > * {\\r\\n float: left;\\r\\n display: block;\\r\\n}\\r\\n\\r\\n.validation-asterisk-big{\\r\\n color: rgb(244, 70, 65);\\r\\n font-size: 2em;\\r\\n margin-top: -10px;\\r\\n}\\r\\n.invalid-allegro-points{\\r\\n padding-left: 30px;\\r\\n}\\r\\n.invalid-allegro-points li{\\r\\n list-style-type: disc;\\r\\n}\\r\\n\\r\\n.validation-error-color{\\r\\n color: rgb(244, 70, 65);\\r\\n}\\r\\n.validation-warning-color{\\r\\n color: rgb(237,174,73) !important;\\r\\n}\\r\\n.validation-neutral-color {\\r\\n color: rgb(20, 181, 240);\\r\\n}\\r\\n.validation-success-color{\\r\\n color: rgb(180, 216, 139);\\r\\n}\\r\\n\\r\\n.validation-hour-count-card{\\r\\n height: 110px;\\r\\n min-width: 80px;\\r\\n /*max-width: 120px;*/\\r\\n text-align: center;\\r\\n cursor: pointer;\\r\\n box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);\\r\\n border-radius: 2px;\\r\\n}\\r\\n.limit-warning-count-upper{\\r\\n background-color: rgb(240,189,107);\\r\\n color: white;\\r\\n height: 60%;\\r\\n padding: 10px;\\r\\n}\\r\\n.limit-warning-count-upper span {\\r\\n font-size: 2em;\\r\\n}\\r\\n.limit-warning-count-lower{\\r\\n background-color: rgb(237,174,73);\\r\\n height: 40%;\\r\\n}\\r\\n.limit-error-count-upper{\\r\\n background-color: rgb(246,104,100);\\r\\n color: white;\\r\\n height: 60%;\\r\\n padding: 10px;\\r\\n}\\r\\n.limit-error-count-upper span{\\r\\n font-size: 2em;\\r\\n}\\r\\n.limit-error-count-lower{\\r\\n background-color: rgb(244,70,65);\\r\\n height: 40%;\\r\\n}\\r\\n.hourly-validation-container{\\r\\n padding-right: 30px !important;\\r\\n}\\r\\n.limit-warning-card{\\r\\n margin-right: 10px;\\r\\n}\\r\\n.below-fixed-card{\\r\\n margin-left: 10px;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Schedule header and search bar/\\r\\n////////////////////////////*/\\r\\n.schedule-search-bar{\\r\\n padding-right: 50px;\\r\\n padding-left: 20px;\\r\\n padding-top: 15px;\\r\\n padding-bottom: 15px;\\r\\n/* height: 65px;*/\\r\\n top:82px;\\r\\n z-index: 1020;\\r\\n}\\r\\n.schedule-export{\\r\\n z-index: 1021;\\r\\n}\\r\\n.dropdown-scrollbar{\\r\\n max-height: 250px;\\r\\n overflow-y: scroll;\\r\\n}\\r\\n.clear-customer-search{\\r\\n background-color: rgb(244,70,65) !important;\\r\\n color: white;\\r\\n border-radius: 0;\\r\\n}\\r\\n\\r\\n.schedule-search-bar button{\\r\\n/* padding: 3px 10px;*/\\r\\n}\\r\\n.schedule-search-box{\\r\\n width: 300px;\\r\\n background-color: white;\\r\\n vertical-align: middle;\\r\\n}\\r\\n.schedule-search-box input {\\r\\n padding-left: 10px;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n.schedule-search-icon {\\r\\n padding-left: 30px;\\r\\n padding-right: 30px;\\r\\n}\\r\\n\\r\\n.he-grey{\\r\\n color: rgb(191,193,194);\\r\\n}\\r\\n.schedule-header{\\r\\n background-color: black;\\r\\n color: white;\\r\\n border-style: none;\\r\\n /*If an overflow scroll bar is used, add 17px to the right padding for the scrollbar in the table body to properly line up the headers*/\\r\\n padding: 0px 30px 0 35px; \\r\\n}\\r\\n.schedule-header table{\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.schedule-header td.schedule-header-cell {\\r\\n border-style: none;\\r\\n font-weight: bold;\\r\\n vertical-align: bottom;\\r\\n border-left: 1px solid #3F474D;\\r\\n border-right: 1px solid #3F474D;\\r\\n padding-top:5px;\\r\\n color: white;\\r\\n background-color: black;\\r\\n}\\r\\n\\r\\n\\r\\n/* have to undo mdb */\\r\\n.header-filter a{\\r\\n margin-left: 0;\\r\\n}\\r\\n.schedule-header .he-table-cell{\\r\\n padding-left: 0;\\r\\n padding-right: 0;\\r\\n}\\r\\n.he-table-cell{\\r\\n text-align: center;\\r\\n padding-left: 0 !important; /* Have to overwrite bootstrap, it's a tight fit*/\\r\\n padding-right: 0 !important;\\r\\n}\\r\\n\\r\\n.schedule-upload-table .he-table-cell{\\r\\n width:2.6%;\\r\\n}\\r\\n\\r\\n\\r\\n.schedule-upload-table .customer-table-cell{\\r\\n width: 15%;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n/* the next two need to sum to the third */\\r\\n.flowdate-table-cell{\\r\\n width: 7.6%;\\r\\n}\\r\\n.schedule-label-table-cell{\\r\\n width: 15%;\\r\\n}\\r\\n.flowdate-table-header{\\r\\n width: 22.6%;\\r\\n}\\r\\n.flowdate-header-text{\\r\\n width: 33.6283185%;\\r\\n}\\r\\n.flowdate-header-filter{\\r\\n width: 66.37168141%; /* 15/22.6 */\\r\\n}\\r\\n.filter-button{\\r\\n padding: 4px 6px 4px 6px;\\r\\n margin-bottom: -5px !important;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Archive Tables /\\r\\n////////////////////////////*/\\r\\ntd.schedule-table-cell-gray-bg{\\r\\n /* This gives the td the same color background and border as the body background */\\r\\n background-color:#F2F2F2;\\r\\n border-color:#F2F2F2;\\r\\n}\\r\\n\\r\\n.scrollable-schedule-container{\\r\\n width:100%;\\r\\n overflow-x:auto;\\r\\n}\\r\\n.scrollable-schedule-content{\\r\\n min-width:1900px;\\r\\n overflow-y:hidden;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .final-table-cell{\\r\\n width: 2.4%;\\r\\n}\\r\\n.schedule-archive-table .timestamp-table-cell{\\r\\n width: 5.5%;\\r\\n}\\r\\n.schedule-archive-table .customer-table-cell{\\r\\n width: 7%;\\r\\n word-wrap: break-word;\\r\\n word-break: break-all;\\r\\n}\\r\\n.schedule-archive-table .flowdate-table-cell{\\r\\n width: 4.3%;\\r\\n}\\r\\n.schedule-archive-table .schedule-label-table-cell{\\r\\n width:6.7%;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .he-table-cell{\\r\\n width:2.4%;\\r\\n}\\r\\n\\r\\n.schedule-archive-table .dow-table-cell{\\r\\n width: 3.4%;\\r\\n}\\r\\n.schedule-archive-table .submitter-table-cell{\\r\\n width:13.1%;\\r\\n}\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n.schedule-timestamp{\\r\\n text-align: center;\\r\\n}\\r\\n.schedule-timestamp-month{\\r\\n font-size:14px;\\r\\n font-weight:bold;\\r\\n}\\r\\n.schedule-timestamp-day{\\r\\n font-size:18px;\\r\\n font-weight:bold;\\r\\n}\\r\\n.schedule-timestamp-year{\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n\\r\\n/*/////////////////////////////\\r\\n/ Schedule Tables /\\r\\n////////////////////////////*/\\r\\n.schedule-lock i{\\r\\n font-size: 1.75em;\\r\\n}\\r\\n.schedule-lock .fa-pencil{\\r\\n color: #5aad00;\\r\\n}\\r\\n\\r\\n.schedule-upload-area{\\r\\n padding: 0 30px 30px 35px;\\r\\n margin-bottom: -10px; \\r\\n box-sizing: border-box;\\r\\n}\\r\\n.schedule-grey{\\r\\n color: rgb(66,74,80);\\r\\n}\\r\\n.validation-asterisk{\\r\\n padding-left: 20px;\\r\\n color: rgb(244, 70, 65);\\r\\n font-size: 1.3em;\\r\\n}\\r\\n\\r\\ntd.hourly-validation-error, .hourly-validation-error td{\\r\\n border-bottom: 10px solid rgb(244, 70, 65) !important;\\r\\n}\\r\\n.hourly-validation-warning{\\r\\n border-bottom: 10px solid rgb(252,186,77) !important;\\r\\n}\\r\\n.he-table-cell{\\r\\n width:2.6%;\\r\\n text-align: center;\\r\\n padding-left: 0 !important; /* Have to overwrite bootstrap, it's a tight fit*/\\r\\n padding-right: 0 !important;\\r\\n}\\r\\n/* force every HE cell in the customer to be 46px. Otherwise, it would be impossible to format all the \\r\\n highlighting due to the limit/fixed warning border only sometimes being present */\\r\\n.customer-he-cell{\\r\\n height: 46px;\\r\\n}\\r\\n.he-table-cell > div > div{\\r\\n padding-top: 12px;\\r\\n padding-bottom: 12px;\\r\\n}\\r\\n\\r\\n/* padding changes when the dirty highlight is present*/\\r\\n.he-table-cell.he-highlight-dirty > div > div {\\r\\n padding-top: 9px;\\r\\n padding-bottom: 14px;\\r\\n}\\r\\n/* input height if validation border is NOT present*/\\r\\n.he-highlight-active .edit-he-input,\\r\\n.he-highlight-active .edit-he-input\\r\\n {\\r\\n height: 42px;\\r\\n padding-bottom: 7px;\\r\\n}\\r\\n/* input height if border is present*/\\r\\n.he-highlight-active.hourly-validation-error .edit-he-input,\\r\\n.he-highlight-active.hourly-validation-warning .edit-he-input\\r\\n {\\r\\n height: 36px;\\r\\n padding-bottom: 2px;\\r\\n}\\r\\n/* highlight box height if border is not present */\\r\\n.he-highlight-active > div,\\r\\n.he-highlight-dirty > div{\\r\\n height: 45px;\\r\\n}\\r\\n/* highlight box height if boder IS present*/\\r\\n.he-highlight-active.hourly-validation-warning > div, .he-highlight-active.hourly-validation-error > div,\\r\\n.he-highlight-dirty.hourly-validation-warning > div, .he-highlight-dirty.hourly-validation-error > div{\\r\\n height: 40px;\\r\\n}\\r\\n/*Actual highlighting*/\\r\\n.he-highlight-active > div{\\r\\n border: 2px solid rgb(0,176,238) !important;\\r\\n /*height: 45px;*/\\r\\n}\\r\\n.he-highlight-dirty > div{\\r\\n border: 3px solid rgb(88,173,75) !important;\\r\\n /*height: 45px;*/\\r\\n}\\r\\n.he-highlight-error {\\r\\n border: 3px solid rgb(255,0,56) !important;\\r\\n}\\r\\n.he-highlight-active input.middle:focus {\\r\\n outline-width: 0;\\r\\n}\\r\\n.save-schedules-btn{\\r\\n /* this is all copied from mdb .fixed-action-btn - the associated mdb JS was erroring with zone js for unknown reasons */\\r\\n bottom: 45px; \\r\\n right: 24px;\\r\\n position: fixed;\\r\\n margin-bottom: 0;\\r\\n z-index: 998;\\r\\n}\\r\\n.save-schedules-btn.active{\\r\\n background-color:transparent;\\r\\n}\\r\\n\\r\\n.uploaded-schedule-table{\\r\\n box-sizing: border-box;\\r\\n background-color: white;\\r\\n}\\r\\n.dashed-line {\\r\\n border-width: 1px;\\r\\n border-style: dashed;\\r\\n border-color: gainsboro;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n.schedule-upload-card{\\r\\n padding: 30px 30px 30px 30px;\\r\\n}\\r\\n\\r\\n.hour-validation-count{\\r\\n width: 30px;\\r\\n height: 30px;\\r\\n color: white;\\r\\n -moz-border-radius: 15px;\\r\\n -webkit-border-radius: 15px;\\r\\n border-radius: 15px;\\r\\n display: block;\\r\\n text-align: center;\\r\\n vertical-align: middle;\\r\\n display: inline-block;\\r\\n padding-top: 5px;\\r\\n}\\r\\n.hour-error-count{\\r\\n background-color: rgb(244, 70, 65);\\r\\n margin-left: -10px;\\r\\n} \\r\\n.hour-warning-count{\\r\\n background-color: rgb(252,186,77);\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// Tooltips //\\r\\n////////////////////////////*/\\r\\n\\r\\n.dyn-schedule-tooltip-error .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color: rgb(246,104,100) !important;\\r\\n\\r\\n}\\r\\n.dyn-schedule-tooltip-error .tooltip-arrow{\\r\\n border-top-color: rgb(246,104,100) !important;\\r\\n}\\r\\n\\r\\n.dyn-schedule-tooltip-warning .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color: rgb(240,189,107) !important;\\r\\n}\\r\\n.dyn-schedule-tooltip-warning .tooltip-arrow{\\r\\n border-top-color: rgb(240,189,107) !important;\\r\\n}\\r\\n\\r\\n.dyn-schedule-tooltip-he-truncation .tooltip-inner{\\r\\n color: white !important;\\r\\n background-color:#3F474D;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// Error Splashscreen //\\r\\n////////////////////////////*/\\r\\n\\r\\n.error-card {\\r\\n max-width: 500px;\\r\\n width: 85%;\\r\\n text-align: center;\\r\\n margin: 0 auto;\\r\\n margin-top: 75px; \\r\\n}\\r\\n.error-card-container {\\r\\n padding: 50px;\\r\\n}\\r\\n.error-btn {\\r\\n background: #939BA1 !important;\\r\\n margin-bottom: 2px;\\r\\n width: 80%;\\r\\n}\\r\\n\\r\\n/*/////////////////////////////\\r\\n// High Warning Dialog //\\r\\n////////////////////////////*/\\r\\n\\r\\n.dialog-header {\\r\\n background-color: RGB(0,174,239) !important;\\r\\n}\\r\\n.modal-title {\\r\\n color: white;\\r\\n}\\r\\n\\r\\n\\r\\n/*///////////////////////////////////////////\\r\\n// Dashboard and Search fixed to top //\\r\\n//////////////////////////////////////////*/\\r\\n.fixed-schedule-upload-dashboard{\\r\\n width:100%;\\r\\n top:127px;\\r\\n position:fixed; \\r\\n z-index: 1020;\\r\\n}\\r\\n\\r\\n.schedule-upload-list-db-expanded{\\r\\n padding-top:585px; \\r\\n}\\r\\n.schedule-upload-list-db-collapsed{\\r\\n padding-top:245px;\\r\\n}\\r\\n\\r\\n.schedule-upload-container .schedule-header {\\r\\n width: 100%; \\r\\n z-index:1020; \\r\\n position:fixed;\\r\\n /* top:617px; */\\r\\n}\\r\\n.schedule-upload-area{\\r\\n min-height:300px;\\r\\n}\\r\\n\\r\\n.schedule-archive-container .schedule-header {\\r\\n width: 100%; \\r\\n z-index:1020; \\r\\n position:fixed;\\r\\n min-width: 1900px;\\r\\n}\\r\\n\\r\\n.schedule-archive-list{\\r\\n padding-top:225px;\\r\\n}\\r\\n\\r\\n\\r\\n/* DATEPICKER */\\r\\n.ui-datepicker{\\r\\n z-index: 1020 !important;\\r\\n}\\r\\n\\r\\n.schedule-date-filter-input-box{\\r\\n background-color:white;\\r\\n vertical-align: middle;\\r\\n margin-bottom: 0;\\r\\n}\\r\\n\\r\\n.schedule-date-filter-input-box input {\\r\\n font-weight: normal;\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\n.schedule-date-range-filter-container{\\r\\n padding-left: 15px;\\r\\n padding-right: 15px;\\r\\n width:500px;\\r\\n height:60px;\\r\\n}\\r\\n\\r\\n.daterange-clear-btn{\\r\\n padding-top:15px;\\r\\n}\\r\\n\\r\\n.schedule-preload-spinner-top {\\r\\n padding-top: 250px;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".active-blue-tab {\\r\\n color: #0026ff;\\r\\n}\\r\\n.active-black-tab {\\r\\n color: #000000;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/dynamic-scheduling/shared/dynamic-scheduling.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,cAAc;AAClB;AACA;IACI,cAAc;AAClB\",\"sourcesContent\":[\".active-blue-tab {\\r\\n color: #0026ff;\\r\\n}\\r\\n.active-black-tab {\\r\\n color: #000000;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nimport ___CSS_LOADER_GET_URL_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/getUrl.js\";\nimport ___CSS_LOADER_URL_IMPORT_0___ from \"../../assets/home_background.jpg\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\nvar ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".body-home-background {\\r\\n background-image: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \");\\r\\n background-repeat: no-repeat;\\r\\n background-position: center center;\\r\\n background-attachment: fixed;\\r\\n background-size: cover;\\r\\n min-height: 100%\\r\\n}\\r\\n\\r\\n.white-text {\\r\\n color: white;\\r\\n}\\r\\n\\r\\n.home-title-font {\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 65px;\\r\\n line-height: 1;\\r\\n font-weight: 300;\\r\\n text-transform: uppercase;\\r\\n text-shadow: 0px 1px 10px rgba(150, 150, 150, 1);\\r\\n}\\r\\n.gray-box {\\r\\n background: linear-gradient(to right, #262627, #1a2129);\\r\\n background-image: linear-gradient(to right, rgba(38,38,39,1), rgba(26,33,41,0));\\r\\n position: absolute;\\r\\n top: 40%;\\r\\n display: inline-block;\\r\\n padding: 40px;\\r\\n}\\r\\n\\r\\n.home-tile-title {\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 26px;\\r\\n line-height: 1;\\r\\n text-transform: uppercase;\\r\\n font-weight: 300;\\r\\n}\\r\\n\\r\\n.home-horizontal-line {\\r\\n width: 15%;\\r\\n color: #5AAD00;\\r\\n margin-left: 0px;\\r\\n height: 8px;\\r\\n background-color: #5AAD00;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.home-left-margin {\\r\\n margin-left: 30px;\\r\\n}\\r\\n\\r\\n.home-tiles-border {\\r\\n border-top-color: rgba(255, 255, 255, 0.23);\\r\\n border-bottom-color: rgba(3, 3, 3, 0.23);\\r\\n border-left-color: rgba(3, 3, 3, 0.23);\\r\\n border-right-color: rgba(3, 3, 3, 0.23);\\r\\n border-width: 2px;\\r\\n border-style: solid;\\r\\n height: 300px;\\r\\n width: 400px;\\r\\n background-color: rgba(0, 0, 0, 0.15);\\r\\n}\\r\\n.home-tile-buttons {\\r\\n border-style: none;\\r\\n height: 40px;\\r\\n width: 90%;\\r\\n text-align: left;\\r\\n}\\r\\n.bullet-points{\\r\\n list-style-type: disc!important;\\r\\n}\\r\\n.bullet-points-padding{\\r\\n -webkit-padding-start: 40px;\\r\\n}\\r\\n#terms-conditions .text-blue{\\r\\n color: #0063a8 !important;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/home/home.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,yDAAyD;IACzD,4BAA4B;IAC5B,kCAAkC;IAClC,4BAA4B;IAC5B,sBAAsB;IACtB;AACJ;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,gBAAgB;IAChB,yBAAyB;IACzB,gDAAgD;AACpD;AACA;IACI,uDAAuD;IACvD,+EAA+E;IAC/E,kBAAkB;IAClB,QAAQ;IACR,qBAAqB;IACrB,aAAa;AACjB;;AAEA;IACI,oCAAoC;IACpC,eAAe;IACf,cAAc;IACd,yBAAyB;IACzB,gBAAgB;AACpB;;AAEA;IACI,UAAU;IACV,cAAc;IACd,gBAAgB;IAChB,WAAW;IACX,yBAAyB;IACzB,gBAAgB;AACpB;;AAEA;IACI,iBAAiB;AACrB;;AAEA;IACI,2CAA2C;IAC3C,wCAAwC;IACxC,sCAAsC;IACtC,uCAAuC;IACvC,iBAAiB;IACjB,mBAAmB;IACnB,aAAa;IACb,YAAY;IACZ,qCAAqC;AACzC;AACA;IACI,kBAAkB;IAClB,YAAY;IACZ,UAAU;IACV,gBAAgB;AACpB;AACA;KACK,+BAA+B;AACpC;AACA;KACK,2BAA2B;AAChC;AACA;IACI,yBAAyB;AAC7B\",\"sourcesContent\":[\".body-home-background {\\r\\n background-image: url(\\\"../../assets/home_background.jpg\\\");\\r\\n background-repeat: no-repeat;\\r\\n background-position: center center;\\r\\n background-attachment: fixed;\\r\\n background-size: cover;\\r\\n min-height: 100%\\r\\n}\\r\\n\\r\\n.white-text {\\r\\n color: white;\\r\\n}\\r\\n\\r\\n.home-title-font {\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 65px;\\r\\n line-height: 1;\\r\\n font-weight: 300;\\r\\n text-transform: uppercase;\\r\\n text-shadow: 0px 1px 10px rgba(150, 150, 150, 1);\\r\\n}\\r\\n.gray-box {\\r\\n background: linear-gradient(to right, #262627, #1a2129);\\r\\n background-image: linear-gradient(to right, rgba(38,38,39,1), rgba(26,33,41,0));\\r\\n position: absolute;\\r\\n top: 40%;\\r\\n display: inline-block;\\r\\n padding: 40px;\\r\\n}\\r\\n\\r\\n.home-tile-title {\\r\\n font-family: 'Open Sans', sans-serif;\\r\\n font-size: 26px;\\r\\n line-height: 1;\\r\\n text-transform: uppercase;\\r\\n font-weight: 300;\\r\\n}\\r\\n\\r\\n.home-horizontal-line {\\r\\n width: 15%;\\r\\n color: #5AAD00;\\r\\n margin-left: 0px;\\r\\n height: 8px;\\r\\n background-color: #5AAD00;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.home-left-margin {\\r\\n margin-left: 30px;\\r\\n}\\r\\n\\r\\n.home-tiles-border {\\r\\n border-top-color: rgba(255, 255, 255, 0.23);\\r\\n border-bottom-color: rgba(3, 3, 3, 0.23);\\r\\n border-left-color: rgba(3, 3, 3, 0.23);\\r\\n border-right-color: rgba(3, 3, 3, 0.23);\\r\\n border-width: 2px;\\r\\n border-style: solid;\\r\\n height: 300px;\\r\\n width: 400px;\\r\\n background-color: rgba(0, 0, 0, 0.15);\\r\\n}\\r\\n.home-tile-buttons {\\r\\n border-style: none;\\r\\n height: 40px;\\r\\n width: 90%;\\r\\n text-align: left;\\r\\n}\\r\\n.bullet-points{\\r\\n list-style-type: disc!important;\\r\\n}\\r\\n.bullet-points-padding{\\r\\n -webkit-padding-start: 40px;\\r\\n}\\r\\n#terms-conditions .text-blue{\\r\\n color: #0063a8 !important;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"td.leafNodeBreadCrumb a{\\n color: #5AAD00;\\r\\n}\\r\\n\\r\\n.breadCrumbPath a{\\r\\n color: #939BA1;\\r\\n}\\n\\r\\n.breadCrumbSeperator{\\r\\n color: #939BA1;\\r\\n}\\r\\n\\r\\n.breadCrumbHeight{\\r\\n height:40px;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/breadcrumb/breadcrumb.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,eAAe;AACnB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,cAAc;AAClB;;AAEA;KACK,WAAW;AAChB\",\"sourcesContent\":[\"td.leafNodeBreadCrumb a{\\n color: #5AAD00;\\r\\n}\\r\\n\\r\\n.breadCrumbPath a{\\r\\n color: #939BA1;\\r\\n}\\n\\r\\n.breadCrumbSeperator{\\r\\n color: #939BA1;\\r\\n}\\r\\n\\r\\n.breadCrumbHeight{\\r\\n height:40px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"ngb-datepicker .ngb-dp-header {\\r\\n /* Changes the background color of the month/year header */\\r\\n background-color: #3468bf;\\r\\n}\\r\\n\\r\\nngb-datepicker select {\\r\\n /* Changes the background color of the month/year dropdowns */\\r\\n background-color: #3468bf;\\r\\n color: white;\\r\\n}\\r\\n\\r\\nngb-datepicker .ngb-dp-content .btn-info.active {\\r\\n /* Changes the background color of the selected/active date */\\r\\n background-color: #28a745;\\r\\n border-color: #28a745;\\r\\n}\\r\\n\\r\\nngb-datepicker {\\r\\n background-color: lightblue;\\r\\n}\\r\\n\\r\\nngb-datepicker .ngb-dp-day{\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-input {\\r\\n width: 150px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-btn {\\r\\n padding-left: 5px;\\r\\n padding-right: 5px;\\r\\n padding-top: 0px;\\r\\n padding-bottom: 0px;\\r\\n margin-top: 0px;\\r\\n margin-bottom: 0px;\\r\\n font-size: 20px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-btn-color {\\r\\n color: #5AAD00;\\r\\n}\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/datepicker/datepicker-popup.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,8DAA8D;IAC9D,yBAAyB;AAC7B;;AAEA;IACI,iEAAiE;IACjE,yBAAyB;IACzB,YAAY;AAChB;;AAEA;IACI,iEAAiE;IACjE,yBAAyB;IACzB,qBAAqB;AACzB;;AAEA;IACI,2BAA2B;AAC/B;;AAEA;IACI,eAAe;AACnB;;AAEA;IACI,YAAY;AAChB;;AAEA;IACI,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,eAAe;IACf,kBAAkB;IAClB,eAAe;AACnB;;AAEA;IACI,cAAc;AAClB\",\"sourcesContent\":[\"ngb-datepicker .ngb-dp-header {\\r\\n /* Changes the background color of the month/year header */\\r\\n background-color: #3468bf;\\r\\n}\\r\\n\\r\\nngb-datepicker select {\\r\\n /* Changes the background color of the month/year dropdowns */\\r\\n background-color: #3468bf;\\r\\n color: white;\\r\\n}\\r\\n\\r\\nngb-datepicker .ngb-dp-content .btn-info.active {\\r\\n /* Changes the background color of the selected/active date */\\r\\n background-color: #28a745;\\r\\n border-color: #28a745;\\r\\n}\\r\\n\\r\\nngb-datepicker {\\r\\n background-color: lightblue;\\r\\n}\\r\\n\\r\\nngb-datepicker .ngb-dp-day{\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-input {\\r\\n width: 150px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-btn {\\r\\n padding-left: 5px;\\r\\n padding-right: 5px;\\r\\n padding-top: 0px;\\r\\n padding-bottom: 0px;\\r\\n margin-top: 0px;\\r\\n margin-bottom: 0px;\\r\\n font-size: 20px;\\r\\n}\\r\\n\\r\\n.datepicker-popup-btn-color {\\r\\n color: #5AAD00;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"\\r\\n.button-nav {\\r\\n background: #939BA1;\\r\\n padding: 20px 80px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 16px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n }\\r\\n.button-nav:hover {\\r\\n background: #A4A6A8;\\r\\n color: #fff;\\r\\n }\\r\\n.button-nav:active {\\r\\n background: #B3B3B3;\\r\\n color: #fff;\\r\\n }\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/footer/footer.component.css\"],\"names\":[],\"mappings\":\";AACA;GACG,mBAAmB;GACnB,kBAAkB;GAClB,kBAAkB;GAClB,cAAc;GACd,eAAe;GACf,kCAAkC;GAClC,qBAAqB;GACrB,sBAAsB;GACtB;AACH;GACG,mBAAmB;GACnB,WAAW;GACX;AACH;GACG,mBAAmB;GACnB,WAAW;GACX\",\"sourcesContent\":[\"\\r\\n.button-nav {\\r\\n background: #939BA1;\\r\\n padding: 20px 80px;\\r\\n border-radius: 2px;\\r\\n color: #ffffff;\\r\\n font-size: 16px;\\r\\n font-family: open sans, sans-serif;\\r\\n text-decoration: none;\\r\\n vertical-align: middle;\\r\\n }\\r\\n.button-nav:hover {\\r\\n background: #A4A6A8;\\r\\n color: #fff;\\r\\n }\\r\\n.button-nav:active {\\r\\n background: #B3B3B3;\\r\\n color: #fff;\\r\\n }\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nimport ___CSS_LOADER_GET_URL_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/getUrl.js\";\nimport ___CSS_LOADER_URL_IMPORT_0___ from \"../../../assets/Gray/Power-Manager-gray.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_1___ from \"../../../assets/Blue/Power-Manager-blue.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_2___ from \"../../../assets/Gray/Billing-gray.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_3___ from \"../../../assets/Blue/Billing-blue.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_4___ from \"../../../assets/Gray/Administration-gray.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_5___ from \"../../../assets/Blue/Administration-blue.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_6___ from \"../../../assets/Gray/Impersonate-gray.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_7___ from \"../../../assets/Blue/Impersonate-blue.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_8___ from \"../../../assets/Gray/Reports-gray.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_9___ from \"../../../assets/Blue/Reports-blue.jpg\";\nimport ___CSS_LOADER_URL_IMPORT_10___ from \"../../../assets/Gray/Reports-grayed-out.jpg\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\nvar ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);\nvar ___CSS_LOADER_URL_REPLACEMENT_1___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_1___);\nvar ___CSS_LOADER_URL_REPLACEMENT_2___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_2___);\nvar ___CSS_LOADER_URL_REPLACEMENT_3___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_3___);\nvar ___CSS_LOADER_URL_REPLACEMENT_4___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_4___);\nvar ___CSS_LOADER_URL_REPLACEMENT_5___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_5___);\nvar ___CSS_LOADER_URL_REPLACEMENT_6___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_6___);\nvar ___CSS_LOADER_URL_REPLACEMENT_7___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_7___);\nvar ___CSS_LOADER_URL_REPLACEMENT_8___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_8___);\nvar ___CSS_LOADER_URL_REPLACEMENT_9___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_9___);\nvar ___CSS_LOADER_URL_REPLACEMENT_10___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_10___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".flex-container {\\r\\n height: 82px;\\r\\n display:flex;\\r\\n border: 1px solid lightgray;\\r\\n border-collapse: collapse;\\r\\n text-align: center; \\r\\n background-color: white;\\r\\n}\\r\\n\\r\\n.logo {\\r\\n flex: 0 0 75px;\\r\\n width: 75px;\\r\\n}\\r\\n\\r\\n.menu-button {\\r\\n flex: 0 0 175px;\\r\\n width: 175px;\\r\\n}\\r\\n\\r\\n.user-button {\\r\\n position:relative;\\r\\n padding-top: 20px;\\r\\n text-align: right;\\r\\n padding-right: 20px;\\r\\n}\\r\\n\\r\\n.impersonate-note {\\r\\n font-weight: 900;\\r\\n color: #ff0000;\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.user-button .dropdown-menu { \\r\\n font-size: 12px; \\r\\n min-width: 120px; \\r\\n left: auto; \\r\\n right: 2px; \\r\\n top: 80%;\\r\\n}\\r\\n\\r\\n.user-name {\\r\\n font-weight: bold;\\r\\n}\\r\\n\\r\\n.user-name a, a:focus, a:hover{\\r\\n color: #00AEEF;\\r\\n font-weight: bold;\\r\\n}\\r\\n\\r\\n.spacing {\\r\\n flex: 1;\\r\\n}\\r\\n\\r\\n.active{\\r\\n background-color: white; \\r\\n}\\r\\n.header-button {\\r\\n /* width: 13% auto; */\\r\\n}\\r\\n\\r\\n.header-button a {\\r\\n display: block;\\r\\n /*width: 100%; */\\r\\n color: #3F474D;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n.header-button .btn {\\r\\n /* width: 100%; */\\r\\n height: 100%;\\r\\n margin: 0;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n}\\r\\n\\r\\n.header-button:hover {\\r\\n background: -moz-linear-gradient(top, rgba(255,255,255,1) 16%, rgba(255,255,255,0) 79%, rgba(255,255,255,0) 88%); /* FF3.6-15 */\\r\\n background: -webkit-linear-gradient(top, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* Chrome10-25,Safari5.1-6 */\\r\\n background: linear-gradient(to bottom, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */\\r\\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */\\r\\n background-color: #E3E3E3;\\r\\n}\\r\\n.active-header-button {\\r\\n background: -moz-linear-gradient(top, rgba(255,255,255,1) 16%, rgba(255,255,255,0) 79%, rgba(255,255,255,0) 88%); /* FF3.6-15 */\\r\\n background: -webkit-linear-gradient(top, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* Chrome10-25,Safari5.1-6 */\\r\\n background: linear-gradient(to bottom, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */\\r\\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */\\r\\n background-color: #E3E3E3;\\r\\n}\\r\\n.header-logo {\\r\\n width: 75px;\\r\\n}\\r\\n.header-div {\\r\\n padding-top: 5px;\\r\\n}\\r\\n.power-manager {\\r\\n padding-top: 5px;\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.power-manager-enabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \") no-repeat center;\\r\\n}\\r\\n.power-manager-enabled:hover,\\r\\n.power-manager-active {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_1___ + \") no-repeat center;\\r\\n}\\r\\n.billing {\\r\\n padding-top: 5px;\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.billing-enabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_2___ + \") no-repeat center;\\r\\n}\\r\\n.billing-enabled:hover,\\r\\n.billing-active {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_3___ + \") no-repeat center;\\r\\n}\\r\\n.administration {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.administration-enabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_4___ + \") no-repeat center;\\r\\n}\\r\\n.administration-enabled:hover,\\r\\n.administration-active {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_5___ + \") no-repeat center;\\r\\n}\\r\\n\\r\\n.impersonate {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n\\r\\n/*Need to fix, need a blue and grey clipart for Impersonate*/\\r\\n.impersonate-enabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_6___ + \") no-repeat center;\\r\\n}\\r\\n\\r\\n.impersonate-enabled:hover,\\r\\n.impersonate-active {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_7___ + \") no-repeat center;\\r\\n}\\r\\n\\r\\n.reports {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.reports-enabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_8___ + \") no-repeat center;\\r\\n}\\r\\n.reports-enabled:hover,\\r\\n.reports-active {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_9___ + \") no-repeat center;\\r\\n}\\r\\n.reports-disabled {\\r\\n background: url(\" + ___CSS_LOADER_URL_REPLACEMENT_10___ + \") no-repeat center;\\r\\n pointer-events:none;\\r\\n}\\r\\n\\r\\n.dropdown-nav {\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.dropdown-nav.dropdown-enabled {\\r\\n position: absolute;\\r\\n top: 80px;\\r\\n width: fit-content;\\r\\n min-width: 175px;\\r\\n background: #ffffff;\\r\\n border: solid 1px rgba(0, 0, 0, 0.1);\\r\\n}\\r\\n\\r\\n.header-div:hover .dropdown-nav.dropdown-enabled {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n flex-wrap: nowrap;\\r\\n align-items: flex-start;\\r\\n}\\r\\n\\r\\n.dropdown-nav > a {\\r\\n text-align: left;\\r\\n flex: 1;\\r\\n text-transform: uppercase;\\r\\n padding: 10px;\\r\\n display: block;\\r\\n width: 100%;\\r\\n}\\r\\n\\r\\n.dropdown-nav > a:hover {\\r\\n background: rgba(0,0,0,0.1);\\r\\n color: #069 !important;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/nav-menu/nav-menu.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,YAAY;IACZ,YAAY;IACZ,2BAA2B;IAC3B,yBAAyB;IACzB,kBAAkB;IAClB,uBAAuB;AAC3B;;AAEA;IACI,cAAc;IACd,WAAW;AACf;;AAEA;IACI,eAAe;IACf,YAAY;AAChB;;AAEA;IACI,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;AACvB;;AAEA;IACI,gBAAgB;IAChB,cAAc;IACd,eAAe;AACnB;;AAEA;KACK,eAAe;KACf,gBAAgB;KAChB,UAAU;KACV,UAAU;KACV,QAAQ;AACb;;AAEA;IACI,iBAAiB;AACrB;;AAEA;IACI,cAAc;IACd,iBAAiB;AACrB;;AAEA;IACI,OAAO;AACX;;AAEA;IACI,uBAAuB;AAC3B;AACA;IACI,sBAAsB;AAC1B;;AAEA;IACI,cAAc;IACd,iBAAiB;IACjB,cAAc;IACd,gBAAgB;AACpB;;AAEA;GACG,mBAAmB;IAClB,YAAY;IACZ,SAAS;IACT,UAAU;IACV,SAAS;AACb;;AAEA;IACI,iHAAiH,EAAE,aAAa;IAChI,kHAAkH,EAAE,4BAA4B;IAChJ,gHAAgH,EAAE,qDAAqD;IACvK,qHAAqH,EAAE,UAAU;IACjI,yBAAyB;AAC7B;AACA;IACI,iHAAiH,EAAE,aAAa;IAChI,kHAAkH,EAAE,4BAA4B;IAChJ,gHAAgH,EAAE,qDAAqD;IACvK,qHAAqH,EAAE,UAAU;IACjI,yBAAyB;AAC7B;AACA;IACI,WAAW;AACf;AACA;IACI,gBAAgB;AACpB;AACA;IACI,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,YAAY;AAChB;AACA;IACI,oEAA6E;AACjF;AACA;;IAEI,oEAA6E;AACjF;AACA;IACI,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,YAAY;AAChB;AACA;IACI,oEAAuE;AAC3E;AACA;;IAEI,oEAAuE;AAC3E;AACA;IACI,cAAc;IACd,YAAY;IACZ,YAAY;AAChB;AACA;IACI,oEAA8E;AAClF;AACA;;IAEI,oEAA8E;AAClF;;AAEA;IACI,cAAc;IACd,YAAY;IACZ,YAAY;AAChB;;AAEA,4DAA4D;AAC5D;IACI,oEAA2E;AAC/E;;AAEA;;IAEI,oEAA2E;AAC/E;;AAEA;IACI,cAAc;IACd,YAAY;IACZ,YAAY;AAChB;AACA;IACI,oEAAuE;AAC3E;AACA;;IAEI,oEAAuE;AAC3E;AACA;IACI,qEAA6E;IAC7E,mBAAmB;AACvB;;AAEA;IACI,aAAa;AACjB;;AAEA;IACI,kBAAkB;IAClB,SAAS;IACT,kBAAkB;IAClB,gBAAgB;IAChB,mBAAmB;IACnB,oCAAoC;AACxC;;AAEA;IACI,aAAa;IACb,sBAAsB;IACtB,iBAAiB;IACjB,uBAAuB;AAC3B;;AAEA;IACI,gBAAgB;IAChB,OAAO;IACP,yBAAyB;IACzB,aAAa;IACb,cAAc;IACd,WAAW;AACf;;AAEA;IACI,2BAA2B;IAC3B,sBAAsB;AAC1B\",\"sourcesContent\":[\".flex-container {\\r\\n height: 82px;\\r\\n display:flex;\\r\\n border: 1px solid lightgray;\\r\\n border-collapse: collapse;\\r\\n text-align: center; \\r\\n background-color: white;\\r\\n}\\r\\n\\r\\n.logo {\\r\\n flex: 0 0 75px;\\r\\n width: 75px;\\r\\n}\\r\\n\\r\\n.menu-button {\\r\\n flex: 0 0 175px;\\r\\n width: 175px;\\r\\n}\\r\\n\\r\\n.user-button {\\r\\n position:relative;\\r\\n padding-top: 20px;\\r\\n text-align: right;\\r\\n padding-right: 20px;\\r\\n}\\r\\n\\r\\n.impersonate-note {\\r\\n font-weight: 900;\\r\\n color: #ff0000;\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.user-button .dropdown-menu { \\r\\n font-size: 12px; \\r\\n min-width: 120px; \\r\\n left: auto; \\r\\n right: 2px; \\r\\n top: 80%;\\r\\n}\\r\\n\\r\\n.user-name {\\r\\n font-weight: bold;\\r\\n}\\r\\n\\r\\n.user-name a, a:focus, a:hover{\\r\\n color: #00AEEF;\\r\\n font-weight: bold;\\r\\n}\\r\\n\\r\\n.spacing {\\r\\n flex: 1;\\r\\n}\\r\\n\\r\\n.active{\\r\\n background-color: white; \\r\\n}\\r\\n.header-button {\\r\\n /* width: 13% auto; */\\r\\n}\\r\\n\\r\\n.header-button a {\\r\\n display: block;\\r\\n /*width: 100%; */\\r\\n color: #3F474D;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n.header-button .btn {\\r\\n /* width: 100%; */\\r\\n height: 100%;\\r\\n margin: 0;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n}\\r\\n\\r\\n.header-button:hover {\\r\\n background: -moz-linear-gradient(top, rgba(255,255,255,1) 16%, rgba(255,255,255,0) 79%, rgba(255,255,255,0) 88%); /* FF3.6-15 */\\r\\n background: -webkit-linear-gradient(top, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* Chrome10-25,Safari5.1-6 */\\r\\n background: linear-gradient(to bottom, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */\\r\\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */\\r\\n background-color: #E3E3E3;\\r\\n}\\r\\n.active-header-button {\\r\\n background: -moz-linear-gradient(top, rgba(255,255,255,1) 16%, rgba(255,255,255,0) 79%, rgba(255,255,255,0) 88%); /* FF3.6-15 */\\r\\n background: -webkit-linear-gradient(top, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* Chrome10-25,Safari5.1-6 */\\r\\n background: linear-gradient(to bottom, rgba(255,255,255,1) 16%,rgba(255,255,255,0) 79%,rgba(255,255,255,0) 88%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */\\r\\n filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */\\r\\n background-color: #E3E3E3;\\r\\n}\\r\\n.header-logo {\\r\\n width: 75px;\\r\\n}\\r\\n.header-div {\\r\\n padding-top: 5px;\\r\\n}\\r\\n.power-manager {\\r\\n padding-top: 5px;\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.power-manager-enabled {\\r\\n background: url(../../../assets/Gray/Power-Manager-gray.jpg) no-repeat center;\\r\\n}\\r\\n.power-manager-enabled:hover,\\r\\n.power-manager-active {\\r\\n background: url(../../../assets/Blue/Power-Manager-blue.jpg) no-repeat center;\\r\\n}\\r\\n.billing {\\r\\n padding-top: 5px;\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.billing-enabled {\\r\\n background: url(../../../assets/Gray/Billing-gray.jpg) no-repeat center;\\r\\n}\\r\\n.billing-enabled:hover,\\r\\n.billing-active {\\r\\n background: url(../../../assets/Blue/Billing-blue.jpg) no-repeat center;\\r\\n}\\r\\n.administration {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.administration-enabled {\\r\\n background: url(../../../assets/Gray/Administration-gray.jpg) no-repeat center;\\r\\n}\\r\\n.administration-enabled:hover,\\r\\n.administration-active {\\r\\n background: url(../../../assets/Blue/Administration-blue.jpg) no-repeat center;\\r\\n}\\r\\n\\r\\n.impersonate {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n\\r\\n/*Need to fix, need a blue and grey clipart for Impersonate*/\\r\\n.impersonate-enabled {\\r\\n background: url(../../../assets/Gray/Impersonate-gray.jpg) no-repeat center;\\r\\n}\\r\\n\\r\\n.impersonate-enabled:hover,\\r\\n.impersonate-active {\\r\\n background: url(../../../assets/Blue/Impersonate-blue.jpg) no-repeat center;\\r\\n}\\r\\n\\r\\n.reports {\\r\\n display: block;\\r\\n height: 67px;\\r\\n width: 175px;\\r\\n}\\r\\n.reports-enabled {\\r\\n background: url(../../../assets/Gray/Reports-gray.jpg) no-repeat center;\\r\\n}\\r\\n.reports-enabled:hover,\\r\\n.reports-active {\\r\\n background: url(../../../assets/Blue/Reports-blue.jpg) no-repeat center;\\r\\n}\\r\\n.reports-disabled {\\r\\n background: url(../../../assets/Gray/Reports-grayed-out.jpg) no-repeat center;\\r\\n pointer-events:none;\\r\\n}\\r\\n\\r\\n.dropdown-nav {\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.dropdown-nav.dropdown-enabled {\\r\\n position: absolute;\\r\\n top: 80px;\\r\\n width: fit-content;\\r\\n min-width: 175px;\\r\\n background: #ffffff;\\r\\n border: solid 1px rgba(0, 0, 0, 0.1);\\r\\n}\\r\\n\\r\\n.header-div:hover .dropdown-nav.dropdown-enabled {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n flex-wrap: nowrap;\\r\\n align-items: flex-start;\\r\\n}\\r\\n\\r\\n.dropdown-nav > a {\\r\\n text-align: left;\\r\\n flex: 1;\\r\\n text-transform: uppercase;\\r\\n padding: 10px;\\r\\n display: block;\\r\\n width: 100%;\\r\\n}\\r\\n\\r\\n.dropdown-nav > a:hover {\\r\\n background: rgba(0,0,0,0.1);\\r\\n color: #069 !important;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".subNavHeight{\\r\\n height:40px;\\r\\n}\\r\\n\\r\\n.subnavbar-fixed-top{\\r\\n top:82px;\\r\\n z-index: 1000;\\r\\n\\r\\n}\\r\\n\\r\\n.subnav a{\\r\\n color:#939BA1 !important;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\ntd.activeSubNav a{\\r\\n color:#5AAD00 !important;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n.subNavSeperator{\\r\\n margin-left:12px;\\r\\n margin-right:12px;\\r\\n margin-bottom:10px;\\r\\n margin-top:10px;\\r\\n border-left:2px solid #c8c1c1;\\r\\n height:30px;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/nav-menu/sub-nav-menu/sub-nav-menu.component.css\"],\"names\":[],\"mappings\":\"AAAA;KACK,WAAW;AAChB;;AAEA;IACI,QAAQ;IACR,aAAa;;AAEjB;;AAEA;IACI,wBAAwB;IACxB,gBAAgB;AACpB;;AAEA;IACI,wBAAwB;IACxB,gBAAgB;AACpB;;AAEA;IACI,gBAAgB;IAChB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,6BAA6B;IAC7B,WAAW;AACf\",\"sourcesContent\":[\".subNavHeight{\\r\\n height:40px;\\r\\n}\\r\\n\\r\\n.subnavbar-fixed-top{\\r\\n top:82px;\\r\\n z-index: 1000;\\r\\n\\r\\n}\\r\\n\\r\\n.subnav a{\\r\\n color:#939BA1 !important;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\ntd.activeSubNav a{\\r\\n color:#5AAD00 !important;\\r\\n font-weight:bold;\\r\\n}\\r\\n\\r\\n.subNavSeperator{\\r\\n margin-left:12px;\\r\\n margin-right:12px;\\r\\n margin-bottom:10px;\\r\\n margin-top:10px;\\r\\n border-left:2px solid #c8c1c1;\\r\\n height:30px;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".ag-pager-wrap {\\r\\n line-height: 1.25;\\r\\n display: flex;\\r\\n -webkit-box-align: center;\\r\\n align-items: flex-start;\\r\\n overflow: hidden;\\r\\n cursor: default;\\r\\n -webkit-box-flex: 0;\\r\\n flex: 0 0 auto;\\r\\n border-width: 1px 0 0;\\r\\n border-style: solid;\\r\\n background-color: #b3b3b3;\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.ag-pager-wrap .ag-link {\\r\\n box-sizing: content-box;\\r\\n display: inline-flex;\\r\\n -webkit-box-align: center;\\r\\n align-items: center;\\r\\n -webkit-box-pack: center;\\r\\n justify-content: center;\\r\\n position: relative;\\r\\n text-align: center;\\r\\n z-index: 1;\\r\\n width: calc(1.25em + 20px);\\r\\n height: calc(1.25em + 20px);\\r\\n \\r\\n}\\r\\n\\r\\n.ag-pager-numbers {\\r\\n display: -webkit-inline-box;\\r\\n display: -ms-inline-flexbox;\\r\\n display: inline-flex;\\r\\n -webkit-box-orient: horizontal;\\r\\n -webkit-box-direction: normal;\\r\\n -ms-flex-direction: row;\\r\\n flex-direction: row;\\r\\n}\\r\\n\\r\\n.ag-pager-page-active {\\r\\n background: #2199e8;\\r\\n color: #fefefe !important;\\r\\n}\\r\\n\\r\\n.page-sizes-container {\\r\\n padding-left: 30px;\\r\\n}\\r\\n\\r\\n.calpine-reset {\\r\\n margin: 0;\\r\\n padding: 0;\\r\\n border-width: 0;\\r\\n outline: 0;\\r\\n text-decoration: none;\\r\\n font: inherit;\\r\\n list-style: none;\\r\\n} \\r\\n\\r\\n.margin-right-auto {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n.align-self-flex-start {\\r\\n align-self: flex-start;\\r\\n}\\r\\n\\r\\n.display-inline-flex {\\r\\n display: inline-flex;\\r\\n}\\r\\n\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/shared/pager/pager.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,iBAAiB;IACjB,aAAa;IACb,yBAAyB;IACzB,uBAAuB;IACvB,gBAAgB;IAChB,eAAe;IACf,mBAAmB;IACnB,cAAc;IACd,qBAAqB;IACrB,mBAAmB;IACnB,yBAAyB;IACzB,yBAAyB;AAC7B;;AAEA;IACI,uBAAuB;IACvB,oBAAoB;IACpB,yBAAyB;IACzB,mBAAmB;IACnB,wBAAwB;IACxB,uBAAuB;IACvB,kBAAkB;IAClB,kBAAkB;IAClB,UAAU;IACV,0BAA0B;IAC1B,2BAA2B;;AAE/B;;AAEA;IACI,2BAA2B;IAC3B,2BAA2B;IAC3B,oBAAoB;IACpB,8BAA8B;IAC9B,6BAA6B;IAC7B,uBAAuB;IACvB,mBAAmB;AACvB;;AAEA;IACI,mBAAmB;IACnB,yBAAyB;AAC7B;;AAEA;IACI,kBAAkB;AACtB;;AAEA;IACI,SAAS;IACT,UAAU;IACV,eAAe;IACf,UAAU;IACV,qBAAqB;IACrB,aAAa;IACb,gBAAgB;AACpB;;AAEA;IACI,kBAAkB;AACtB;;AAEA;IACI,sBAAsB;AAC1B;;AAEA;IACI,oBAAoB;AACxB\",\"sourcesContent\":[\".ag-pager-wrap {\\r\\n line-height: 1.25;\\r\\n display: flex;\\r\\n -webkit-box-align: center;\\r\\n align-items: flex-start;\\r\\n overflow: hidden;\\r\\n cursor: default;\\r\\n -webkit-box-flex: 0;\\r\\n flex: 0 0 auto;\\r\\n border-width: 1px 0 0;\\r\\n border-style: solid;\\r\\n background-color: #b3b3b3;\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.ag-pager-wrap .ag-link {\\r\\n box-sizing: content-box;\\r\\n display: inline-flex;\\r\\n -webkit-box-align: center;\\r\\n align-items: center;\\r\\n -webkit-box-pack: center;\\r\\n justify-content: center;\\r\\n position: relative;\\r\\n text-align: center;\\r\\n z-index: 1;\\r\\n width: calc(1.25em + 20px);\\r\\n height: calc(1.25em + 20px);\\r\\n \\r\\n}\\r\\n\\r\\n.ag-pager-numbers {\\r\\n display: -webkit-inline-box;\\r\\n display: -ms-inline-flexbox;\\r\\n display: inline-flex;\\r\\n -webkit-box-orient: horizontal;\\r\\n -webkit-box-direction: normal;\\r\\n -ms-flex-direction: row;\\r\\n flex-direction: row;\\r\\n}\\r\\n\\r\\n.ag-pager-page-active {\\r\\n background: #2199e8;\\r\\n color: #fefefe !important;\\r\\n}\\r\\n\\r\\n.page-sizes-container {\\r\\n padding-left: 30px;\\r\\n}\\r\\n\\r\\n.calpine-reset {\\r\\n margin: 0;\\r\\n padding: 0;\\r\\n border-width: 0;\\r\\n outline: 0;\\r\\n text-decoration: none;\\r\\n font: inherit;\\r\\n list-style: none;\\r\\n} \\r\\n\\r\\n.margin-right-auto {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n.align-self-flex-start {\\r\\n align-self: flex-start;\\r\\n}\\r\\n\\r\\n.display-inline-flex {\\r\\n display: inline-flex;\\r\\n}\\r\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// Imports\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(true);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".white-div-background {\\r\\n border-radius: 0px;\\r\\n background-color: #ffffff;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em;\\r\\n}\\r\\n\\r\\n.grey-bottom-border{\\r\\n border-bottom: 2px solid darkgray;\\r\\n}\\r\\n\\r\\n.blue-breadCrumb-color{\\r\\n color:#0026ff;\\r\\n}\\r\\n\\r\\ninput.icon {\\r\\n text-align:center;\\r\\n /*height: 3.1rem;*/\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n}\\r\\n\\r\\ninput.icon { font-family: 'FontAwesome'; } \\r\\n\\r\\n@media (min-width: 1200px) {\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 40%;\\r\\n /*height: 50%;*/\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n }\\r\\n .forgot-password-div{\\r\\n position: fixed;\\r\\n top: 43%;\\r\\n }\\r\\n .container {\\r\\n max-width: 940px;\\r\\n } \\r\\n}\\r\\n@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) {\\r\\n /* For portrait layouts only */\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 50%;\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n font-size:10px;\\r\\n }\\r\\n /*h3 {\\r\\n font-size:14px;\\r\\n }*/\\r\\n input.icon {\\r\\n text-align:center;\\r\\n height: 2.1rem;\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n font-size: 10px;\\r\\n }\\r\\n .container {\\r\\n max-width: 500px;\\r\\n } \\r\\n}\\r\\n\\r\\n@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape) {\\r\\n /* For landscape layouts only */\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 50%;\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n font-size:14px;\\r\\n }\\r\\n input.icon {\\r\\n text-align:center;\\r\\n height: 2.1rem;\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n font-size: 10px;\\r\\n }\\r\\n .container {\\r\\n max-width: 640px;\\r\\n }\\r\\n}\\r\\n\\r\\n.md-form{\\r\\n border: 1px!important;\\r\\n}\\r\\n\\r\\n#profile-info-container input.form-control{\\r\\n font-size:14px !important;\\r\\n height:auto;\\r\\n line-height: 1.25;\\r\\n\\r\\n}\\r\\n\\r\\n#profile-info-container label{\\r\\n font-size:14px;\\r\\n}\\r\\n\\r\\n.user-profile-phone{\\r\\n padding-top: .5rem;\\r\\n}\", \"\",{\"version\":3,\"sources\":[\"webpack://src/app/user-management/shared/user-management.component.css\"],\"names\":[],\"mappings\":\"AAAA;IACI,kBAAkB;IAClB,yBAAyB;IACzB,eAAe;IACf,kBAAkB;AACtB;;AAEA;IACI,iCAAiC;AACrC;;AAEA;IACI,aAAa;AACjB;;AAEA;IACI,iBAAiB;IACjB,kBAAkB;IAClB,gCAAgC;AACpC;;AAEA,aAAa,0BAA0B,EAAE;;AAEzC;IACI;QACI,iBAAiB;QACjB,oBAAoB;IACxB;IACA;QACI,eAAe;QACf,qBAAqB;QACrB,kBAAkB;QAClB,wBAAwB;QACxB,kBAAkB;QAClB,UAAU;QACV,eAAe;QACf,eAAe;QACf,QAAQ;QACR,SAAS;QACT,wCAAwC;QACxC,gCAAgC;IACpC;IACA;QACI,eAAe;QACf,QAAQ;IACZ;IACA;QACI,gBAAgB;IACpB;AACJ;AACA;IACI,8BAA8B;IAC9B;QACI,iBAAiB;QACjB,oBAAoB;IACxB;IACA;QACI,eAAe;QACf,qBAAqB;QACrB,kBAAkB;QAClB,wBAAwB;QACxB,kBAAkB;QAClB,UAAU;QACV,eAAe;QACf,QAAQ;QACR,SAAS;QACT,wCAAwC;QACxC,gCAAgC;QAChC,cAAc;IAClB;IACA;;MAEE;IACF;QACI,iBAAiB;QACjB,cAAc;QACd,gCAAgC;QAChC,eAAe;IACnB;IACA;QACI,gBAAgB;IACpB;AACJ;;AAEA;EACE,+BAA+B;IAC7B;QACI,iBAAiB;QACjB,oBAAoB;IACxB;IACA;QACI,eAAe;QACf,qBAAqB;QACrB,kBAAkB;QAClB,wBAAwB;QACxB,kBAAkB;QAClB,UAAU;QACV,eAAe;QACf,QAAQ;QACR,SAAS;QACT,wCAAwC;QACxC,gCAAgC;QAChC,cAAc;IAClB;IACA;QACI,iBAAiB;QACjB,cAAc;QACd,gCAAgC;QAChC,eAAe;IACnB;IACA;QACI,gBAAgB;IACpB;AACJ;;AAEA;IACI,qBAAqB;AACzB;;AAEA;IACI,yBAAyB;IACzB,WAAW;IACX,iBAAiB;;AAErB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,kBAAkB;AACtB\",\"sourcesContent\":[\".white-div-background {\\r\\n border-radius: 0px;\\r\\n background-color: #ffffff;\\r\\n padding-top:2em;\\r\\n padding-bottom:2em;\\r\\n}\\r\\n\\r\\n.grey-bottom-border{\\r\\n border-bottom: 2px solid darkgray;\\r\\n}\\r\\n\\r\\n.blue-breadCrumb-color{\\r\\n color:#0026ff;\\r\\n}\\r\\n\\r\\ninput.icon {\\r\\n text-align:center;\\r\\n /*height: 3.1rem;*/\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n}\\r\\n\\r\\ninput.icon { font-family: 'FontAwesome'; } \\r\\n\\r\\n@media (min-width: 1200px) {\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 40%;\\r\\n /*height: 50%;*/\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n }\\r\\n .forgot-password-div{\\r\\n position: fixed;\\r\\n top: 43%;\\r\\n }\\r\\n .container {\\r\\n max-width: 940px;\\r\\n } \\r\\n}\\r\\n@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:portrait) {\\r\\n /* For portrait layouts only */\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 50%;\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n font-size:10px;\\r\\n }\\r\\n /*h3 {\\r\\n font-size:14px;\\r\\n }*/\\r\\n input.icon {\\r\\n text-align:center;\\r\\n height: 2.1rem;\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n font-size: 10px;\\r\\n }\\r\\n .container {\\r\\n max-width: 500px;\\r\\n } \\r\\n}\\r\\n\\r\\n@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation:landscape) {\\r\\n /* For landscape layouts only */\\r\\n .confirm-email-div-img-center {\\r\\n text-align:center;\\r\\n padding-bottom: 15px;\\r\\n }\\r\\n .confirm-email-div{\\r\\n padding-top:2em;\\r\\n align-content: center;\\r\\n border-radius: 0px;\\r\\n background-color:#ffffff;\\r\\n padding-bottom:2em;\\r\\n width: 50%;\\r\\n position: fixed;\\r\\n top: 45%;\\r\\n left: 50%;\\r\\n -webkit-transform: translate(-50%, -50%);\\r\\n transform: translate(-50%, -50%);\\r\\n font-size:14px;\\r\\n }\\r\\n input.icon {\\r\\n text-align:center;\\r\\n height: 2.1rem;\\r\\n box-shadow: 2px 2px 2px 3px #ccc;\\r\\n font-size: 10px;\\r\\n }\\r\\n .container {\\r\\n max-width: 640px;\\r\\n }\\r\\n}\\r\\n\\r\\n.md-form{\\r\\n border: 1px!important;\\r\\n}\\r\\n\\r\\n#profile-info-container input.form-control{\\r\\n font-size:14px !important;\\r\\n height:auto;\\r\\n line-height: 1.25;\\r\\n\\r\\n}\\r\\n\\r\\n#profile-info-container label{\\r\\n font-size:14px;\\r\\n}\\r\\n\\r\\n.user-profile-phone{\\r\\n padding-top: .5rem;\\r\\n}\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","export default __webpack_public_path__ + \"fonts/Administration-blue.84e01685386f6ca14ed8ece54aa9b9f9.jpg\";","export default __webpack_public_path__ + \"fonts/Billing-blue.ab64b38dd53f3b67e727d71bec507eb9.jpg\";","export default __webpack_public_path__ + \"fonts/Impersonate-blue.3214b6ce6c7cb23bfe0da49fd3cbb459.jpg\";","export default __webpack_public_path__ + \"fonts/Power-Manager-blue.5c18808c25c18b6f7514544f31f42485.jpg\";","export default __webpack_public_path__ + \"fonts/Reports-blue.d08fd112f0219a96968b972fd73ccd25.jpg\";","export default __webpack_public_path__ + \"fonts/Administration-gray.e072ceb88bf1d41b6fb34ac28cdfc97e.jpg\";","export default __webpack_public_path__ + \"fonts/Billing-gray.8c6852ae56b12d03380c3dcf23b02502.jpg\";","export default __webpack_public_path__ + \"fonts/Impersonate-gray.6eb5891f17520f97b10fd37ea4405e9d.jpg\";","export default __webpack_public_path__ + \"fonts/Power-Manager-gray.194071b1143f7fab83ae8b1650a9dcb7.jpg\";","export default __webpack_public_path__ + \"fonts/Reports-gray.bb55d75b4d1a5b1370f4fd6e302a2036.jpg\";","export default __webpack_public_path__ + \"fonts/Reports-grayed-out.b0742535800c6b9e56132f67f9389d96.jpg\";","export default __webpack_public_path__ + \"fonts/home_background.538e653c913b6bcae950c69b9b4a7f83.jpg\";","export default __webpack_public_path__ + \"fonts/nes_bg.d915e08c8686d6c94ee175dbe28242e8.jpg\";","const map = {\n\t\"./af\": 26030,\n\t\"./af.js\": 26030,\n\t\"./ar\": 87762,\n\t\"./ar-dz\": 54073,\n\t\"./ar-dz.js\": 54073,\n\t\"./ar-kw\": 55177,\n\t\"./ar-kw.js\": 55177,\n\t\"./ar-ly\": 82664,\n\t\"./ar-ly.js\": 82664,\n\t\"./ar-ma\": 66905,\n\t\"./ar-ma.js\": 66905,\n\t\"./ar-ps\": 17078,\n\t\"./ar-ps.js\": 17078,\n\t\"./ar-sa\": 39211,\n\t\"./ar-sa.js\": 39211,\n\t\"./ar-tn\": 5077,\n\t\"./ar-tn.js\": 5077,\n\t\"./ar.js\": 87762,\n\t\"./az\": 26890,\n\t\"./az.js\": 26890,\n\t\"./be\": 60732,\n\t\"./be.js\": 60732,\n\t\"./bg\": 88550,\n\t\"./bg.js\": 88550,\n\t\"./bm\": 77124,\n\t\"./bm.js\": 77124,\n\t\"./bn\": 1709,\n\t\"./bn-bd\": 50800,\n\t\"./bn-bd.js\": 50800,\n\t\"./bn.js\": 1709,\n\t\"./bo\": 91534,\n\t\"./bo.js\": 91534,\n\t\"./br\": 88825,\n\t\"./br.js\": 88825,\n\t\"./bs\": 92394,\n\t\"./bs.js\": 92394,\n\t\"./ca\": 16633,\n\t\"./ca.js\": 16633,\n\t\"./cs\": 36039,\n\t\"./cs.js\": 36039,\n\t\"./cv\": 88540,\n\t\"./cv.js\": 88540,\n\t\"./cy\": 28113,\n\t\"./cy.js\": 28113,\n\t\"./da\": 60802,\n\t\"./da.js\": 60802,\n\t\"./de\": 54606,\n\t\"./de-at\": 3518,\n\t\"./de-at.js\": 3518,\n\t\"./de-ch\": 9496,\n\t\"./de-ch.js\": 9496,\n\t\"./de.js\": 54606,\n\t\"./dv\": 85979,\n\t\"./dv.js\": 85979,\n\t\"./el\": 21672,\n\t\"./el.js\": 21672,\n\t\"./en-au\": 22073,\n\t\"./en-au.js\": 22073,\n\t\"./en-ca\": 93435,\n\t\"./en-ca.js\": 93435,\n\t\"./en-gb\": 43210,\n\t\"./en-gb.js\": 43210,\n\t\"./en-ie\": 55361,\n\t\"./en-ie.js\": 55361,\n\t\"./en-il\": 68874,\n\t\"./en-il.js\": 68874,\n\t\"./en-in\": 70656,\n\t\"./en-in.js\": 70656,\n\t\"./en-nz\": 22083,\n\t\"./en-nz.js\": 22083,\n\t\"./en-sg\": 16689,\n\t\"./en-sg.js\": 16689,\n\t\"./eo\": 74593,\n\t\"./eo.js\": 74593,\n\t\"./es\": 37221,\n\t\"./es-do\": 36435,\n\t\"./es-do.js\": 36435,\n\t\"./es-mx\": 4767,\n\t\"./es-mx.js\": 4767,\n\t\"./es-us\": 30306,\n\t\"./es-us.js\": 30306,\n\t\"./es.js\": 37221,\n\t\"./et\": 88304,\n\t\"./et.js\": 88304,\n\t\"./eu\": 12455,\n\t\"./eu.js\": 12455,\n\t\"./fa\": 74980,\n\t\"./fa.js\": 74980,\n\t\"./fi\": 8060,\n\t\"./fi.js\": 8060,\n\t\"./fil\": 21954,\n\t\"./fil.js\": 21954,\n\t\"./fo\": 86010,\n\t\"./fo.js\": 86010,\n\t\"./fr\": 92125,\n\t\"./fr-ca\": 79842,\n\t\"./fr-ca.js\": 79842,\n\t\"./fr-ch\": 63913,\n\t\"./fr-ch.js\": 63913,\n\t\"./fr.js\": 92125,\n\t\"./fy\": 77324,\n\t\"./fy.js\": 77324,\n\t\"./ga\": 80797,\n\t\"./ga.js\": 80797,\n\t\"./gd\": 76818,\n\t\"./gd.js\": 76818,\n\t\"./gl\": 44234,\n\t\"./gl.js\": 44234,\n\t\"./gom-deva\": 53011,\n\t\"./gom-deva.js\": 53011,\n\t\"./gom-latn\": 15252,\n\t\"./gom-latn.js\": 15252,\n\t\"./gu\": 9617,\n\t\"./gu.js\": 9617,\n\t\"./he\": 60346,\n\t\"./he.js\": 60346,\n\t\"./hi\": 13198,\n\t\"./hi.js\": 13198,\n\t\"./hr\": 51923,\n\t\"./hr.js\": 51923,\n\t\"./hu\": 14058,\n\t\"./hu.js\": 14058,\n\t\"./hy-am\": 83989,\n\t\"./hy-am.js\": 83989,\n\t\"./id\": 14156,\n\t\"./id.js\": 14156,\n\t\"./is\": 35369,\n\t\"./is.js\": 35369,\n\t\"./it\": 86908,\n\t\"./it-ch\": 62886,\n\t\"./it-ch.js\": 62886,\n\t\"./it.js\": 86908,\n\t\"./ja\": 952,\n\t\"./ja.js\": 952,\n\t\"./jv\": 20637,\n\t\"./jv.js\": 20637,\n\t\"./ka\": 96257,\n\t\"./ka.js\": 96257,\n\t\"./kk\": 3383,\n\t\"./kk.js\": 3383,\n\t\"./km\": 56693,\n\t\"./km.js\": 56693,\n\t\"./kn\": 98412,\n\t\"./kn.js\": 98412,\n\t\"./ko\": 98675,\n\t\"./ko.js\": 98675,\n\t\"./ku\": 4301,\n\t\"./ku-kmr\": 98374,\n\t\"./ku-kmr.js\": 98374,\n\t\"./ku.js\": 4301,\n\t\"./ky\": 19625,\n\t\"./ky.js\": 19625,\n\t\"./lb\": 11415,\n\t\"./lb.js\": 11415,\n\t\"./lo\": 76692,\n\t\"./lo.js\": 76692,\n\t\"./lt\": 24389,\n\t\"./lt.js\": 24389,\n\t\"./lv\": 76291,\n\t\"./lv.js\": 76291,\n\t\"./me\": 47967,\n\t\"./me.js\": 47967,\n\t\"./mi\": 57811,\n\t\"./mi.js\": 57811,\n\t\"./mk\": 56405,\n\t\"./mk.js\": 56405,\n\t\"./ml\": 16256,\n\t\"./ml.js\": 16256,\n\t\"./mn\": 80298,\n\t\"./mn.js\": 80298,\n\t\"./mr\": 14126,\n\t\"./mr.js\": 14126,\n\t\"./ms\": 63437,\n\t\"./ms-my\": 21392,\n\t\"./ms-my.js\": 21392,\n\t\"./ms.js\": 63437,\n\t\"./mt\": 47704,\n\t\"./mt.js\": 47704,\n\t\"./my\": 4099,\n\t\"./my.js\": 4099,\n\t\"./nb\": 33685,\n\t\"./nb.js\": 33685,\n\t\"./ne\": 33184,\n\t\"./ne.js\": 33184,\n\t\"./nl\": 22367,\n\t\"./nl-be\": 55649,\n\t\"./nl-be.js\": 55649,\n\t\"./nl.js\": 22367,\n\t\"./nn\": 17889,\n\t\"./nn.js\": 17889,\n\t\"./oc-lnc\": 41313,\n\t\"./oc-lnc.js\": 41313,\n\t\"./pa-in\": 2116,\n\t\"./pa-in.js\": 2116,\n\t\"./pl\": 42697,\n\t\"./pl.js\": 42697,\n\t\"./pt\": 69857,\n\t\"./pt-br\": 25898,\n\t\"./pt-br.js\": 25898,\n\t\"./pt.js\": 69857,\n\t\"./ro\": 26494,\n\t\"./ro.js\": 26494,\n\t\"./ru\": 7836,\n\t\"./ru.js\": 7836,\n\t\"./sd\": 94790,\n\t\"./sd.js\": 94790,\n\t\"./se\": 25509,\n\t\"./se.js\": 25509,\n\t\"./si\": 58129,\n\t\"./si.js\": 58129,\n\t\"./sk\": 30255,\n\t\"./sk.js\": 30255,\n\t\"./sl\": 49870,\n\t\"./sl.js\": 49870,\n\t\"./sq\": 89177,\n\t\"./sq.js\": 89177,\n\t\"./sr\": 94528,\n\t\"./sr-cyrl\": 45375,\n\t\"./sr-cyrl.js\": 45375,\n\t\"./sr.js\": 94528,\n\t\"./ss\": 93303,\n\t\"./ss.js\": 93303,\n\t\"./sv\": 88332,\n\t\"./sv.js\": 88332,\n\t\"./sw\": 96435,\n\t\"./sw.js\": 96435,\n\t\"./ta\": 9906,\n\t\"./ta.js\": 9906,\n\t\"./te\": 34046,\n\t\"./te.js\": 34046,\n\t\"./tet\": 23680,\n\t\"./tet.js\": 23680,\n\t\"./tg\": 89588,\n\t\"./tg.js\": 89588,\n\t\"./th\": 38521,\n\t\"./th.js\": 38521,\n\t\"./tk\": 18240,\n\t\"./tk.js\": 18240,\n\t\"./tl-ph\": 7086,\n\t\"./tl-ph.js\": 7086,\n\t\"./tlh\": 23921,\n\t\"./tlh.js\": 23921,\n\t\"./tr\": 2383,\n\t\"./tr.js\": 2383,\n\t\"./tzl\": 2083,\n\t\"./tzl.js\": 2083,\n\t\"./tzm\": 97148,\n\t\"./tzm-latn\": 43620,\n\t\"./tzm-latn.js\": 43620,\n\t\"./tzm.js\": 97148,\n\t\"./ug-cn\": 32375,\n\t\"./ug-cn.js\": 32375,\n\t\"./uk\": 78477,\n\t\"./uk.js\": 78477,\n\t\"./ur\": 2678,\n\t\"./ur.js\": 2678,\n\t\"./uz\": 87294,\n\t\"./uz-latn\": 98470,\n\t\"./uz-latn.js\": 98470,\n\t\"./uz.js\": 87294,\n\t\"./vi\": 73516,\n\t\"./vi.js\": 73516,\n\t\"./x-pseudo\": 94384,\n\t\"./x-pseudo.js\": 94384,\n\t\"./yo\": 11949,\n\t\"./yo.js\": 11949,\n\t\"./zh-cn\": 27025,\n\t\"./zh-cn.js\": 27025,\n\t\"./zh-hk\": 98477,\n\t\"./zh-hk.js\": 98477,\n\t\"./zh-mo\": 87216,\n\t\"./zh-mo.js\": 87216,\n\t\"./zh-tw\": 87685,\n\t\"./zh-tw.js\": 87685\n};\n\n\nfunction webpackContext(req) {\n\tconst id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tconst e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 32220;","const map = {\n\t\"./af\": 39778,\n\t\"./af.js\": 39778,\n\t\"./ar\": 94046,\n\t\"./ar-dz\": 14189,\n\t\"./ar-dz.js\": 14189,\n\t\"./ar-kw\": 55645,\n\t\"./ar-kw.js\": 55645,\n\t\"./ar-ly\": 27500,\n\t\"./ar-ly.js\": 27500,\n\t\"./ar-ma\": 30973,\n\t\"./ar-ma.js\": 30973,\n\t\"./ar-sa\": 37895,\n\t\"./ar-sa.js\": 37895,\n\t\"./ar-tn\": 26449,\n\t\"./ar-tn.js\": 26449,\n\t\"./ar.js\": 94046,\n\t\"./az\": 9430,\n\t\"./az.js\": 9430,\n\t\"./be\": 40048,\n\t\"./be.js\": 40048,\n\t\"./bg\": 60474,\n\t\"./bg.js\": 60474,\n\t\"./bn\": 15697,\n\t\"./bn.js\": 15697,\n\t\"./bo\": 47810,\n\t\"./bo.js\": 47810,\n\t\"./br\": 26421,\n\t\"./br.js\": 26421,\n\t\"./bs\": 17462,\n\t\"./bs.js\": 17462,\n\t\"./ca\": 20981,\n\t\"./ca.js\": 20981,\n\t\"./cs\": 85027,\n\t\"./cs.js\": 85027,\n\t\"./cv\": 27664,\n\t\"./cv.js\": 27664,\n\t\"./cy\": 44365,\n\t\"./cy.js\": 44365,\n\t\"./da\": 35030,\n\t\"./da.js\": 35030,\n\t\"./de\": 8458,\n\t\"./de-at\": 61858,\n\t\"./de-at.js\": 61858,\n\t\"./de-ch\": 17492,\n\t\"./de-ch.js\": 17492,\n\t\"./de.js\": 8458,\n\t\"./dv\": 98119,\n\t\"./dv.js\": 98119,\n\t\"./el\": 79140,\n\t\"./el.js\": 79140,\n\t\"./en-au\": 63549,\n\t\"./en-au.js\": 63549,\n\t\"./en-ca\": 6983,\n\t\"./en-ca.js\": 6983,\n\t\"./en-gb\": 52014,\n\t\"./en-gb.js\": 52014,\n\t\"./en-ie\": 33381,\n\t\"./en-ie.js\": 33381,\n\t\"./en-nz\": 60455,\n\t\"./en-nz.js\": 60455,\n\t\"./eo\": 3725,\n\t\"./eo.js\": 3725,\n\t\"./es\": 90841,\n\t\"./es-do\": 42311,\n\t\"./es-do.js\": 42311,\n\t\"./es.js\": 90841,\n\t\"./et\": 32012,\n\t\"./et.js\": 32012,\n\t\"./eu\": 81747,\n\t\"./eu.js\": 81747,\n\t\"./fa\": 86248,\n\t\"./fa.js\": 86248,\n\t\"./fi\": 31680,\n\t\"./fi.js\": 31680,\n\t\"./fo\": 13942,\n\t\"./fo.js\": 13942,\n\t\"./fr\": 95281,\n\t\"./fr-ca\": 50630,\n\t\"./fr-ca.js\": 50630,\n\t\"./fr-ch\": 63789,\n\t\"./fr-ch.js\": 63789,\n\t\"./fr.js\": 95281,\n\t\"./fy\": 62160,\n\t\"./fy.js\": 62160,\n\t\"./gd\": 56622,\n\t\"./gd.js\": 56622,\n\t\"./gl\": 1542,\n\t\"./gl.js\": 1542,\n\t\"./gom-latn\": 78888,\n\t\"./gom-latn.js\": 78888,\n\t\"./he\": 34878,\n\t\"./he.js\": 34878,\n\t\"./hi\": 74058,\n\t\"./hi.js\": 74058,\n\t\"./hr\": 69039,\n\t\"./hr.js\": 69039,\n\t\"./hu\": 7886,\n\t\"./hu.js\": 7886,\n\t\"./hy-am\": 63593,\n\t\"./hy-am.js\": 63593,\n\t\"./id\": 10096,\n\t\"./id.js\": 10096,\n\t\"./is\": 3413,\n\t\"./is.js\": 3413,\n\t\"./it\": 63264,\n\t\"./it.js\": 63264,\n\t\"./ja\": 17204,\n\t\"./ja.js\": 17204,\n\t\"./jv\": 58929,\n\t\"./jv.js\": 58929,\n\t\"./ka\": 29389,\n\t\"./ka.js\": 29389,\n\t\"./kk\": 70051,\n\t\"./kk.js\": 70051,\n\t\"./km\": 28361,\n\t\"./km.js\": 28361,\n\t\"./kn\": 52880,\n\t\"./kn.js\": 52880,\n\t\"./ko\": 77031,\n\t\"./ko.js\": 77031,\n\t\"./ky\": 39253,\n\t\"./ky.js\": 39253,\n\t\"./lb\": 2731,\n\t\"./lb.js\": 2731,\n\t\"./lo\": 44592,\n\t\"./lo.js\": 44592,\n\t\"./lt\": 82465,\n\t\"./lt.js\": 82465,\n\t\"./lv\": 86943,\n\t\"./lv.js\": 86943,\n\t\"./me\": 52315,\n\t\"./me.js\": 52315,\n\t\"./mi\": 22743,\n\t\"./mi.js\": 22743,\n\t\"./mk\": 34073,\n\t\"./mk.js\": 34073,\n\t\"./ml\": 75244,\n\t\"./ml.js\": 75244,\n\t\"./mr\": 78210,\n\t\"./mr.js\": 78210,\n\t\"./ms\": 62449,\n\t\"./ms-my\": 67340,\n\t\"./ms-my.js\": 67340,\n\t\"./ms.js\": 62449,\n\t\"./my\": 10951,\n\t\"./my.js\": 10951,\n\t\"./nb\": 27705,\n\t\"./nb.js\": 27705,\n\t\"./ne\": 92172,\n\t\"./ne.js\": 92172,\n\t\"./nl\": 26715,\n\t\"./nl-be\": 78069,\n\t\"./nl-be.js\": 78069,\n\t\"./nl.js\": 26715,\n\t\"./nn\": 90621,\n\t\"./nn.js\": 90621,\n\t\"./pa-in\": 35864,\n\t\"./pa-in.js\": 35864,\n\t\"./pl\": 57149,\n\t\"./pl.js\": 57149,\n\t\"./pt\": 53349,\n\t\"./pt-br\": 44718,\n\t\"./pt-br.js\": 44718,\n\t\"./pt.js\": 53349,\n\t\"./ro\": 90994,\n\t\"./ro.js\": 90994,\n\t\"./ru\": 72336,\n\t\"./ru.js\": 72336,\n\t\"./sd\": 62362,\n\t\"./sd.js\": 62362,\n\t\"./se\": 74889,\n\t\"./se.js\": 74889,\n\t\"./si\": 59565,\n\t\"./si.js\": 59565,\n\t\"./sk\": 75,\n\t\"./sk.js\": 75,\n\t\"./sl\": 14114,\n\t\"./sl.js\": 14114,\n\t\"./sq\": 11957,\n\t\"./sq.js\": 11957,\n\t\"./sr\": 53676,\n\t\"./sr-cyrl\": 44355,\n\t\"./sr-cyrl.js\": 44355,\n\t\"./sr.js\": 53676,\n\t\"./ss\": 53939,\n\t\"./ss.js\": 53939,\n\t\"./sv\": 52576,\n\t\"./sv.js\": 52576,\n\t\"./sw\": 58647,\n\t\"./sw.js\": 58647,\n\t\"./ta\": 24774,\n\t\"./ta.js\": 24774,\n\t\"./te\": 69018,\n\t\"./te.js\": 69018,\n\t\"./tet\": 15580,\n\t\"./tet.js\": 15580,\n\t\"./th\": 5869,\n\t\"./th.js\": 5869,\n\t\"./tl-ph\": 66874,\n\t\"./tl-ph.js\": 66874,\n\t\"./tlh\": 67445,\n\t\"./tlh.js\": 67445,\n\t\"./tr\": 243,\n\t\"./tr.js\": 243,\n\t\"./tzl\": 41719,\n\t\"./tzl.js\": 41719,\n\t\"./tzm\": 52000,\n\t\"./tzm-latn\": 81344,\n\t\"./tzm-latn.js\": 81344,\n\t\"./tzm.js\": 52000,\n\t\"./uk\": 85441,\n\t\"./uk.js\": 85441,\n\t\"./ur\": 79930,\n\t\"./ur.js\": 79930,\n\t\"./uz\": 48034,\n\t\"./uz-latn\": 49602,\n\t\"./uz-latn.js\": 49602,\n\t\"./uz.js\": 48034,\n\t\"./vi\": 48304,\n\t\"./vi.js\": 48304,\n\t\"./x-pseudo\": 3332,\n\t\"./x-pseudo.js\": 3332,\n\t\"./yo\": 3553,\n\t\"./yo.js\": 3553,\n\t\"./zh-cn\": 37893,\n\t\"./zh-cn.js\": 37893,\n\t\"./zh-hk\": 27209,\n\t\"./zh-hk.js\": 27209,\n\t\"./zh-tw\": 66433,\n\t\"./zh-tw.js\": 66433\n};\n\n\nfunction webpackContext(req) {\n\tconst id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tconst e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 35358;","module.exports = \"\\r\\n
\\r\\n

Add/Edit User

\\r\\n Create a new user or add an existing one to this counterparty\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n This field is required\\r\\n Not in correct email format\\r\\n User already exists \\r\\n Email already exists \\r\\n Adding existing user \\r\\n User already exists on this counterparty \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n This field is required\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n This field is required\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n

Registration

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n

Internal Roles

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n

Impersonate Roles

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Roles\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n Counterparty has already been added!\\r\\n Select a Counterparty\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n {{counterpartyName }} ({{userCount }})\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\";","module.exports = \"\\r\\n
\\r\\n

Remove User

\\r\\n Remove User from Counterparty\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Are you sure you want to remove this user from the counterparty?
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"\\r\\n
\\r\\n
{{module.module}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"\";","module.exports = \"\\r\\n
\\r\\n

Welcome Email

\\r\\n Resend Welcome Email\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
This operation will resend welcome e-mails to all unverified users. Are you sure you want to proceed?
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
This operation will resend welcome e-mail to {{userEmail}}. Are you sure you want to proceed?
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \";","module.exports = \"\\r\\n
\\r\\n

Remove User

\\r\\n Remove User\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Are you sure you want to remove this user?
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"\";","module.exports = \"\\r\\n
\\r\\n
\\r\\n

Your session is about to expire!

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
You will be logged out in {{ticks}} seconds.\\r\\n
Do you want to stay signed in?\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\";","module.exports = \"\\r\\n
\\r\\n

File Download Error

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n The file you requested is currently unavailable for download. Please try again later, or contact support at {{supportEmail}} or {{supportPhone}}.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n\";","module.exports = \"\\r\\n
\\r\\n \\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Help Resource - Schedule Upload

\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n

\\r\\n On the Schedule Upload page, schedules can be uploaded within an Excel file. For security reasons, the only file extension allowed for upload is .xlsx.\\r\\n If you are working with a macro-enabled Excel file (.xlsm), you will first need to save a separate copy of the file as .xlsx, and then upload that file.\\r\\n To do this, open your .xlsm file and click \\\"File\\\" > \\\"Save As\\\", enter a new file name and select \\\"Excel Workbook (xlsx)\\\" from the \\\"Save as Type\\\" dropdown, and click the \\\"Save\\\" button.\\r\\n

\\r\\n
\\r\\n
\\r\\n
\\r\\n Have Questions?\\r\\n
\\r\\n
\\r\\n
\\r\\n Contact your Dynamic Scheduling\\r\\n
\\r\\n Customer Service Representative\\r\\n
\\r\\n
\\r\\n Send an e-mail to
\\r\\n {{dynSchedEmail}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Schedule Submission History

\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
0\\\" horizontal-scroll class=\\\"scrollable-schedule-container\\\"\\r\\n [fixedElementID]=\\\"'archiveTableHeader'\\\" [fixedElementStartPosition]=\\\"0\\\">\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"\\r\\n
\\r\\n

Limit Error

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n WARNING

Your Requested Quantities are unusually high. Are you sure you want to proceed with the submission?
\\r\\n

If you are unsure, then select Cancel. You may review your submission on the next screen and upload a new submission afterwards.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\";","module.exports = \"\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n Upload\\r\\n Schedule\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Dynamic Scheduling Dashboard

\\r\\n Welcome to the New Dynamic Scheduling Dashboard\\r\\n
0\\\">\\r\\n Results from your last submission on: {{(scheduleUploadModel | async).lastUploadedDate}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Uploaded files must have a file type of .xlsx. View Help for details\\r\\n Please save .xlsm files as .xslx and upload again. View Help for details\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Submittal processing may take a few minutes. You may navigate to other areas of the site without canceling the process.\\r\\n
\\r\\n
0\\\">\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Filters\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n

Schedules Submitted Successfully With No Error

\\r\\n
\\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.successfullySubmitted}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n

Schedules Submitted With Error

\\r\\n
\\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.submittedWithErrors}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n

Schedules Not Submitted

\\r\\n
\\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.notSubmitted}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n

Customer Points Submitted

\\r\\n
\\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.pointsSubmitted}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.limitWarning}}\\r\\n
\\r\\n
\\r\\n Limit Warning\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n {{(scheduleUploadModel | async).dashboardCounts.belowFixed}}\\r\\n
\\r\\n
\\r\\n Below Fixed Price\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Error Log\\r\\n \\r\\n
\\r\\n
\\r\\n
    \\r\\n
  • \\r\\n Quantities submitted without error\\r\\n
  • \\r\\n \\r\\n
  • \\r\\n
    \\r\\n
    \\r\\n *\\r\\n
    \\r\\n
    \\r\\n {{validationMessages[flowDateError].Summary}}\\r\\n \\r\\n
    \\r\\n
    \\r\\n
  • \\r\\n
    \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n Final\\r\\n
\\r\\n
0 && scheduleUploadFilter.finals.length < scheduleFinals.length}\\\">\\r\\n \\r\\n
\\r\\n\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Flow Date \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n From:\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n To:\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Customer Location \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
0 && scheduleUploadFilter.customerPoints.length < scheduleCustomerPoints.length}\\\">\\r\\n \\r\\n
\\r\\n\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n HE
{{ HE_INDEX < 10 ? '0' + HE_INDEX : HE_INDEX }}
\\r\\n
\\r\\n
\\r\\n
\\r\\n Timestamp \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n From:\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n To:\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n DOW \\r\\n
\\r\\n
\\r\\n
\\r\\n
0 && scheduleUploadFilter.DOWs.length < scheduleDOWs.length}\\\">\\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n (Select All)\\r\\n \\r\\n
\\r\\n \\r\\n {{dow}}\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Submitted By \\r\\n
\\r\\n
\\r\\n
\\r\\n
0 && scheduleUploadFilter.submitters.length < scheduleSubmitters.length}\\\">\\r\\n \\r\\n
\\r\\n\\r\\n \\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n\\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n *\\r\\n \\r\\n Quantities displayed are rounded to two decimal places and may not reflect the exact quantities submitted. Hover over the quantity to see a tooltip with the actual submitted quantities.\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n *\\r\\n \\r\\n Quantities displayed are rounded to two decimal places and may not reflect the exact quantities submitted. Export the submittal history to csv to view the actual submitted quantities.\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n\\r\\n \\r\\n\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule.FlowDate | date:\\\"MMM\\\" }}\\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule.FlowDate | date:\\\"d\\\" }}\\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule.FlowDateYear }}\\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule.MeterNumber == null || schedule.DynamicSchedule.MeterNumber.trim() === \\\"\\\" ? schedule.DynamicSchedule.Point : schedule.DynamicSchedule.Point + ':' + schedule.DynamicSchedule.MeterNumber }}\\r\\n \\r\\n Customer Request\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule['HE' + HE_INDEX].value | number:'1.0-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule['HE' + HE_INDEX].value | number:'1.0-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DynamicSchedule['HE' + HE_INDEX].value | number:'1.0-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.UploadDateStamp }}\\r\\n
\\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.UploadTimeString }}\\r\\n
\\r\\n
\\r\\n \\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.DOW }}\\r\\n \\r\\n \\r\\n \\r\\n {{schedule.hasInvalidFileError ? '-' : schedule.SubmittedBy }}\\r\\n \\r\\n
\\r\\n
{{schedule.warningCount}}
\\r\\n
{{schedule.errorCount}}
\\r\\n
\\r\\n Accepted Volume\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n {{schedule.FinalSchedule['HE' + HE_INDEX] | number:'1.0-2'}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n *{{validationMessages[flowdateError.Message].Footnote}}\\r\\n
\\r\\n
\\r\\n
\\r\\n *{{validationMessages[2].Footnote}}\\r\\n
\\r\\n
\\r\\n *{{validationMessages[1].Footnote}}\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n\\r\\n
5 && (isArchiveView)\\\" class=\\\"schedule-paging-container\\\">\\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n\";","module.exports = \"
\\r\\n
\\r\\n

Hello.
The dynamic scheduling feature
is temporarily unavailable.

\\r\\n

Please select an option below.

\\r\\n Home
\\r\\n Contact support\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n

Have questions?

\\r\\n

\\r\\n

Contact Calpine Energy Solutions Technical Support

\\r\\n

Call this toll free number {{contactUsPhone}} at any time

\\r\\n

or send an email to {{contactUsEmail}}

\\r\\n Home
\\r\\n
\\r\\n
\\r\\n\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n

CALPINE ENERGY SOLUTIONS
CLIENT PORTAL

\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\n\\t
\\n\\t\\t\\n\\t
\\n\\t
\\n\\t\\t
\\n\\t\\t\\t

Terms & Conditions

\\n\\t\\t
\\n\\t\\t
\\n\\t\\t
\\n\\t
\\n
\\n
\\n\\t
\\n\\t
\\n\\t
\\n\\t\\t
\\n\\t\\t
\\n
\\r\\n

Terms of Service.


\\r\\n

\\r\\n Welcome to the Calpine Energy Solutions website. The Terms of Service (TOS) below apply to your use of any and all internet sites operated by Calpine Corporation and any if its subsidiaries or affiliates (\\\"Calpine\\\", \\\"we\\\", \\\"our\\\" and \\\"us\\\"). The term \\\"you\\\" or \\\"your\\\" includes any of your subsidiaries, affiliates, and employees.\\r\\n

\\r\\n

\\r\\n Your use of this Site in any form, you agree that you have read, understand and agree to be bound by these terms, and you agree to abide by any rules, policies, and guidelines in connection with such use.\\r\\n

\\r\\n

\\r\\n IF YOU DO NOT AGREE TO ANY OF THESE TERMS, PLEASE DO NOT USE THIS SITE AND LEAVE THE SITE IMMEDITELY.\\r\\n


\\r\\n

Modification

\\r\\n

\\r\\n Calpine may modify these TOS from time to time without prior notice. Modifications shall be effective immediately upon being posted on the Site. You are responsible for reviewing the TOS on this website. Your use of the Site after modifications have been posted constitutes your agreement to be bound by the TOS as modified. If you disagree with the TOS modifications, please discontinue use of the site. Calpine reserves the right to change, modify or discontinue, temporarily or permanently, the Site (or any portion thereof), including any and all content contained on the Site, at any time without notice. Calpine shall not be liable to you or to any third party for any modification, suspension or discontinuance of the Site (or any portion thereof).\\r\\n


\\r\\n

Eligibility

\\r\\n

\\r\\n Only individuals (and not legal entities) who (a) have reached the age of majority (eighteen in most states), (b) have legal capacity to enter into contracts and (c) are citizens of or residents living in the continental United States of America, Alaska, Hawaii or the District of Columbia may buy, manage and pay for products and services through this Site. If you are under the age of majority or otherwise cannot lawfully enter into a contract, you must have your parent or guardian place an order on your behalf and thereby assent to these Conditions of Sale. Any orders placed in contravention to this provision shall be null and void.\\r\\n


\\r\\n

Online Account

\\r\\n

\\r\\n Use of some portions of the Site may require you to register or create an account. In doing so, you agree to: (1) provide true, accurate, current and complete information and (b) maintain and promptly update such information to keep it true, accurate, current and complete.\\r\\n You may also be asked to choose a password and a user name. Please select a password that would not be obvious to someone trying to guess your password, and change it regularly as an added precaution. You are responsible for ensuring that your password and account login are kept secret, safe and secure at all times and you are fully responsible for all activities that occur under your password or account identification. You agree to immediately notify Calpine of any unauthorized use of your password or account or any other breach of security. Without limiting any rights which Calpine may otherwise have, Calpine reserves the right to take any and all action, as it deems necessary or reasonable, to ensure the security of the Sites and your account, including without limitation terminating your account, changing your password, or requesting additional information to authorize transactions on your account. Notwithstanding the above, Calpine may rely on the authority of anyone accessing your account or using your password and in no event and under no circumstances shall Calpine be held liable to you for any damages resulting from or arising out of (a) any action or inaction of Calpine under this provision, (b) any compromise of the confidentiality of your account or password and (c) any unauthorized access to your account or use of your password. You may not use anyone else's account at any time, without the permission of the account holder.\\r\\n


\\r\\n

Privacy

\\r\\n

\\r\\n Please refer to our Privacy Policy for more details about how we may collect and use your personal information in or in connection with the Site. Calpine’s use of your personal information is governed by our Privacy Policy, which is incorporated into herein by reference. You agree that by your use of the Site you consent to the collection and use of your personal information (as set forth in the Privacy Policy).\\r\\n


\\r\\n

Security

\\r\\n

\\r\\n We use reasonable security measures that are designed to protect personal information from accidental loss, disclosure, misuse, and destruction. These measures may include regular review of our data collection and storage processes, data encryption, and security software on our networks and servers. Please be aware, however, that no data security measures can be completely effective. Consequently, you understand and agree that such steps do not guarantee that use of the Site is invulnerable to all security breaches, and that Calpine makes no warranty or representation nor can it ensure that use of any of our Site is protected from viruses, security threats or other vulnerabilities. You transmit information to us at your own risk.\\r\\n


\\r\\n

Accuracy of Services

\\r\\n

\\r\\n While every effort will be made to ensure that the descriptions, information, and service descriptions or other content of the Sites is accurate, complete, reliable, updated, current, or error-free, Calpine does not warrant that the Site is error free. In the event Calpine determines that a service contains an inaccurate price or description, Calpine reserves the right to take any action it deems reasonable and necessary, in its sole discretion, to rectify the error, unless prohibited by law. Calpine may make improvements or changes to any of its content, information or services described on the Sites at any time without notice. You agree to notify Calpine immediately if you become aware of any pricing or descriptive errors or inconsistencies with any services you order through the Sites and to comply with any corrective action.\\r\\n


\\r\\n

Ownership of Content

\\r\\n

\\r\\n Our Site includes a combination of content that we and other third parties create (collectively, the “Content”). All of the Content available through the Site, including, but not limited to, written content, interface design and layout, photographs, graphics, images, illustrations, marks, logos, sound or video clips, software code and animation, is trademarked or copyright protected. You may not use, store, display, modify, reproduce, publish, transmit, participate in the transfer or sale of, create derivative works of, distribute, publicly perform, publicly display, or in any way exploit any of the materials or Content on the Site in whole or in part. If you would like to request permission to use any of the Content on the Site, please contact us.\\r\\n


\\r\\n

Copyright Policy and Digital Millennium Copyright Act (“DMCA”) Notice

\\r\\n

\\r\\n Calpine respects the copyright interests of others and, as such, requires our users to comply with these TOS and all applicable laws regarding copyrights. If you believe that any content shown on or transmitted through the Site violates these TOS or your copyright, please report the violation to: CorporateCommunications@calpine.com and provide the following information:\\r\\n

\\r\\n
    \\r\\n
  • A description of the copyrighted work or other intellectual property that you claim has been infringed;
  • \\r\\n
  • A description of where the material that you claim is infringing is located on the Site (including the exact URL);
  • \\r\\n
  • An address, a telephone number, and an email address where we can contact you;
  • \\r\\n
  • A statement that you have a good-faith belief that the use is not authorized by the copyright or other intellectual property rights owner, by its agent, or by law; and
  • \\r\\n
  • A statement by you under penalty of perjury that the information in your notice is accurate and that you are the copyright or intellectual property owner or are authorized to act on the owner’s behalf.
  • \\r\\n
\\r\\n

\\r\\n It is often difficult to determine if your intellectual property rights have been violated. We may request additional information before we remove allegedly infringing material. If a dispute develops as to the correct owner of the rights in question, we reserve the right to remove the content of both parties.\\r\\n


\\r\\n

Copyright

\\r\\n

\\r\\n You may download one copy of the materials in this website for viewing [and printing a single copy of limited portions of the material] on a single computer [for personal use only or any other limitation]. Except as stated above, you may not download, upload, display, copy, reproduce, reprint, modify or distribute the material without the express prior written consent of Calpine.\\r\\n


\\r\\n

Trademarks and Service Marks

\\r\\n

\\r\\n All trademarks, service marks and trade names, including federal state and common law, are proprietary of Calpine unless otherwise indicated.\\r\\n


\\r\\n

Contributions

\\r\\n

\\r\\n Calpine welcomes your comments. Unfortunately, however, Calpine’s long-standing company policy does not allow it to accept or consider creative ideas, suggestions or materials other than those it has specifically requested. Accordingly, we must ask that you not send us any original or creative ideas, suggestions or materials. While Calpine does value your feedback on our services and products, we request that you be specific in your comments on those services and products, and do not submit any creative ideas, suggestions or materials.\\r\\n If despite our requests that you do not send Calpine any such materials, you send Calpine creative suggestions, ideas, notes, drawings, concepts or other information (collectively, the \\\"Contribution\\\"), such Contribution shall be deemed, and shall remain, the exclusive property of Calpine, unless prohibited by law in which case you hereby grant Calpine a perpetual, worldwide, irrevocable, unrestricted, non-exclusive, royalty-free license to use the Contributions in any manner whatsoever without compensation or attribution to you. Use of the Contribution shall not require permission from or payment to you or to any other person or entity. No Contribution shall be subject to any obligation of confidentiality, express of implied, on the part of Calpine, and Calpine shall not be liable for any use or disclosure of the Contribution. You represent and warrant that you own or otherwise control all of the rights to the Contribution that you post, that the Contribution is accurate and, that use of the Contribution you supply does not violate these TOS and will not cause injury to any person or entity. Without limiting the foregoing, Calpine shall exclusively own all now known or hereafter existing rights to any Contribution.\\r\\n


\\r\\n

Links to Third Party Sites

\\r\\n

\\r\\n To provide you with access to related sites, our Site may contain links to third-party websites. By clicking on or following through to any such websites, you agree to review and agree to such third-party website’s terms of use and privacy policies. Calpine is not responsible for the privacy practices or the content of any such third-party websites. Links are not intended to imply sponsorship, affiliation or endorsement of the linked website or any content or material on such website. If you believe that Calpine has provided a link to a website that contains infringing or illegal content or material, please notify us so that we may evaluate whether (in our sole discretion) to disable or remove such link.\\r\\n


\\r\\n

Restrictions on Use of the Site

\\r\\n

\\r\\n Subject to the terms and conditions of these Terms of Service, Calpine hereby grants you a revocable, non-transferable, non-exclusive, personal and limited license to use and view in manner consistent with all applicable laws and regulations.\\r\\n


\\r\\n

Limitation of Liability

\\r\\n

\\r\\n IN NO EVENT WILL CALPINE ITS EMPLOYEES, OFFICERS, REPRESENTATIVES, SERVICE PROVIDERS, SUPPLIERS, LICENSORS, AND AGENTS BE LIABLE TO YOU FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, INCIDENTAL OR SPECIAL DAMAGES, INCLUDING WITHOUT LIMITATION, LOSS OF USE, LOSS OF PROFITS, OR LOSS OF DATA, WHETHER IN AN ACTION IN CONTRACT, TORT (INCLUDING BUT NOT LIMITED TO NEGLIGENCE), OR OTHERWISE, ARISING OUT OF OR IN ANY WAY CONNECTED WITH (I) THE USE OR INABILITY TO USE THE SITES OR THE CONTENT, MATERIALS, INFORMATION OR TRANSACTIONS PROVIDED ON OR THROUGH THE SITES, OR (II) ANY CLAIM ATTRIBUTABLE TO ERRORS, OMISSIONS, OR OTHER INACCURACIES IN THE SITES OR THE CONTENT, MATERIALS, INFORMATION, PRODUCTS, OR SERVICES ON OR AVAILABLE THROUGH THE SITES, (III) THE COST OF PROCUREMENT OF SUBSTITUTE GOODS AND SERVICES RESULTING FROM ANY DATA, INFORMATION OR SERVICES PURCHASED OR OBTAINED OR TRANSACTIONS ENTERED INTO THROUGH OR FROM OUR SITE; (IV) UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA; (V) STATEMENTS OR CONDUCT OF ANY THIRD PARTY ON OUR SITE; (VI) THE DELAY OR FAILURE IN PERFORMANCE RESULTING FROM AN ACT OF FORCE MAJEURE, INCLUDING WITHOUT LIMITATION, ACTS OF GOD, NATURAL DISASTERS, COMMUNICATIONS FAILURE, GOVERNMENTAL ACTIONS, WARS, STRIKES, LABOR DISPUTES, RIOTS, SHORTAGES OF LABOR OR MATERIALS, VANDALISM, TERRORISM, NON-PERFORMANCE OF THIRD PARTIES OR ANY REASONS BEYOND THEIR REASONABLE CONTROL; OR (VII) ANY OTHER MATTER RELATING TO OUR SITE, EVEN IF YOU CLAIM TO HAVE NOTIFIED CALPINE ABOUT SUCH DAMAGES, OR FOR ANY CLAIMS BY ANY THIRD PARTIES, UNLESS OTHERWISE PROVIDED FOR BY LAW, THEN THE AGGREGATE LIABILITY OF CALPINE UNDER SUCH CIRCUMSTANCES FOR LIABILITIES THAT OTHERWISE WOULD HAVE BEEN LIMITED SHALL NOT EXCEED ONE HUNDRED DOLLARS ($100).\\r\\n YOU ACKNOWLEDGE THAT THIS LIMITATION OF LIABILITY IS AN ESSENTIAL TERM BETWEEN YOU AND US RELATING TO THE PROVISION OF THE SITE, THE SERVICE AND THE CONTENT TO YOU, AND WE WOULD NOT PROVIDE THE SITE OR SERVICE OR CONTENT TO YOU WITHOUT THIS LIMITATION.\\r\\n YOUR SOLE REMEDY FOR DISSATISFACTION WITH THE SITE AND/OR SITE-RELATED SERVICES IS TO STOP USING THE SITE AND/OR THOSE SERVICES.\\r\\n


\\r\\n

Disclaimer of Warranties

\\r\\n

\\r\\n Some of the information on this website may contain projections or other forward-looking statements regarding future events or the future financial performance of Calpine. We wish to caution you that these statements are only predictions and that actual events or results may differ materially. We refer you to the documents that Calpine files from time to time with the United States Securities and Exchange Commission, including the company's most recent Annual Report on Form 10-K and Quarterly Report on Form 10-Q. These documents identify important factors that could cause Calpine's actual results to differ materially from those contained in any projections or forward-looking statements.\\r\\n

\\r\\n

\\r\\n IN ADDITION, CALPINE MAKES NO WARRANTIES, REPRESENTATIONS OR GUARANTEES THAT THIS SITE (I) WILL BE FREE OF INFECTION OR VIRUSES, WORMS, TROJAN HORSES, OR OTHER CODE THAT MANIFESTS CONTAMINATING OR DESTRUCTIVE PROPERTIES; (II) WILL BE TIMELY, CONTINUOUS AND WITHOUT INTERRUPTION (III) SECURE (INCLUDING FREE FROM UNAUTHORIZED ACCESS), PROVIDE CONTINUOUS STORAGE OR ACCESS, OR ERROR-FREE, (IV) THE RESULTS THAT MAY BE OBTAINED FROM THE USE OF OUR SITE WILL BE ACCURATE, COMPLETE OR RELIABLE, (V) THE QUALITY OF ANY SERVICES, INFORMATION, OR OTHER MATERIAL PURCHASED OR OBTAINED BY YOU THROUGH OUR SITE WILL MEET YOUR EXPECTATIONS, AND (VI) ANY ERRORS IN OUR SITE OR SOFTWARE WILL BE CORRECTED.\\r\\n

\\r\\n

\\r\\n CALPINE HEREBY DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS OR IMPLIED, STATUTORY, ORAL OR WRITTEN, INCLUDING, WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF MERCHANTABILITY, REASONABLE CARE, ACCURACY, FITNESS FOR A PARTICULAR PURPOSE, AND ANY AND ALL WARRANTIES OF TITLE, ACCURACY OF DATE AND/OR NON-INFRINGEMENT, UNLESS OTHERWISE PROHIBITED BY LAW.\\r\\n

\\r\\n

\\r\\n TO THE EXTENT THAT YOU MIGHT OTHERWISE BELIEVE THAT WARRANTIES, REPRESENTATIONS OR GUARANTEES HAVE BEEN MADE TO YOU, YOU HEREBY AGREE THAT SUCH STATEMENTS, WHETHER MADE ORALLY OR IN WRITING, ARE TO BE CONSTRUED MERELY AS NONBINDING EXPRESSIONS OF POLICY RATHER THAN AFFIRMATIVE REPRESENTATIONS, OBLIGATIONS, GUARANTEES OR WARRANTIES. IN THE EVENT OF ANY CONFLICT BETWEEN THIS SECTION AND OTHER TERMS OR PROVISIONS OF THE TOS, THIS SECTION SHALL BE CONSTRUED TO TAKE PRECEDENCE.\\r\\n


\\r\\n

Governing Law

\\r\\n

\\r\\n By visiting or using the Site, you agree that the laws of the State of Texas, without regard to principles of conflicts of law, will govern our Privacy Policy and these Terms of Service and any dispute of any sort that might arise between you and Calpine. You agree that any action at law or in equity that arises out of or relates to any use of the Site will be filed solely and exclusively in the state or federal courts located in Harris County, and you hereby consent and submit to the personal jurisdiction and venue of such courts for the purposes of litigating any such action.\\r\\n


\\r\\n

Indemnification

\\r\\n

\\r\\n You agree to indemnify, hold harmless and, at our option, defend Calpine (including our affiliates, officers, directors, employees, agents, licensors, suppliers, and any-third part information providers from and against all damages, claims, demands, liabilities, losses costs and expenses, including reasonable attorney’s fees in connection with or arising out of violation of these TOS, your use of the Site, the Content, the Contributions, these TOS, your passwords and/or account information, or your violation of any law or the rights of another. These obligations will survive any termination of your relationship with Calpine or your use of our Site.\\r\\n


\\r\\n

Termination of Right to Use Website

\\r\\n

\\r\\n If you breach any of the terms of these TOS, Calpine may terminate your right to use the Website. Upon such termination, you immediately shall delete or destroy any copies (electronic or otherwise) of the Content or any other materials or information you have obtained from the Website.\\r\\n


\\r\\n

No Waiver

\\r\\n

\\r\\n No delay or omission by Calpine to exercise any right or power occurring upon any breach of these TOS shall impair any such right or power or be construed to be a waiver thereof. A waiver by Calpine of any breach of these TOS shall not be construed to be a waiver of any subsequent breach.\\r\\n


\\r\\n

Severability

\\r\\n

\\r\\n The determination that any provision of these TOS is invalid or unenforceable will not affect the validity or enforceability of the remaining provisions or of that provision under other circumstances. Any invalid or unenforceable provision will be enforced to the maximum extent permitted by law.\\r\\n


\\r\\n

Entire Agreement

\\r\\n

\\r\\n These Terms of Service (as amended from time to time), including policies incorporated herein (e.g., Privacy Policy) constitute the entire agreement between you and Calpine regarding the Site and your use of the Site or the Content, and supersede any prior agreement or understanding, arrangements, undertaking or proposal, written or oral, between you and Calpine in relation to such matters.\\r\\n


\\r\\n

\\r\\n If you have questions about these TOS, do not hesitate to contact us at corporatecommunications@calpine.com.\\r\\n


\\r\\n
\\n\\t\\t
\\n\\t
\\n\\t
\\n\\t
\\n
`\";","module.exports = \"
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n / \\r\\n {{breadcrumb.label}}\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\";","module.exports = \"\\r\\n\\r\\n
\\r\\n

Download Documents Queue

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
Document
{{invoice.counterpartyName}} {{invoice.accountNumber}} {{invoice.invoiceDate | date: 'MM/dd/yyyy'}}
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\";","module.exports = \"
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\t403\\r\\n\\t\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\tThe Requested Resource is Forbidden\\r\\n\\t\\t
\\r\\n\\t\\t\\r\\n\\t
\\r\\n\\t
\\r\\n
\";","module.exports = \"
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t\\t
{{message}}
\\r\\n\\t\\t
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t
\\r\\n\\r\\n\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\r\\n\\t\\t
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\r\\n\\t\\t
\\r\\n\\t
\\r\\n
\";","module.exports = \"
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\t404\\r\\n\\t\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\tThe Requested Resource Not Found\\r\\n\\t\\t
\\r\\n\\t\\t\\r\\n\\t
\\r\\n\\t
\\r\\n
\";","module.exports = \"
\\r\\n\\t
\\r\\n\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\t401\\r\\n\\t\\t
\\r\\n\\t\\t
\\r\\n\\t\\t\\tYou are not authorized to access this page\\r\\n\\t\\t
\\r\\n\\t\\t\\r\\n\\t
\\r\\n\\t
\\r\\n
\";","module.exports = \"\";","module.exports = \"
\\r\\n
\\r\\n
True
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
False
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"\\r\\n
\\r\\n
\\r\\n

{{modalData.headerText}}

\\r\\n
\\r\\n
\\r\\n
\\r\\n
  
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"\";","module.exports = \"
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n {{rd.routerText}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n

Outdated Browser Detected

\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n If this page looks broken please consider updating your browser\\r\\n
to fix it and to benefit from the advanced functionality.\\r\\n
\\r\\n
\\r\\n
\\r\\n
For a better experience, keep your browser up to date. Check here for latest versions.
\\r\\n \\r\\n \\r\\n \\r\\n  \\r\\n \\r\\n \\r\\n \\r\\n  \\r\\n \\r\\n \\r\\n \\r\\n  \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
SHOW PER PAGE
\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Calpine Energy Solutions
Client Portal

\\r\\n
\\r\\n
\\r\\n {{message}}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n Password Reset Request has been cancelled successfully.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Change Password
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{message}}\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n Old Password is required.\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n Password with minimum 8 and maximum 20 characters with minimum 1 Upper, 1 Lower, (1 Digit or 1 Special Character)\\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n Password mismatch\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Calpine Energy Solutions
Client Portal

\\r\\n
\\r\\n
\\r\\n {{message}}\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n The link has expired\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Enter your email address below and we'll send you instructions on how to complete your registration.
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Enter your new portal password.
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n Password with min 8 and max 20 characters with 1 Upper, 1 Lower, (1 Digit or 1 Special Character)\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n Password mismatch\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Calpine Energy Solutions
Client Portal

\\r\\n
\\r\\n
\\r\\n {{message}}\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
Enter your new portal password.
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n Password with min 8 and max 20 characters with 1 Upper, 1 Lower, (1 Digit or 1 Special Character)\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n Password mismatch\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n Email sent! {{messageOptions.headerText}} follow the instructions we've sent to your email address.\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n {{messageOptions.footerText}}\\r\\n
Check your spam folder for an email from {{supportEmail}}\\r\\n
If you still don't see the email,\\r\\n try again\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n

Calpine Energy Solution
Client Portal

\\r\\n
\\r\\n
\\r\\n {{message}}\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
Forgot your password?
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n The link has expired\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Enter your email address below and we'll send you instructions on how to change your password.
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n
Account Information
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\";","module.exports = \"
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n Account Information \\r\\n
\\r\\n Update your information here\\r\\n
\\r\\n
\\r\\n \\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n \\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n \\r\\n \\r\\n
\\r\\n
\\r\\n Have Questions?\\r\\n
\\r\\n
\\r\\n
\\r\\n Contact your Calpine Energy Solutions\\r\\n
\\r\\n Customer Service Representative\\r\\n
\\r\\n
\\r\\n Call this toll-free number {{supportPhone}} at any time or send an e-mail to
\\r\\n {{supportEmail}}\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n
\\r\\n\";","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./counterparty-users-add-edit-dialog.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./counterparty-users-grouped-row.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./counterparty-users.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./users.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../node_modules/css-loader/dist/cjs.js!./app.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./help-schedule.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./schedule-archive.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./schedule-upload.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./dynamic-scheduling.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../node_modules/css-loader/dist/cjs.js!./home.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./breadcrumb.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./datepicker-popup.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./footer.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./nav-menu.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../../node_modules/css-loader/dist/cjs.js!./sub-nav-menu.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./pager.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import api from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import content from \"!!../../../../node_modules/css-loader/dist/cjs.js!./user-management.component.css\";\n\nvar options = {};\n\noptions.insert = \"head\";\noptions.singleton = false;\n\nvar update = api(content, options);\n\n\n\nexport default content.locals || {};","import { ConfirmEmailModel } from './../../user-management/shared/confirm-email.model';\r\nimport { AuthenticationService } from './../../authentication/authentication.service';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { Component, OnInit } from '@angular/core';\r\nimport { ICellRendererAngularComp } from 'ag-grid-angular';\r\nimport { ICellRendererParams } from 'ag-grid-community';\r\nimport { AddEditUserModalParams, RemoveUserModalParams, CounterpartyUserInfo } from './counterparty-users.model';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { param } from 'jquery';\r\n\r\n@Component({\r\n selector: 'counterparty-user-edit-delete-buttons',\r\n template: `\r\n
\r\n \r\n \r\n
\r\n `\r\n})\r\n\r\nexport class CounterpartyUserEditDeleteButtonComponent implements ICellRendererAngularComp {\r\n params: ICellRendererParams;\r\n hasPortalAdminRole: boolean;\r\n disabled: boolean = false;\r\n constructor(private counterpartyUserService: CounterpartyUsersService,\r\n private authService: AuthenticationService,\r\n private loggedInUserService: LoggedInUserService) { }\r\n \r\n agInit(params: ICellRendererParams): void {\r\n this.params = params;\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n if (this.params.data && this.params.data.email) {\r\n this.disabled = false;\r\n }\r\n else {\r\n this.disabled = true;\r\n }\r\n }\r\n \r\n refresh(params: any): boolean {\r\n if (this.params.data && this.params.data.email) {\r\n this.disabled = false;\r\n }\r\n else {\r\n this.disabled = true;\r\n }\r\n return false;\r\n }\r\n\r\n openAddEditUserModal() {\r\n let params: AddEditUserModalParams = {\r\n isAdd: false,\r\n isNewUser: false,\r\n id: this.params.data.id,\r\n userInfo: this.loggedInUserService.getLoggedInUser(),\r\n hasPortalAdminRole: this.authService.isPortalAdminUser(),\r\n counterpartyId: this.params.data.counterpartyId,\r\n counterpartyName: this.params.data.shortName,\r\n rowIdx: this.params.rowIndex\r\n };\r\n this.counterpartyUserService.openAddEditUserDialog(params);\r\n }\r\n\r\n openRemoveUserModal() {\r\n let params: RemoveUserModalParams = {\r\n counterpartyId: this.params.data.counterpartyId,\r\n email: this.params.data.email\r\n };\r\n\r\n this.counterpartyUserService.openRemoveUserDialog(params);\r\n }\r\n}","import {\r\n ChangeDetectorRef,\r\n Component,\r\n EventEmitter,\r\n OnInit,\r\n Input,\r\n Output,\r\n ViewChild\r\n} from '@angular/core';\r\nimport { GridApi, GridOptions, GridReadyEvent, IGetRowsParams, RowNode, IRowNode, GridSizeChangedEvent } from 'ag-grid-community';\r\n\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { UsersService } from '../../administration/users/users.service';\r\nimport { IUserData, LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { CounterpartyUserInfo, UserCounterparty } from './counterparty-users.model';\r\nimport { CounterpartyUsersRolesComponent } from './counterparty-users-roles.component';\r\n\r\nimport { IMultiSelectOption, IMultiSelectSettings, IMultiSelectTexts } from '../../shared/multiselect-dropdown/multiselect-dropdown';\r\nimport { CounterpartyActive, Counterparty, AddEditUserModalParams } from '../../administration/counterparty-users/counterparty-users.model';\r\nimport { GridService } from '../../shared/grid/grid.service';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { Typeahead } from '../../shared/typeahead/cp-typeahead.component';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\r\nimport { map } from 'rxjs/operators';\r\nimport { param } from 'jquery';\r\n\r\ninterface IUserRowsParams extends IGetRowsParams {\r\n counterpartyId: number;\r\n}\r\n\r\n@Component({\r\n selector: 'counterparty-users-add-edit-dialog',\r\n template: require('./counterparty-users-add-edit-dialog.component.html'),\r\n styles: [require('./counterparty-users-add-edit-dialog.component.css').toString()]\r\n})\r\nexport class CounterpartyUsersAddEditDialogComponent implements OnInit {\r\n newUserGridOptions: GridOptions;\r\n @ViewChild(CounterpartyUsersRolesComponent) counterpartyUsersRolesComponent: CounterpartyUsersRolesComponent;\r\n @ViewChild(Typeahead) emailTypeahead: Typeahead;\r\n\r\n //@Input() isEditView: boolean;\r\n @Input() user: AddEditUserModalParams;\r\n @Output() userUpdated = new EventEmitter();\r\n\r\n public loggedInUser: IUserData;\r\n public userAccountId: number;\r\n public counterpartyId: number;\r\n public firstName: string;\r\n public lastName: string;\r\n public email: string;\r\n public originalEmail: string;\r\n public salutation: string;\r\n public phoneNumber: string;\r\n public editUserDialogStep: number;\r\n public hasEmail: boolean;\r\n public emailPassesFormat: boolean;\r\n public emailAlreadyExists: boolean;\r\n public emailAlreadyExistsEdit: boolean;\r\n public isNewUser: boolean;\r\n public isFromUsersTab: boolean;\r\n public checkingEmailAlreadyExists: boolean;\r\n public hasFirstName: boolean;\r\n public hasLastName: boolean;\r\n public isAccountVerified: boolean;\r\n public isLoginAllowed: boolean;\r\n public loggedInUserIsPortalAdmin: boolean;\r\n public showRegistration: boolean;\r\n public allValidationPasses: boolean;\r\n public canSaveCounterparty: boolean;\r\n public isAccordionHidden: boolean;\r\n public clickRemoveButtonEventListener: EventListener;\r\n public isInternal: boolean = false;\r\n public isUserPortalAdmin: boolean = false;\r\n public isImpersonateScheduler: boolean = false;\r\n public isImpersonateBilling: boolean = false;\r\n public isImpersonateAdmin: boolean = false;\r\n public isEmailDisabled: boolean = true;\r\n // Typeahead variables\r\n public typeaheadActive: boolean;\r\n public userSearchList: any[];\r\n\r\n public hasPortalAdminRole: boolean;\r\n public existingUserGUID: string;\r\n public hasValidEmail: boolean; // this is for the server call. Is the email taken, are they on the counterparty, etc.\r\n public existingUserProfile: IUserData;\r\n public placeholderText: string;\r\n public canAddCounterparty: boolean;\r\n public canSave: boolean;\r\n public canResendWelcomeEmail: boolean;\r\n public userAlreadyOnCounterparty: boolean;\r\n public userAlreadyExists: boolean;\r\n\r\n private initialGridLoad: boolean;\r\n private userProfile: any;\r\n private counterUserProfile: any;\r\n public isAddUser: boolean;\r\n public showSpinner: boolean = false;\r\n private rowIndex: number;\r\n private oldUserInfo: any;\r\n private currentUserProfile: any;\r\n private isGettingUser: boolean;\r\n frameworkComponents: any;\r\n storedAgGridParams: IUserRowsParams;\r\n // Counterparty Dropdown Settings\r\n private loadedCounterparties: CounterpartyActive[];\r\n private loadedCounterpartiesDropdown: CounterpartyActive[];\r\n private selectedCounterpartyId: number;\r\n private selectedCounterpartyName: string;\r\n private userSelectedCounterparties: UserCounterparty[];\r\n // CustomerPoint Dropdown Settings\r\n private customerPointOptions: IMultiSelectOption[];\r\n private customerPointSelectedOptions: number[];\r\n private customerPointSelectedIds: number[];\r\n private customerPointSelectedNames: string[];\r\n private customerPointSelectSettings: IMultiSelectSettings = {\r\n enableSearch: true,\r\n checkedStyle: 'checkboxes',\r\n showCheckAll: true,\r\n showUncheckAll: true,\r\n autoUnselect: true,\r\n dynamicTitleMaxItems: 0,\r\n buttonClasses: 'button-green',\r\n pullRight: false\r\n };\r\n public customerPointTexts: IMultiSelectTexts = {\r\n checkAll: 'Select All',\r\n uncheckAll: 'Deselect All',\r\n searchPlaceholder: 'Search...',\r\n defaultTitle: 'Select Customer Point(s)',\r\n };\r\n private schedulerCounterparties: UserCounterparty[];\r\n private userCounterParties: UserCounterparty[] = [];\r\n private gridApi!: GridApi;\r\n gridData: UserCounterparty[] = [];\r\n //Impersonate Dropdown Setting\r\n private impersonateOptions: string[];\r\n private impersonateReportOptions: IMultiSelectOption[];\r\n private impersonateSelectedOptions: number[];\r\n private impersonateSelectSettings: IMultiSelectSettings = {\r\n enableSearch: false,\r\n checkedStyle: 'checkboxes',\r\n showCheckAll: true,\r\n showUncheckAll: true,\r\n autoUnselect: true,\r\n dynamicTitleMaxItems: 0,\r\n buttonClasses: 'button-green',\r\n pullRight: true\r\n };\r\n public impersonateTexts: IMultiSelectTexts = {\r\n checkAll: 'Select All',\r\n uncheckAll: 'Deselect All',\r\n defaultTitle: 'Select Report Impersonate Option(s)',\r\n };\r\n\r\n constructor(private counterpartyUsersService: CounterpartyUsersService,\r\n private usersService: UsersService,\r\n private loggedInUserService: LoggedInUserService,\r\n private gridService: GridService,\r\n private changeDetectorRef: ChangeDetectorRef,\r\n private authService: AuthenticationService,\r\n private activeModal: NgbActiveModal) {\r\n this.userSearchList = [];\r\n this.typeaheadActive = true;\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n this.placeholderText = 'example@domain.com';\r\n this.canAddCounterparty = false;\r\n this.canSaveCounterparty = false;\r\n this.canSave = false;\r\n this.canResendWelcomeEmail = false;\r\n this.userAlreadyOnCounterparty = false;\r\n this.userAlreadyExists = false;\r\n }\r\n\r\n ngOnInit() {\r\n this.isAccordionHidden = true;\r\n\r\n //CustomerPoint Dropdown\r\n this.customerPointSelectedIds = [];\r\n this.customerPointSelectedNames = [];\r\n this.userSelectedCounterparties = [];\r\n this.customerPointOptions = [];\r\n this.customerPointSelectedOptions = [];\r\n\r\n //Impersonate Dropdown - The Tabs are added here, and the Reports are gathered from the Reports table\r\n this.setImpersonateOptions();\r\n this.impersonateSelectedOptions = [];\r\n\r\n this.initialGridLoad = true;\r\n this.showSpinner = false;\r\n this.canSaveCounterparty = true;\r\n var self = this;\r\n this.loadCounterparties().subscribe((cps: any) => {\r\n self.loadedCounterparties = cps;\r\n });\r\n this.frameworkComponents = {\r\n };\r\n\r\n this.newUserGridOptions = {\r\n headerHeight: 50,\r\n //serverSideSortOnServer: true,\r\n //serverSideFilterOnServer: true,\r\n rowSelection: 'multiple',\r\n columnDefs: this.createColumnDefs(),\r\n defaultColDef: { resizable: true },\r\n //frameworkComponents: this.frameworkComponents,\r\n onGridReady: (params: GridReadyEvent) => {\r\n //this.setUserGridDataSource(params);\r\n this.gridApi = params.api;\r\n },\r\n onModelUpdated: (params) => {\r\n //if (this.gridApi) {\r\n // this.gridApi.sizeColumnsToFit();\r\n //}\r\n },\r\n onGridSizeChanged(params: GridSizeChangedEvent) {\r\n // Only resize columns if the grid container actually has a width\r\n if (params.clientWidth > 0) {\r\n params.api.sizeColumnsToFit();\r\n }\r\n },\r\n suppressMenuHide: true,\r\n suppressPaginationPanel: true,\r\n overlayLoadingTemplate:\r\n '
',\r\n icons: {\r\n menu: '',\r\n groupExpanded: '',\r\n groupContracted: ''\r\n }\r\n };\r\n\r\n setTimeout(() => {\r\n this.initDialogBox();\r\n }, 500);\r\n }\r\n\r\n private async initDialogBox() {\r\n var data = await this.retrieveAllCounterparties();\r\n localStorage.setItem('allCounterparties', JSON.stringify(data));\r\n\r\n this.setupAddEditUserDialogBox(this.user.isAdd,\r\n this.user.isNewUser,\r\n this.user.userInfo,\r\n this.user.hasPortalAdminRole,\r\n this.user.id,\r\n this.user.counterpartyId,\r\n this.user.counterpartyName,\r\n this.user.rowIdx,\r\n this.user.isFromUsersTab);\r\n }\r\n\r\n public retrieveAllCounterparties(): Promise {\r\n return this.loggedInUserService.getAllCounterpartiesAndCustomerPoints().toPromise();\r\n }\r\n\r\n public async setupAddEditUserDialogBox(isAdd: boolean,\r\n isNewUser: boolean,\r\n userInfo: IUserData,\r\n hasPortalAdminRole: boolean,\r\n id: string,\r\n counterpartyId: number,\r\n counterpartyName: string,\r\n rowIdx: number,\r\n isFromUsersTab: boolean) {\r\n this.counterpartyId = counterpartyId;\r\n this.rowIndex = rowIdx;\r\n this.loggedInUserIsPortalAdmin = hasPortalAdminRole;\r\n this.showSpinner = false;\r\n if (!this.isAccordionHidden) {\r\n this.hideAccordion();\r\n }\r\n this.isAddUser = isAdd;\r\n this.isNewUser = isNewUser;\r\n this.isFromUsersTab = isFromUsersTab;\r\n this.changeDetectorRef.detectChanges();\r\n if (await this.isAddingNewUserFromUsersTab()) { // Check if email already exists, clear form, etc.\r\n this.resetTypeahead();\r\n this.resetForm();\r\n this.hasFirstName = false;\r\n this.hasLastName = false;\r\n if (this.loggedInUserService.isImpersonate) {\r\n this.emailTypeahead.setDisabledState(true);\r\n }\r\n }\r\n else if (await this.isEditingUserFromUsersTab() || await this.isAddingExistingUserFromCounterpartyUsersTab()) { // Allow to update email, change name and add/edit counterparties/customer points\r\n this.emailTypeahead.setDisabledState(true);\r\n this.oldUserInfo = userInfo;\r\n var self = this;\r\n this.userProfile = await this.usersService.getUser(id).toPromise();\r\n this.setRoles(this.userProfile);\r\n self.existingUserProfile = this.userProfile;\r\n self.existingUserGUID = id;\r\n self.userAccountId = this.userProfile.key;\r\n self.firstName = this.userProfile.firstName;\r\n self.lastName = this.userProfile.lastName;\r\n self.setHasFirstAndLastName();\r\n self.email = this.userProfile.email;\r\n self.isEmailNotEmpty();\r\n self.doesEmailPassFormat();\r\n self.originalEmail = this.userProfile.email;\r\n self.phoneNumber = this.userProfile.phone;\r\n self.salutation = this.userProfile.salutation;\r\n self.isAccountVerified = this.userProfile.isAccountVerified;\r\n self.isLoginAllowed = this.userProfile.isLoginAllowed;\r\n self.showRegistration = self.loggedInUserIsPortalAdmin;\r\n let counterparties = this.userProfile.counterparties as UserCounterparty[];\r\n var activeCounterparties: UserCounterparty[] = self.populateCounterparties(counterparties);\r\n self.populateUserCounterparties(activeCounterparties);\r\n self.userSelectedCounterparties = counterparties;\r\n self.setButtonsEnabled(true, self);\r\n self.fillForm(this.userProfile);\r\n this.setInternalRole();\r\n if (this.loggedInUserService.isImpersonate) {\r\n this.impersonateSelectSettings.showCheckAll = false;\r\n this.impersonateSelectSettings.showUncheckAll = false;\r\n }\r\n }\r\n else if (await this.isAddingNewUserFromCounterpartyUsersTab()) {\r\n this.clearForm();\r\n this.isEmailNotEmpty();\r\n this.selectedCounterpartyId = counterpartyId;\r\n this.selectedCounterpartyName = counterpartyName;\r\n this.populateCustomerPointsOptions(counterpartyId);\r\n this.resetTypeahead();\r\n this.resetForm();\r\n if (this.loggedInUserService.isImpersonate) {\r\n this.emailTypeahead.setDisabledState(true);\r\n }\r\n }\r\n else if (await this.isEditingUserFromCounterpartyUsersTab()) {\r\n this.emailTypeahead.setDisabledState(true);\r\n var self = this;\r\n this.counterUserProfile = await this.counterpartyUsersService.getUser(id).toPromise();\r\n this.setRoles(this.counterUserProfile);\r\n self.existingUserProfile = this.counterUserProfile;\r\n self.existingUserGUID = id;\r\n self.userAccountId = this.counterUserProfile.key;\r\n self.firstName = this.counterUserProfile.firstName;\r\n self.lastName = this.counterUserProfile.lastName;\r\n self.setHasFirstAndLastName();\r\n if (this.counterUserProfile.email != undefined || this.counterUserProfile.email != null) {\r\n self.email = this.counterUserProfile.email;\r\n self.isEmailNotEmpty();\r\n }\r\n self.doesEmailPassFormat();\r\n self.originalEmail = this.counterUserProfile.email;\r\n self.phoneNumber = this.counterUserProfile.phone;\r\n self.salutation = this.counterUserProfile.salutation;\r\n self.isAccountVerified = this.counterUserProfile.isAccountVerified;\r\n self.isLoginAllowed = this.counterUserProfile.isLoginAllowed;\r\n self.showRegistration = self.loggedInUserIsPortalAdmin;\r\n let counterparties = this.counterUserProfile.counterparties as UserCounterparty[];\r\n if (counterparties != null || counterparties != undefined){\r\n var activeCounterparties: UserCounterparty[] = self.populateCounterparties(counterparties);\r\n }\r\n self.populateUserCounterparties(activeCounterparties);\r\n self.userSelectedCounterparties = counterparties;\r\n self.setButtonsEnabled(true, self);\r\n self.fillForm(this.counterUserProfile);\r\n this.setInternalRole();\r\n if (this.loggedInUserService.isImpersonate) {\r\n this.impersonateSelectSettings.showCheckAll = false;\r\n this.impersonateSelectSettings.showUncheckAll = false;\r\n }\r\n }\r\n var verified = this.isAccountVerified && this.isLoginAllowed;\r\n this.canResendWelcomeEmail = this.loggedInUserIsPortalAdmin && !verified;\r\n //this.modalAddEditUserDialog.open();\r\n $('#edit-user-scroll-area').animate({ scrollTop: 0 });\r\n }\r\n\r\n public populateCounterparties(counterparties: any): UserCounterparty[] {\r\n let allCounterparties: Counterparty[] = JSON.parse(localStorage.getItem('allCounterparties')) as Counterparty[];\r\n var activeCounterparties: UserCounterparty[] = new Array();\r\n counterparties.forEach(function (userCounterparty) {\r\n let storedCounterparty: Counterparty = allCounterparties.filter(c => c.counterpartyId == userCounterparty.counterpartyId)[0] as Counterparty;\r\n if (storedCounterparty !== undefined) {\r\n activeCounterparties.push(userCounterparty);\r\n userCounterparty.counterpartyName = storedCounterparty.shortName;\r\n if (userCounterparty.customerPoints != null) {\r\n userCounterparty.customerPointNames = getCustomerPointNames(userCounterparty, storedCounterparty);\r\n if (userCounterparty.customerPoints.length === storedCounterparty.customerPoints.length) {\r\n var allText: string[] = [\"All\"];\r\n userCounterparty.customerPointNamesDisplay = allText;\r\n } else {\r\n userCounterparty.customerPointNamesDisplay = getCustomerPointNames(userCounterparty, storedCounterparty);\r\n }\r\n }\r\n }\r\n });\r\n return activeCounterparties;\r\n }\r\n public fillForm(userInfo: any) {\r\n this.firstName = userInfo.firstName;\r\n this.lastName = userInfo.lastName;\r\n if (userInfo.email != undefined) {\r\n this.email = userInfo.email;\r\n this.setEmailTypeahead(userInfo.email);\r\n this.originalEmail = userInfo.email;\r\n }\r\n else {\r\n this.email = null;\r\n this.setEmailTypeahead(null);\r\n this.originalEmail = null;\r\n }\r\n this.salutation = userInfo.salutation === null ? '' : userInfo.salutation;\r\n this.phoneNumber = userInfo.phone;\r\n this.isAccountVerified = userInfo.isAccountVerified;\r\n this.isLoginAllowed = userInfo.isLoginAllowed;\r\n this.showRegistration = this.loggedInUserIsPortalAdmin;\r\n\r\n this.setHasFirstAndLastName();\r\n this.hasEmail = true;\r\n this.emailPassesFormat = true;\r\n this.emailAlreadyExists = false;\r\n this.emailAlreadyExistsEdit = this.doesEmailAlreadyExistEdit();\r\n this.checkingEmailAlreadyExists = false;\r\n this.allValidationPasses = !(this.hasFirstName == null || this.hasLastName == null);\r\n if (userInfo.counterparties != null || userInfo.counterparties != undefined) {\r\n var activeCounterparties: UserCounterparty[] = this.populateCounterparties(userInfo.counterparties);\r\n }\r\n this.populateUserCounterparties(activeCounterparties);\r\n\r\n }\r\n private doesEmailAlreadyExistEdit() {\r\n return this.emailAlreadyExists && !this.isNewUser;\r\n }\r\n public populateUserCounterparties(counterparties: UserCounterparty[]) {\r\n //this.newUserGridOptions.api.setRowData(counterparties);\r\n this.gridData = counterparties;\r\n }\r\n public clearForm() {\r\n this.firstName = \"\";\r\n this.lastName = \"\";\r\n this.email = \"\";\r\n this.originalEmail = \"\";\r\n this.salutation = \"\";\r\n this.phoneNumber = \"\";\r\n this.isAccountVerified = false;\r\n this.isLoginAllowed = false;\r\n this.showRegistration = this.loggedInUserIsPortalAdmin;\r\n\r\n this.setHasFirstAndLastName();\r\n this.hasEmail = true;\r\n this.emailPassesFormat = true;\r\n this.emailAlreadyExists = false;\r\n this.checkingEmailAlreadyExists = false;\r\n this.canSaveCounterparty = true;\r\n this.allValidationPasses = !(this.hasFirstName == false || this.hasLastName == false);\r\n this.populateUserCounterparties(null);\r\n }\r\n public clearCounterpartyAccordionForm() {\r\n this.selectedCounterpartyId = 0;\r\n this.customerPointSelectedOptions = [];\r\n this.customerPointOptions = [];\r\n this.customerPointSelectedNames = [];\r\n this.counterpartyUsersRolesComponent.clearForm();\r\n this.counterpartyUsersRolesComponent.disableForm();\r\n }\r\n\r\n public selectSalutation(salutation: string) {\r\n this.salutation = salutation;\r\n };\r\n\r\n public reSend() {\r\n this.counterpartyUsersService.openWelcomeUserDialog(this.email);\r\n }\r\n public cancel() {\r\n this.clearCounterpartyAccordionForm();\r\n this.resetGlobalRoles();\r\n this.activeModal.close('cancelled');\r\n }\r\n public saveCounterparty() {\r\n if (!this.doesCounterpartyExistInGrid() && this.selectedCounterpartyId != -1) {\r\n this.canSaveCounterparty = true;\r\n var counterparty: UserCounterparty = {\r\n counterpartyId: this.selectedCounterpartyId,\r\n counterpartyName: this.selectedCounterpartyName,\r\n customerPoints: this.customerPointSelectedOptions,\r\n customerPointNames: this.customerPointSelectedNames,\r\n customerPointNamesDisplay: this.customerPointSelectedNames,\r\n counterpartyRoles: this.counterpartyUsersRolesComponent.getSelectedRoles()\r\n };\r\n if (this.areAllCustomerPointsSelected(counterparty)) {\r\n counterparty.customerPointNamesDisplay = [\"All\"];\r\n }\r\n //this.newUserGridOptions.api.updateRowData({ add: [counterparty] });\r\n this.gridApi.applyTransaction({ add: [counterparty] });\r\n\r\n this.userSelectedCounterparties.push(counterparty);\r\n this.clearCounterpartyAccordionForm();\r\n }\r\n }\r\n\r\n public expandCounterpartyAccordion(event) {\r\n //Remove 'ALL COUNTERPARTIES' from the list, it only gets populated based on specific flags in HTML\r\n this.loadedCounterpartiesDropdown = this.loadedCounterparties;\r\n if (this.loadedCounterpartiesDropdown.some(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID)) {\r\n this.loadedCounterpartiesDropdown.splice(this.loadedCounterpartiesDropdown.findIndex(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID), 1);\r\n }\r\n this.selectedCounterpartyId = -1;\r\n this.hideAccordionElement(document.querySelector('#counterparty-accordion') as HTMLElement);\r\n this.counterpartyUsersRolesComponent.checkAllBillingRoles();\r\n this.counterpartyUsersRolesComponent.removeCounterpartyAdminForAllCounterparties(this.selectedCounterpartyId);\r\n }\r\n // We need to clear out the typeahead suggestions but the typeahead stops behaving well if you empty the search list. So let's re-init the whole thing\r\n // Unfortunately the typeahead offers no great way to reset it so I'm using an ngIf binding to destroy and create a new one. \r\n // Change detection only happens during browser events so we have to manually trigger it. The modal opening will take care of the re-create\r\n public resetTypeahead() {\r\n this.userSearchList = [];\r\n this.typeaheadActive = false;\r\n this.changeDetectorRef.detectChanges();\r\n this.typeaheadActive = true;\r\n }\r\n keyPressHandler(typeaheadElem: any) {\r\n //if (this.isNewUser) {\r\n // store what they're typing in case they want to make a new user\r\n this.email = typeaheadElem.inputElement.nativeElement.value;\r\n let emailInProgress = this.email;\r\n this.validateEmail();\r\n // wait 2 chars before searching\r\n if (this.email.length > 2) {\r\n // only portal admins get the typeahead\r\n if (this.hasPortalAdminRole) {\r\n this.counterpartyUsersService\r\n .searchEmails(typeaheadElem.inputElement.nativeElement.value, this.counterpartyId)\r\n .subscribe((searchResults: any) => {\r\n // the typeahead will stop matching properly if you feed it an empty array. Just keep the last suggestion list, the typeahead will filter things correctly\r\n if (searchResults.length != 0) {\r\n this.userSearchList = searchResults;\r\n }\r\n });\r\n }\r\n // wait 1 second and see if they stop typing before checking if the email exists already\r\n setTimeout(() => {\r\n if (this.email == emailInProgress) {\r\n var self = this;\r\n this.counterpartyUsersService\r\n .checkEmailExists(this.email, this.counterpartyId)\r\n .subscribe((result: any) => {\r\n let response: string = result.response;\r\n let userInfo = result.userInfo;\r\n\r\n switch (response) {\r\n case 'NEW_USER':\r\n if (!self.isEditingUserFromCounterpartyUsersTab() &&\r\n !self.isEditingUserFromUsersTab()) { // this is called after editing an existing user\r\n self.isNewUser = true;\r\n self.isAddUser = true;\r\n }\r\n self.validateEmail();\r\n self.aggregateValidation();\r\n break;\r\n case 'VALID_EXISTING_USER':\r\n self.hasValidEmail = true;\r\n self.isAddUser = false;\r\n self.isNewUser = false;\r\n self.emailTypeahead.selectSuggestion(userInfo);\r\n if (self.isAddingExistingUserFromCounterpartyUsersTab()) {\r\n self.selectUser(userInfo);\r\n } else {\r\n self.emailAlreadyExists = true;\r\n self.setButtonsEnabled(false, self);\r\n }\r\n break;\r\n case 'ALREADY_ON_COUNTERPARTY':\r\n if (self.isAddingNewUserFromCounterpartyUsersTab()) {\r\n self.hasValidEmail = false;\r\n self.setButtonsEnabled(false, self);\r\n self.userAlreadyOnCounterparty = true;\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n self.aggregateValidation();\r\n });\r\n }\r\n },\r\n 1000);\r\n }\r\n\r\n }\r\n selectUser(event) {\r\n if (event) {\r\n this.email = event.name;\r\n this.existingUserGUID = event.guid;\r\n this.hasFirstName = true;\r\n this.hasLastName = true;\r\n this.hasEmail = true;\r\n this.emailPassesFormat = true;\r\n this.hasValidEmail = true;\r\n this.allValidationPasses = true;\r\n // now grab the whole userprofile with the GUID associated to the email\r\n var self = this;\r\n this.counterpartyUsersService\r\n .getUser(event.guid)\r\n .subscribe((userProfile: any) => {\r\n if (self.isAddingNewUserFromUsersTab()) {\r\n self.emailAlreadyExists = true;\r\n self.setButtonsEnabled(false, self);\r\n } else if (self.isAddingExistingUserFromCounterpartyUsersTab()) {\r\n self.emailAlreadyExists = true;\r\n self.setButtonsEnabled(true, self);\r\n } else { // this is called from CounterpartyUsers page when clicking on Add User and it finds an existing email\r\n self.originalEmail = userProfile.email;\r\n self.firstName = userProfile.firstName;\r\n self.lastName = userProfile.lastName;\r\n self.phoneNumber = userProfile.phone;\r\n self.salutation = userProfile.salutation;\r\n self.isAccountVerified = userProfile.isAccountVerified;\r\n self.isLoginAllowed = userProfile.isLoginAllowed;\r\n self.counterpartyUsersRolesComponent.checkAllBillingRoles();\r\n this.counterpartyUsersRolesComponent.removeCounterpartyAdminForAllCounterparties(this.selectedCounterpartyId);\r\n let existingCounterparties: UserCounterparty[] =\r\n self.populateCounterparties(userProfile.counterparties);\r\n self.userSelectedCounterparties = existingCounterparties;\r\n self.populateUserCounterparties(existingCounterparties);\r\n if (self.isAddingNewUserFromCounterpartyUsersTab()) { // will need to flip from AddNewUser to EditExistingUser\r\n self.isNewUser = false;\r\n self.isAddUser = false;\r\n }\r\n self.setButtonsEnabled(true, self);\r\n }\r\n });\r\n }\r\n }\r\n public isAddingNewUserFromCounterpartyUsersTab(): boolean {\r\n return this.isAddUser && this.isNewUser && !this.isFromUsersTab;\r\n }\r\n public isAddingExistingUserFromCounterpartyUsersTab(): boolean {\r\n return this.isAddUser && !this.isNewUser && !this.isFromUsersTab;\r\n }\r\n public isEditingUserFromCounterpartyUsersTab(): boolean {\r\n return !this.isAddUser && !this.isNewUser && !this.isFromUsersTab;\r\n }\r\n public isAddingNewUserFromUsersTab(): boolean {\r\n return this.isAddUser && this.isNewUser && this.isFromUsersTab;\r\n }\r\n public isEditingUserFromUsersTab(): boolean {\r\n return !this.isAddUser && !this.isNewUser && this.isFromUsersTab;\r\n }\r\n\r\n setButtonsEnabled(areEnabled: boolean, component: any) {\r\n component.canAddCounterparty = areEnabled;\r\n component.canSaveCounterparty = areEnabled;\r\n component.canSave = areEnabled;\r\n }\r\n\r\n /**\r\n * If they've selected an existing user and go to edit the email, clear the form\r\n */\r\n setEmailTypeahead(email: string) {\r\n this.emailTypeahead.placeholder = '';\r\n this.emailTypeahead.populateInput(email);\r\n }\r\n private hideAccordion() {\r\n this.hideAccordionElement(document.querySelector('#counterparty-accordion') as HTMLElement);\r\n }\r\n private hideAccordionElement(element) {\r\n this.isAccordionHidden = !this.isAccordionHidden;\r\n if (element.style.maxHeight) {\r\n element.style.maxHeight = null;\r\n } else {\r\n element.style.maxHeight = \"572px\";\r\n }\r\n }\r\n private cloneSchedulerCounterparties(): UserCounterparty[] {\r\n var counterparties: UserCounterparty[] = [];\r\n this.userSelectedCounterparties.forEach(selectedCP => {\r\n if (selectedCP.counterpartyRoles.find(cp => cp.roleName == \"Scheduler\")) {\r\n counterparties.push(JSON.parse(JSON.stringify(selectedCP)));\r\n }\r\n });\r\n\r\n return counterparties;\r\n }\r\n\r\n private areAllCustomerPointsSelected(counterparty: UserCounterparty) {\r\n var result: boolean = false;\r\n let allCounterparties: Counterparty[] = JSON.parse(localStorage.getItem('allCounterparties')) as Counterparty[];\r\n let storedCounterparty = allCounterparties.filter(c => c.counterpartyId == counterparty.counterpartyId);\r\n if (storedCounterparty !== null && storedCounterparty.length == 1) {\r\n let storedCustomerPointIds = storedCounterparty[0].customerPoints.map(cp => {\r\n return cp.customerPointId;\r\n });\r\n let intersection = storedCustomerPointIds.filter(item => counterparty.customerPoints.indexOf(item) !== -1);\r\n if (intersection.length !== 0 && storedCustomerPointIds.length === counterparty.customerPoints.length\r\n && intersection.length === storedCustomerPointIds.length && intersection.length === counterparty.customerPoints.length) {\r\n result = true;\r\n }\r\n if (counterparty.customerPoints.length == 0) {\r\n result = true;\r\n }\r\n }\r\n return result;\r\n }\r\n public save() {\r\n this.showSpinner = true;\r\n let newEmail = this.originalEmail !== this.email ? this.email : \"\";\r\n if ((this.isAddingNewUserFromUsersTab() || this.isAddingNewUserFromCounterpartyUsersTab()) && (this.originalEmail === \"\" || this.originalEmail === undefined)) {\r\n this.originalEmail = newEmail;\r\n }\r\n //global Roles\r\n let globalRoles: string[] = [];\r\n if (this.isInternal) { globalRoles.push(Configuration.USER_ROLES.INTERNAL) }\r\n if (this.isUserPortalAdmin && this.isInternal) { globalRoles.push(Configuration.USER_ROLES.PORTAL_ADMIN) }\r\n\r\n //Impersonate Roles\r\n let impersonateRoles: string[] = [];\r\n if (this.isImpersonateBilling && this.isInternal) { impersonateRoles.push(Configuration.USER_ROLES.IMPERSONATE_BILLING) }\r\n if (this.isImpersonateScheduler && this.isInternal) { impersonateRoles.push(Configuration.USER_ROLES.IMPERSONATE_SCHEDULER) }\r\n if (this.isImpersonateAdmin && this.isInternal) { impersonateRoles.push(Configuration.USER_ROLES.IMPERSONATE_ADMIN) }\r\n if (this.impersonateSelectedOptions && this.isInternal) {\r\n this.impersonateSelectedOptions.forEach(x => {\r\n impersonateRoles.push('Impersonate: ' + this.impersonateReportOptions[x].name)\r\n })\r\n }\r\n\r\n let userModel: CounterpartyUserInfo = {\r\n firstName: this.firstName,\r\n lastName: this.lastName,\r\n email: this.originalEmail,\r\n newEmail: newEmail,\r\n salutation: this.salutation,\r\n phone: this.phoneNumber,\r\n isLoginAllowed: this.isLoginAllowed,\r\n isAccountVerified: this.isAccountVerified,\r\n counterparties: this.userSelectedCounterparties,\r\n rowIndex: this.rowIndex,\r\n globalRoles: globalRoles,\r\n impersonateRoles: impersonateRoles\r\n };\r\n\r\n this.schedulerCounterparties = this.cloneSchedulerCounterparties();\r\n \r\n let customerPointNames: string[] = [];\r\n for (let index in userModel.counterparties) {\r\n if (userModel.counterparties[index].customerPointNames !== undefined) {\r\n customerPointNames = customerPointNames.concat(userModel.counterparties[index].customerPointNames);\r\n }\r\n }\r\n \r\n if (this.isAddingNewUserFromCounterpartyUsersTab() || this.isAddingNewUserFromUsersTab()) {\r\n this.counterpartyUsersService.createNewUser(userModel)\r\n .subscribe((result: any) => {\r\n this.userUpdated.emit(userModel);\r\n\r\n this.schedulerCounterparties.forEach(selectedCP => {\r\n this.callToSetSchedulerCounterparty(userModel.email, selectedCP);\r\n });\r\n\r\n this.callAddCustomerPointsByNameToUserAccount(result.key, customerPointNames);\r\n \r\n let button = document.getElementById('btnAddEditUser' + this.rowIndex);\r\n if (button !== null) {\r\n for (let counterparty of userModel.counterparties) {\r\n button.addEventListener('click',\r\n () => {\r\n $(window).trigger('showAddEditUserDialog',\r\n [\r\n counterparty.counterpartyId, counterparty.counterpartyId.toString(),\r\n userModel, this.rowIndex\r\n ]);\r\n });\r\n }\r\n };\r\n\r\n this.activeModal.close('saved');\r\n });\r\n } else {\r\n var that = this;\r\n that.counterpartyUsersService.updateUserInfo(userModel)\r\n .subscribe(async (result: any) => {\r\n that.userUpdated.emit(userModel);\r\n if (that.schedulerCounterparties !== undefined) {\r\n await that.callDeleteUserCounterparty(userModel.email);\r\n that.schedulerCounterparties.forEach(selectedCP => {\r\n that.callToSetSchedulerCounterparty(userModel.email, selectedCP);\r\n });\r\n }\r\n that.callAddCustomerPointsByNameToUserAccount(result.key, customerPointNames);\r\n let button = document.getElementById('btnAddEditUser' + that.rowIndex);\r\n if (button !== null) {\r\n\r\n for (let counterparty of userModel.counterparties) {\r\n button.addEventListener('click',\r\n () => {\r\n $(window).trigger('showAddEditUserDialog',\r\n [\r\n counterparty.counterpartyId, counterparty.counterpartyId.toString(),\r\n userModel, that.rowIndex\r\n ]);\r\n });\r\n }\r\n }\r\n this.activeModal.close('saved');\r\n });\r\n }\r\n this.resetGlobalRoles();\r\n this.resetForm();\r\n this.resetTypeahead(); \r\n this.userSelectedCounterparties = [];\r\n this.clearCounterpartyAccordionForm();\r\n this.hideAccordion();\r\n }\r\n callAddCustomerPointsByNameToUserAccount(userAccountId: number, customerPointNames: string[]) {\r\n this.counterpartyUsersService.addCustomerPointsByNametoUser(userAccountId, customerPointNames)\r\n .subscribe((result: any) => {\r\n });\r\n }\r\n\r\n callToSetSchedulerCounterparty(userId: string, counterparty: UserCounterparty) {\r\n this.counterpartyUsersService.SetSchedulerCounterparty(userId, counterparty)\r\n .subscribe((result: any) => {\r\n });\r\n }\r\n async callDeleteUserCounterparty(userId: string) {\r\n console.log('calling deleteUserCounterparty...');\r\n var response = await this.counterpartyUsersService.DeleteUserCounterparty(userId).toPromise();\r\n console.log('deleteUserCounterparty response ' + response);\r\n }\r\n\r\n validateEmail() {\r\n this.emailAlreadyExists = false;\r\n this.checkingEmailAlreadyExists = false;\r\n this.emailPassesFormat = true;\r\n this.userAlreadyOnCounterparty = false;\r\n this.isEmailNotEmpty();\r\n if (this.loggedInUserIsPortalAdmin && this.originalEmail !== this.email && this.hasEmail) {\r\n this.checkingEmailAlreadyExists = true;\r\n var self = this;\r\n this.counterpartyUsersService\r\n .checkEmailExists(this.email, -1)\r\n .subscribe((result: any) => {\r\n self.emailAlreadyExists = result.response === 'userWithSameEmailAlreadyExists';\r\n self.emailAlreadyExistsEdit = self.doesEmailAlreadyExistEdit();\r\n self.checkingEmailAlreadyExists = false;\r\n self.aggregateValidation();\r\n });\r\n this.doesEmailPassFormat();\r\n this.aggregateValidation();\r\n }\r\n }\r\n private doesEmailPassFormat() {\r\n let emailRegexPattern: RegExp =\r\n /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\r\n this.emailPassesFormat = emailRegexPattern.test(this.email);\r\n this.hasValidEmail = this.emailPassesFormat;\r\n }\r\n private isEmailNotEmpty() {\r\n this.hasEmail = this.email !== \"\";\r\n if (this.hasEmail) {\r\n this.doesEmailPassFormat();\r\n }\r\n }\r\n private setHasFirstAndLastName() {\r\n this.hasFirstName = this.firstName !== \"\";\r\n this.hasLastName = this.lastName !== \"\";\r\n }\r\n public validateFirstName(inputElem: any) {\r\n let firstNameInput = inputElem == null ? this.firstName : inputElem.value;\r\n this.hasFirstName = firstNameInput != '';\r\n this.validateEmail();\r\n this.aggregateValidation();\r\n }\r\n\r\n public validateLastName(inputElem: any) {\r\n let lastNameInput = inputElem.value;\r\n this.hasLastName = lastNameInput != '';\r\n this.validateEmail();\r\n this.validateFirstName(null);\r\n this.aggregateValidation();\r\n }\r\n\r\n private setUserGridDataSource(params) {\r\n //this.newUserGridOptions.api.showLoadingOverlay();\r\n //this.getLoggedInUserCounterparties(true);\r\n\r\n //this.newUserGridOptions.api.hideOverlay();\r\n }\r\n public getLoggedInUserCounterparties(isLoggedInUser: boolean) {\r\n if (isLoggedInUser) {\r\n this.loggedInUser = this.loggedInUserService.getLoggedInUser();\r\n } else { // sets loggedInUser to existing user we're trying to add to populate counterpartyNames\r\n this.loggedInUser = this.existingUserProfile;\r\n }\r\n this.loggedInUserService.getCounterpartiesByLoggedInUserId()\r\n .subscribe((data: any) => {\r\n data = data.filter(c => c.active === true);\r\n this.populateUserCounterparties(data);\r\n });\r\n }\r\n public aggregateValidation() {\r\n this.canResendWelcomeEmail = this.loggedInUserIsPortalAdmin && this.isAccountVerified;\r\n this.allValidationPasses = this.hasFirstName &&\r\n this.hasLastName &&\r\n this.hasEmail &&\r\n this.emailPassesFormat &&\r\n !this.checkingEmailAlreadyExists &&\r\n ((this.selectedCounterpartyId > 0) || (this.counterpartyId === 0 && (this.isAddingNewUserFromUsersTab() || this.isEditingUserFromUsersTab()))) &&\r\n !this.emailAlreadyExists;\r\n this.setButtonsEnabled(this.allValidationPasses, this);\r\n return this.allValidationPasses;\r\n }\r\n public resetForm() {\r\n this.isNewUser = true;\r\n this.existingUserGUID = '';\r\n this.existingUserProfile = null;\r\n this.firstName = '';\r\n this.lastName = '';\r\n this.email = '';\r\n this.originalEmail = '';\r\n this.salutation = '';\r\n this.phoneNumber = '';\r\n\r\n // validation - null=unevaluated. Master-flag starts at false.\r\n this.hasFirstName = null;\r\n this.hasLastName = null;\r\n this.hasEmail = null;\r\n this.emailPassesFormat = null;\r\n this.hasValidEmail = null;\r\n this.allValidationPasses = false;\r\n\r\n this.changeDetectorRef.detectChanges(); // kick the change detector so it sends the new counterpartyId to the roles component\r\n this.counterpartyUsersRolesComponent.resetForm();\r\n //this.newUserGridOptions.api.setRowData(null);\r\n this.gridData = [];\r\n }\r\n public resetEmailWarningMessages() {\r\n this.hasEmail = false;\r\n this.emailPassesFormat = false;\r\n this.emailAlreadyExists = false;\r\n this.emailAlreadyExistsEdit = false;\r\n this.userAlreadyOnCounterparty = false;\r\n }\r\n\r\n private loadCounterparties() {\r\n this.loggedInUser = this.loggedInUserService.getLoggedInUser();\r\n return this.loggedInUserService.getCounterpartiesByLoggedInUserId()\r\n .pipe(\r\n map(cps => {\r\n let activeCps: CounterpartyActive[] = cps;\r\n\r\n\r\n let options: CounterpartyActive[] = activeCps.map(x => {\r\n let cp = new CounterpartyActive();\r\n cp.counterpartyId = x.counterpartyId;\r\n cp.shortName = x.shortName;\r\n return cp;\r\n });\r\n options = options.sort((c1, c2) => {\r\n return c1.shortName.toLowerCase().localeCompare(c2.shortName.toLowerCase());\r\n });\r\n return options;\r\n\r\n })\r\n );\r\n }\r\n\r\n private doesCounterpartyExistInGrid() {\r\n var result: boolean = false;\r\n this.gridApi.forEachNode((rowNode) => {\r\n if (rowNode.data.counterpartyName === this.selectedCounterpartyName) {\r\n this.canSaveCounterparty = false;\r\n result = true;\r\n }\r\n });\r\n return result;\r\n }\r\n\r\n private loadCustomerPoints(event) {\r\n this.customerPointOptions = [];\r\n this.customerPointSelectedOptions = [];\r\n this.customerPointSelectedNames = [];\r\n\r\n this.counterpartyUsersRolesComponent.checkAllBillingRoles();\r\n this.counterpartyUsersRolesComponent.removeCounterpartyAdminForAllCounterparties(this.selectedCounterpartyId);\r\n this.canSaveCounterparty = true;\r\n if (event.target.selectedOptions[0] != null) {\r\n this.selectedCounterpartyName = event.target.selectedOptions[0].text;\r\n }\r\n this.populateCustomerPointsOptions(event.target.value);\r\n }\r\n private populateCustomerPointsOptions(cpId) {\r\n this.counterpartyUsersService.getCustomerPointsByCounterpartyId(cpId)\r\n .subscribe((data: any) => {\r\n if (data !== false) {\r\n data.result.forEach((d) => {\r\n let option: IMultiSelectOption = {\r\n id: d.customerPointId,\r\n name: d.customerPointName\r\n }\r\n this.customerPointOptions.push(option);\r\n this.customerPointSelectSettings.dynamicTitleMaxItems = this.customerPointOptions.length - 1;\r\n this.customerPointSelectedOptions.push(d.customerPointId);\r\n this.customerPointSelectedNames.push(d.customerPointName);\r\n });\r\n }\r\n });\r\n }\r\n private updateUserRolesComponent() {\r\n this.counterpartyUsersRolesComponent.counterpartyId = this.selectedCounterpartyId;\r\n this.counterpartyUsersRolesComponent.resetForm();\r\n this.counterpartyUsersRolesComponent.clearForm();\r\n this.counterpartyUsersRolesComponent.setUserRoles(this.currentUserProfile, this.counterpartyId);\r\n }\r\n private onSelectedCustomerPoint(items: number[]) {\r\n this.customerPointSelectedIds = items;\r\n var idx = 0;\r\n this.customerPointSelectedNames = [];\r\n let allCounterparties: Counterparty[] = JSON.parse(localStorage.getItem('allCounterparties')) as Counterparty[];\r\n this.customerPointSelectedIds.forEach((selectedId) => {\r\n allCounterparties.forEach((counterparty) => {\r\n if (counterparty.customerPoints !== null) {\r\n counterparty.customerPoints.forEach((customerPoint) => {\r\n if (selectedId == customerPoint.customerPointId) {\r\n this.customerPointSelectedNames[idx] = customerPoint.customerPointName;\r\n idx++;\r\n }\r\n });\r\n }\r\n\r\n });\r\n });\r\n }\r\n\r\n public dataTypeDefinitions: any = {\r\n object: {\r\n baseDataType: 'object',\r\n extendsDataType: 'object',\r\n valueFormatter: (params: any) => '' // Acts as a silent dummy fallback\r\n }\r\n };\r\n\r\n private createColumnDefs(): any {\r\n return [\r\n {\r\n headerName: \"Counterparty\",\r\n field: 'counterpartyName',\r\n width: 250,\r\n suppressHeaderMenuButton: true,\r\n tooltipValueGetter: (params) => { return params.value; }\r\n },\r\n {\r\n headerName: \"Customer Points\",\r\n field: \"customerPointNamesDisplay\",\r\n width: 350,\r\n suppressHeaderMenuButton: true,\r\n tooltipValueGetter: (params) => { return params.value; }\r\n },\r\n {\r\n headerName: \"Roles\",\r\n field: 'counterpartyRoles',\r\n width: 250,\r\n suppressHeaderMenuButton: true,\r\n cellRenderer: (params) => {\r\n let commaSeparatedRoles: string = \"\";\r\n let roleCount: number = 0;\r\n if (params.data != null && params.data.counterpartyRoles != null) {\r\n params.data.counterpartyRoles.forEach(x => {\r\n if (roleCount === 0) {\r\n commaSeparatedRoles = x.roleName;\r\n } else {\r\n commaSeparatedRoles += \", \" + x.roleName;\r\n }\r\n roleCount++;\r\n });\r\n }\r\n return commaSeparatedRoles;\r\n },\r\n tooltipValueGetter: (params) => {\r\n let commaSeparatedRoles: string = \"\";\r\n let roleCount: number = 0;\r\n if (params.data != null && params.data.counterpartyRoles != null) {\r\n params.data.counterpartyRoles.forEach(x => {\r\n if (roleCount === 0) {\r\n commaSeparatedRoles = x.roleName;\r\n } else {\r\n commaSeparatedRoles += \", \" + x.roleName;\r\n }\r\n roleCount++;\r\n });\r\n }\r\n return commaSeparatedRoles;\r\n }\r\n },\r\n {\r\n headerName: '',\r\n hide: this.loggedInUserService.impersonateTab || this.loggedInUserService.isImpersonate,\r\n width: 110,\r\n field: 'removeCounterparty',\r\n suppressColumnsToolPanel: true,\r\n suppressHeaderMenuButton: true,\r\n sortable: false,\r\n resizable: false,\r\n suppressMovable: true,\r\n cellRenderer: (params) => {\r\n if (params.data != null) {\r\n var eDiv = document.createElement('div');\r\n eDiv.innerHTML =\r\n '';\r\n var removeButton = eDiv.querySelector('.btn-remove');\r\n this.clickRemoveButtonEventListener = (p) => {\r\n var removeRow: IRowNode = this.gridApi.getRowNode(params.rowIndex);\r\n\r\n this.gridApi.applyTransaction({ remove: [removeRow.data] });\r\n var counterpartyToRemove: UserCounterparty = {\r\n counterpartyId: params.data.counterpartyId,\r\n counterpartyName: params.data.counterpartyName,\r\n customerPoints: params.data.customerPoints,\r\n customerPointNames: params.data.customerPointNames,\r\n customerPointNamesDisplay: params.data.customerPointNamesDisplay,\r\n counterpartyRoles: params.data.counterpartyRoles\r\n };\r\n const cpRemoveIdx: number = this.userSelectedCounterparties.map(function (e) { return e.counterpartyName })\r\n .indexOf(counterpartyToRemove.counterpartyName);\r\n if (cpRemoveIdx > -1) {\r\n this.userSelectedCounterparties.splice(cpRemoveIdx, 1);\r\n }\r\n if (this.selectedCounterpartyId == params.data.counterpartyId) {\r\n this.canSaveCounterparty = true;\r\n }\r\n };\r\n removeButton.addEventListener('click', this.clickRemoveButtonEventListener);\r\n return eDiv;\r\n } else {\r\n return '';\r\n }\r\n },\r\n menuTabs: []\r\n }\r\n ];\r\n }\r\n private setInternalRole() {\r\n if (/calpinesolutions.com|calpine.com|champion.energy/.test(this.email.toLowerCase()) && this.loggedInUserService.isPortalAdmin()) {\r\n this.isInternal = true;\r\n }\r\n else { this.isInternal = false; }\r\n }\r\n private resetGlobalRoles() {\r\n this.isInternal = false;\r\n this.isUserPortalAdmin = false;\r\n this.isImpersonateScheduler = false;\r\n this.isImpersonateBilling = false;\r\n this.isImpersonateAdmin = false;\r\n this.impersonateSelectedOptions = [];\r\n }\r\n private async setImpersonateOptions() {\r\n this.impersonateOptions = [];\r\n this.impersonateReportOptions = [];\r\n let response = await this.counterpartyUsersService.getGetImpersonationRoles().toPromise();\r\n let i = 0;\r\n response.forEach(x => {\r\n this.impersonateOptions.push(x.Name);\r\n if (x.IsReport == true) {\r\n this.impersonateReportOptions.push(\r\n {\r\n id: i,\r\n name: x.Name\r\n })\r\n i++;\r\n }\r\n });\r\n }\r\n private setRoles(user: any) {\r\n user.roles.forEach(userRole => {\r\n if (userRole.includes('Impersonate')) {\r\n this.impersonateReportOptions.forEach(roleOptions => {\r\n if (userRole.includes(roleOptions.name)){\r\n var role = this.impersonateReportOptions.find(i => i.name == roleOptions.name);\r\n this.impersonateSelectedOptions.push(role.id);\r\n }\r\n })\r\n }\r\n })\r\n this.isInternal = user.roles.includes(Configuration.USER_ROLES.INTERNAL);\r\n this.isUserPortalAdmin = user.roles.includes(Configuration.USER_ROLES.PORTAL_ADMIN);\r\n this.isImpersonateScheduler = user.roles.includes(Configuration.USER_ROLES.IMPERSONATE_SCHEDULER);\r\n this.isImpersonateBilling = user.roles.includes(Configuration.USER_ROLES.IMPERSONATE_BILLING);\r\n this.isImpersonateAdmin = user.roles.includes(Configuration.USER_ROLES.IMPERSONATE_ADMIN);\r\n }\r\n}\r\nfunction getCustomerPointNames(counterparty: any, storedCounterparty: Counterparty): any {\r\n return counterparty.customerPoints.map((cp) => {\r\n let customerPoint = storedCounterparty.customerPoints.filter(x => x.customerPointId == cp);\r\n if (customerPoint !== undefined && customerPoint[0] !== undefined && customerPoint[0].customerPointName !== undefined) {\r\n return customerPoint[0].customerPointName;\r\n }\r\n else {\r\n return \"\";\r\n }\r\n });\r\n}","import { Component, OnInit, ViewChild } from '@angular/core';\r\nimport { ICellRendererAngularComp } from 'ag-grid-angular';\r\nimport { ICellRendererParams, IAfterGuiAttachedParams } from 'ag-grid-community';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { PostCounterpartyIsPortalActiveParams, AddEditUserModalParams, Counterparty } from './counterparty-users.model';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { Configuration } from '../../app.configuration';\r\n\r\n@Component({\r\n selector: 'counterparty-users-grouped-row',\r\n template: require('./counterparty-users-grouped-row.component.html'),\r\n styles: [require('./counterparty-users-grouped-row.component.css').toString()]\r\n})\r\n\r\nexport class CounterpartyUsersGroupedRowComponent implements OnInit, ICellRendererAngularComp {\r\n\r\n params: ICellRendererParams;\r\n counterpartyName: string;\r\n userCount: number = 0;\r\n isPortalActive: boolean = false;\r\n isSpinnerVisible: boolean = false;\r\n isInternalAdmin: boolean = false;\r\n isImpersonate: boolean = false;\r\n impersonateTab: boolean = false;\r\n\r\n constructor(private counterpartyUserService: CounterpartyUsersService,\r\n private loggedInUserService: LoggedInUserService) {\r\n }\r\n\r\n ngOnInit() {\r\n this.isImpersonate = this.loggedInUserService.isImpersonate;\r\n this.impersonateTab = this.loggedInUserService.impersonateTab;\r\n this.isInternalAdmin = this.loggedInUserService.isPortalAdmin();\r\n }\r\n\r\n agInit(params: ICellRendererParams): void {\r\n this.params = params;\r\n this.counterpartyName = params.node.key;\r\n if (this.params.node.group) {\r\n this.isPortalActive = params.node.allLeafChildren[0].data.isPortalActive;\r\n if (!!params.node.allLeafChildren[0].data.email) {\r\n this.userCount = this.params.node.allChildrenCount;\r\n }\r\n }\r\n }\r\n\r\n refresh(params: ICellRendererParams): boolean {\r\n this.params = params;\r\n return false;\r\n }\r\n\r\n afterGuiAttached?(params?: IAfterGuiAttachedParams): void {\r\n\r\n }\r\n\r\n showAddUserDialog() {\r\n let params: AddEditUserModalParams =\r\n {\r\n isAdd: true,\r\n isNewUser: true,\r\n hasPortalAdminRole: this.loggedInUserService.isPortalAdmin(),\r\n counterpartyId: this.params.node.allLeafChildren[0].data.counterpartyId,\r\n counterpartyName: this.counterpartyName,\r\n rowIdx: this.params.rowIndex\r\n }\r\n this.counterpartyUserService.openAddEditUserDialog(params);\r\n }\r\n checkboxChecked() {\r\n this.isPortalActive = !this.isPortalActive;\r\n let postParams: PostCounterpartyIsPortalActiveParams = {\r\n counterpartyId: this.params.node.allLeafChildren[0].data.counterpartyId,\r\n isPortalActive: this.isPortalActive\r\n }\r\n this.isSpinnerVisible = true;\r\n this.counterpartyUserService.postCounterpartyIsPortalActive(postParams)\r\n .subscribe((data: any) => {\r\n this.isSpinnerVisible = false;\r\n });\r\n }\r\n\r\n}\r\n","import { Component, ViewChild, Input, ChangeDetectionStrategy, Output, EventEmitter, OnInit } from '@angular/core';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { CounterpartyUserInfo, RemoveUserModalParams } from './counterparty-users.model';\r\nimport { UserCounterparty } from './counterparty-users.model';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service'\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'\r\n\r\n@Component({\r\n selector: 'counterparty-users-remove-dialog',\r\n template: require('./counterparty-users-remove-dialog.component.html'),\r\n changeDetection: ChangeDetectionStrategy.Default\r\n})\r\nexport class CounterpartyUsersRemoveDialogComponent implements OnInit {\r\n public counterpartyId: number;\r\n public userEmail: string;\r\n public showSpinner: boolean;\r\n\r\n @Input() public user: RemoveUserModalParams;\r\n @Output() userRemoved: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n private counterpartyUsersService: CounterpartyUsersService,\r\n private loggedInUserService: LoggedInUserService,\r\n private activeModal: NgbActiveModal) { }\r\n\r\n ngOnInit() {\r\n this.setupDialogBox(this.user.counterpartyId, this.user.email);\r\n }\r\n\r\n setupDialogBox(counterpartyId: number, userEmail: string) {\r\n this.showSpinner = false;\r\n this.counterpartyId = counterpartyId;\r\n this.userEmail = userEmail;\r\n }\r\n \r\n save() {\r\n this.showSpinner = true;\r\n let counterpartyToDelete:[UserCounterparty];\r\n let counterparty: UserCounterparty = new UserCounterparty;\r\n counterparty.counterpartyId = this.counterpartyId;\r\n counterpartyToDelete = [counterparty];\r\n let userModel: CounterpartyUserInfo = {\r\n email: this.userEmail,\r\n counterparties: counterpartyToDelete,\r\n rowIndex: 0\r\n };\r\n this.counterpartyUsersService.removeUserFromCounterparty(userModel.counterparties[0].counterpartyId, userModel.email)\r\n .subscribe(() => {\r\n this.userRemoved.emit(userModel);\r\n this.activeModal.close('save');\r\n });\r\n }\r\n\r\n cancel() {\r\n this.activeModal.close('cancelled');\r\n }\r\n}","import { Component, Input } from '@angular/core';\r\nimport { IUserData, LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { CounterpartyUserRole } from './counterparty-users.model';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { UserRole } from '../../shared/services/user-role.service';\r\nimport { Configuration } from '../../app.configuration';\r\n\r\n@Component({\r\n selector: 'counterparty-users-roles',\r\n template: require('./counterparty-users-roles.component.html')\r\n})\r\nexport class CounterpartyUsersRolesComponent {\r\n public userIsPortalAdmin: boolean;\r\n public roleModules: any[];\r\n public userProfile: IUserData;\r\n @Input() isEditView: boolean;\r\n @Input() counterpartyId: number;\r\n\r\n constructor(private counterpartyUsersService: CounterpartyUsersService,\r\n private loggedInUserService: LoggedInUserService,\r\n private userRole: UserRole) {\r\n if (this.counterpartyId == null) {\r\n this.disableForm();\r\n } else {\r\n this.enableForm();\r\n }\r\n this.roleModules = [];\r\n\r\n this.counterpartyUsersService.getAddUserRoles()\r\n .subscribe((result: any) => {\r\n result.forEach((module) => {\r\n module.roles.forEach((role) => {\r\n role.isChecked = false;\r\n role.isVisible = true;\r\n });\r\n module.visibleRoles = module.roles;\r\n });\r\n\r\n this.roleModules = result;\r\n });\r\n\r\n this.userProfile = this.loggedInUserService.getLoggedInUser();\r\n var globalRoles = this.userProfile.roles;\r\n this.userIsPortalAdmin = this.userRole.matchRolesAndRolesConditions(globalRoles, Configuration.USER_ROLES.PORTAL_ADMIN);\r\n }\r\n\r\n resetForm() {\r\n // grab the user's CP assoc. They can only assign roles that they themselves have\r\n var adminCounterpartyAssoc = this.userProfile.counterparties.find(cp => cp.counterpartyId == this.counterpartyId);\r\n this.roleModules.forEach((module) => {\r\n module.roles.forEach((role) => {\r\n role.isChecked = (!this.isEditView && module.module === \"Billing\");\r\n role.isVisible = (this.userIsPortalAdmin || adminCounterpartyAssoc.counterpartyRoles.find(cpr => role.roleId == cpr.roleId) != undefined);\r\n });\r\n // update the module's visibility too\r\n module.visibleRoles = module.roles.filter(role => { return role.isVisible });\r\n });\r\n }\r\n\r\n clearForm() {\r\n this.roleModules.forEach((module) => {\r\n module.roles.forEach((role) => {\r\n role.isChecked = false;\r\n });\r\n });\r\n }\r\n\r\n getSelectedRoles() {\r\n let selectedRoles: CounterpartyUserRole[] = [];\r\n this.roleModules.forEach(rm => {\r\n selectedRoles = _.union(selectedRoles, rm.roles.filter(role => {\r\n return role.isChecked;\r\n }));\r\n });\r\n return selectedRoles;\r\n }\r\n checkAllBillingRoles() {\r\n this.roleModules.forEach(rm => {\r\n // Check all Billing roles for new users by default\r\n if (rm.module === \"Billing\") {\r\n rm.roles.forEach(role => {\r\n role.isChecked = true;\r\n });\r\n }\r\n });\r\n }\r\n\r\n removeCounterpartyAdminForAllCounterparties(counterpartyId: number) {\r\n if (counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID || counterpartyId == CAPLINE_COUNTERPARTY_ID) {\r\n this.roleModules.forEach(rm => {\r\n if (rm.module === \"Counterparty\") {\r\n rm.roles.forEach(role => {\r\n if (role.roleName == \"Counterparty Administrator\") {\r\n role.isVisible = false;\r\n }\r\n })\r\n }\r\n });\r\n }\r\n else {\r\n this.roleModules.forEach(rm => {\r\n if (rm.module === \"Counterparty\") {\r\n rm.roles.forEach(role => {\r\n if (role.roleName == \"Counterparty Administrator\") {\r\n role.isVisible = true;\r\n }\r\n })\r\n }\r\n });\r\n }\r\n this.enableForm();\r\n }\r\n\r\n setUserRoles(userProfile: IUserData, counterpartyId: number) {\r\n // counterparty roles\r\n var userCounterpartyAssoc = userProfile.counterparties.find(cp => cp.counterpartyId == counterpartyId);\r\n // new users for counterparties won't have a cp assoc yet\r\n if (userCounterpartyAssoc) {\r\n // loop through the user's roles on the counterparty and check the appropriate boxes\r\n userCounterpartyAssoc.counterpartyRoles.forEach(cpr => {\r\n this.roleModules.forEach(rm => {\r\n rm.roles.forEach(role => {\r\n if (role.roleId == cpr.roleId) {\r\n role.isChecked = true;\r\n }\r\n });\r\n });\r\n })\r\n }\r\n }\r\n disableForm() {\r\n if (this.roleModules != null) {\r\n this.roleModules.forEach((module) => {\r\n module.roles.forEach((role) => {\r\n role.isEnabled = false;\r\n });\r\n // update the module's visibility too\r\n module.visibleRoles = module.roles.filter(role => { return role.isVisible });\r\n });\r\n }\r\n }\r\n enableForm() {\r\n if (this.roleModules != null) {\r\n this.roleModules.forEach((module) => {\r\n module.roles.forEach((role) => {\r\n role.isEnabled = true;\r\n });\r\n\r\n // update the module's visibility too\r\n module.visibleRoles = module.roles.filter(role => { return role.isVisible });\r\n });\r\n }\r\n }\r\n}\r\n","import { Subscription } from 'rxjs';\r\nimport { ChangeDetectionStrategy, Component, EventEmitter, OnInit, ViewChild, OnDestroy, Output } from '@angular/core';\r\nimport { GridOptions, IGetRowsParams, GridApi, GridReadyEvent, ColDef, HeaderValueGetterParams, GridSizeChangedEvent } from 'ag-grid-community';\r\nimport * as _ from 'lodash';\r\n\r\nimport { CounterpartyUsersAddEditDialogComponent } from './counterparty-users-add-edit-dialog.component';\r\nimport { CounterpartyUsersRemoveDialogComponent } from './counterparty-users-remove-dialog.component';\r\nimport { SendWelcomeEmailDialogComponent } from './send-welcome-email-dialog.component';\r\nimport { BooleanFilterComponent } from '../../shared/grid/grid.boolean-filter.component';\r\nimport { CounterpartyActive, CounterpartyUserInfo, AddEditUserModalParams, RemoveUserModalParams, CounterpartyUserRole } from './counterparty-users.model';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { LoggedInUserService, IUserData } from '../../shared/services/logged-in-user.service';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { GridService } from '../../shared/grid/grid.service';\r\nimport { CounterpartyUsersGroupedRowComponent } from './counterparty-users-grouped-row.component';\r\nimport { CounterpartyUserEditDeleteButtonComponent } from './counterparty-user-edit-delete-button.component';\r\nimport { CalpineAgGridPagerComponent } from '../../shared/pager/pager.component';\r\nimport { SendWelcomeEmailHeaderComponent } from './send-welcome-email-header-button.component';\r\nimport { UserImpersonateViewButtonsComponent } from '../../shared/impersonate-button/user-impersonate-view-buttons.component'\r\nimport { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';\r\nimport 'ag-grid-enterprise';\r\n\r\ninterface ICounterpartyUserRowsParams extends IGetRowsParams {\r\n counterpartyId: number;\r\n}\r\n@Component({\r\n selector: 'counterparty-users',\r\n template: require('./counterparty-users.component.html'),\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n styles: [require('./counterparty-users.component.css').toString()]\r\n})\r\n\r\nexport class CounterpartyUsersComponent implements OnInit, OnDestroy {\r\n\r\n @ViewChild('counterpartyUsersPager') agGridPager: CalpineAgGridPagerComponent;\r\n @Output() userCreated = new EventEmitter();\r\n hasPortalAdminRole: boolean;\r\n hasCounterpartyAdminRole: boolean;\r\n\r\n gridOptions: GridOptions;\r\n storedAgGridParams: ICounterpartyUserRowsParams;\r\n\r\n counterPartiesAndUsers: any[];\r\n modalReference: NgbModalRef;\r\n\r\n /** Store the counterpartyactive fetched from 'Solutions (calpine)' api */\r\n allUserCounterparties: CounterpartyActive[];\r\n /** Store the data received from Identity Server for current request */\r\n currentPageGridData: CounterpartyUserInfo[];\r\n /** Store the requested counterParttIds to Identity Server DB */\r\n requestedCounterPartyIds: number[];\r\n isAnyColumnFilterApplied: boolean;\r\n\r\n showResetCounterpartyUsersGridFilter: boolean = false;\r\n counterpartyFilterValues: string[];\r\n welcomeEmailColumnWidth: number = 90;\r\n setFilterColumns: string[] = ['counterpartyDisplayName'];\r\n\r\n frameworkComponents: any;\r\n groupRowInnerRenderer: string;\r\n\r\n openRemoveUserDialogSub: Subscription;\r\n openEditUserDialogSub: Subscription;\r\n openAddUserDialogSub: Subscription;\r\n openWelcomeEmailDialogSub: Subscription;\r\n openAddEditUserDialogSub: Subscription;\r\n\r\n private gridApi!: GridApi;\r\n\r\n public groupRowRenderer = CounterpartyUsersGroupedRowComponent;\r\n public groupRowRendererParams = {\r\n suppressCount: true,\r\n innerRenderer: CounterpartyUsersGroupedRowComponent\r\n };\r\n public groupDisplayType = 'groupRows';\r\n\r\n constructor(private counterpartyUsersService: CounterpartyUsersService,\r\n private authService: AuthenticationService,\r\n private loggedInUserService: LoggedInUserService,\r\n private gridService: GridService,\r\n private modalService: NgbModal\r\n ) {\r\n\r\n this.counterPartiesAndUsers = [];\r\n this.allUserCounterparties = [];\r\n this.currentPageGridData = [];\r\n this.requestedCounterPartyIds = [];\r\n this.isAnyColumnFilterApplied = false;\r\n this.counterpartyFilterValues = [];\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n this.welcomeEmailColumnWidth = this.hasPortalAdminRole ? 110 : 90;\r\n this.hasCounterpartyAdminRole = false;\r\n this.storedAgGridParams = null;\r\n if (!this.hasPortalAdminRole) {\r\n this.hasCounterpartyAdminRole = _.some(loggedInUserService.getLoggedInUser().counterparties, c => {\r\n return _.some(c.counterpartyRoles, r => {\r\n return r.roleName === Configuration.USER_ROLES.COUNTERPARTY_ADMIN;\r\n });\r\n });\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n\r\n this.gridOptions = {\r\n headerHeight: 50,\r\n //serverSideSortOnServer: true,\r\n //serverSideFilterOnServer: true,\r\n rowSelection: 'multiple',\r\n columnDefs: this.createColumnDefs(),\r\n defaultColDef: {\r\n resizable: true,\r\n filterParams: {\r\n buttons: ['apply', 'clear'],\r\n closeOnApply: true\r\n }\r\n },\r\n\r\n onGridReady: (params: GridReadyEvent) => {\r\n \r\n this.gridApi = params.api;\r\n this.gridApi.sizeColumnsToFit();\r\n this.setNewDatasource().getRows(params);\r\n\r\n },\r\n onModelUpdated: (params) => {\r\n //if (this.gridApi) {\r\n // this.gridApi.sizeColumnsToFit();\r\n //}\r\n },\r\n onGridSizeChanged(params: GridSizeChangedEvent) {\r\n // Only resize columns if the grid container actually has a width\r\n if (params.clientWidth > 0) {\r\n params.api.sizeColumnsToFit();\r\n }\r\n },\r\n suppressMenuHide: true,\r\n suppressPaginationPanel: true,\r\n groupDefaultExpanded: 0, \r\n overlayLoadingTemplate: '
',\r\n icons: {\r\n menu: '',\r\n groupExpanded: '',\r\n groupContracted: ''\r\n },\r\n onFilterChanged: (params) => {\r\n this.agGridPager.currentPage = 1;\r\n this.gridService.onBeforeSetFilterChange(this.gridApi, this.setFilterColumns);\r\n this.setNewDatasource().getRows(params);\r\n let filterMenu = $('.ag-menu');\r\n filterMenu.hide();\r\n },\r\n onSortChanged: () => {\r\n this.setNewDatasource().getRows();\r\n },\r\n onPaginationChanged: (params) => {\r\n //if (params.newPage) {\r\n // this.setNewDatasource().getRows(params);\r\n //}\r\n }\r\n };\r\n this.openAddEditUserDialogSub = this.counterpartyUsersService.openAddEditUserDialog$.subscribe((addEditUserParams: AddEditUserModalParams) => {\r\n addEditUserParams.isFromUsersTab = false;\r\n this.modalReference = this.modalService.open(CounterpartyUsersAddEditDialogComponent);\r\n this.modalReference.componentInstance.user = addEditUserParams;\r\n this.modalReference.result.then((result) => {\r\n console.log(`Closed with: ${result}`);\r\n }, (reason) => {\r\n console.log(`Dismissed ${reason}`);\r\n });\r\n });\r\n\r\n this.openRemoveUserDialogSub = this.counterpartyUsersService.openRemoveUserDialog$.subscribe((removeUserParams: RemoveUserModalParams) => {\r\n this.modalReference = this.modalService.open(CounterpartyUsersRemoveDialogComponent);\r\n this.modalReference.componentInstance.user = removeUserParams;\r\n });\r\n\r\n this.openWelcomeEmailDialogSub = this.counterpartyUsersService.openWelcomeEmailDialog$.subscribe(params => {\r\n this.modalReference = this.modalService.open(SendWelcomeEmailDialogComponent);\r\n this.modalReference.componentInstance.params = params;\r\n });\r\n\r\n }\r\n\r\n ngOnDestroy() {\r\n this.openRemoveUserDialogSub.unsubscribe();\r\n this.openAddEditUserDialogSub.unsubscribe();\r\n this.openWelcomeEmailDialogSub.unsubscribe();\r\n }\r\n\r\n public paginationChanged(params) {\r\n if (params.newPage) {\r\n this.setNewDatasource().getRows(params);\r\n }\r\n }\r\n\r\n public updateUserCounterpartyInfo(user: CounterpartyUserInfo) {\r\n this.setNewDatasource().getRows(this.storedAgGridParams);\r\n }\r\n private populateSetFilters() {\r\n if (this.counterpartyFilterValues.length == 0) {\r\n this.allUserCounterparties.map(c => {\r\n this.counterpartyFilterValues.push(c.shortName);\r\n });\r\n this.gridApi.destroyFilter('counterpartyDisplayName');\r\n\r\n this.gridService.initSetFilters(this.gridApi, this.setFilterColumns);\r\n }\r\n }\r\n\r\n /** Fetch Counterparties for user: If Portal Admin get all, otherwise get assigned CPs where role is Counterparty Admin */\r\n private configureCounterparties() {\r\n return new Promise((resolve, reject) => {\r\n if (this.allUserCounterparties.length > 0) {\r\n resolve(true);\r\n }\r\n this.counterpartyUsersService.getCounterpartiesByLoggedInUserId().subscribe(counterpartyData => {\r\n\r\n let data: any = counterpartyData;\r\n this.allUserCounterparties = data;\r\n\r\n if (!this.loggedInUserService.isPortalAdmin() && !this.loggedInUserService.impersonateTab) {\r\n let userAdminCounterparties = this.loggedInUserService.getLoggedInUser().counterparties\r\n .filter(cp => cp.counterpartyRoles.map(cpr => { return cpr.roleName; }).indexOf(Configuration.USER_ROLES.COUNTERPARTY_ADMIN) != -1)\r\n .map(cp => { return cp.counterpartyId; });\r\n\r\n this.allUserCounterparties = this.allUserCounterparties.filter(cp => { return userAdminCounterparties.indexOf(cp.counterpartyId) != -1 });\r\n }\r\n resolve(true);\r\n });\r\n });\r\n }\r\n\r\n\t/** Sort alphabetically while ignoring case sensitive \r\n\t * Default ag-grid sorting is Case Sensitive\r\n\t */\r\n private caseInsensitiveComparator(valueA, valueB) {\r\n let valueAMissing = valueA === null || valueA === undefined;\r\n let valueBMissing = valueB === null || valueB === undefined;\r\n if (valueAMissing && valueBMissing) {\r\n return 0;\r\n }\r\n if (valueAMissing) {\r\n return -1;\r\n }\r\n if (valueBMissing) {\r\n return 1;\r\n }\r\n\r\n valueA = valueA.toLowerCase();\r\n valueB = valueB.toLowerCase();\r\n\r\n if (valueA < valueB) {\r\n return -1;\r\n } else if (valueA > valueB) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n }\r\n\r\n public resetCounterpartyUsersGridFilters() {\r\n this.showResetCounterpartyUsersGridFilter = false;\r\n if (this.gridApi.isAnyFilterPresent()) {\r\n this.gridApi.setFilterModel(null);\r\n\r\n // clear the mini filters in the set filters\r\n this.gridApi.getColumnFilterInstance('counterpartyDisplayName').then((cpFilterInstance: any) => {\r\n if (cpFilterInstance && typeof cpFilterInstance.setMiniFilter === 'function') {\r\n cpFilterInstance.setMiniFilter('');\r\n cpFilterInstance.eMiniFilter.value = '';\r\n }\r\n this.gridApi.setColumnFilterModel('counterpartyDisplayName', null);\r\n this.gridApi.onFilterChanged();\r\n });\r\n\r\n }\r\n }\r\n\r\n private booleanIndicator(params): any {\r\n if (params.node.level === 1) {\r\n return params.value === true ? \"\" : '';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /** Column Definitions */\r\n private createColumnDefs(): any {\r\n return [\r\n {\r\n headerName: 'Counterparty',\r\n field: 'counterpartyDisplayName',\r\n filter: 'agSetColumnFilter',\r\n filterParams: { values: this.counterpartyFilterValues, newRowsAction: 'keep', apply: true, selectAllOnMiniFilter: true },\r\n sortingOrder: ['asc', 'desc'],\r\n pinned: 'left',\r\n comparator: this.caseInsensitiveComparator,\r\n rowGroup: true,\r\n hide: false,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n\r\n {\r\n headerName: 'Salutation',\r\n field: 'salutation',\r\n filter: 'agTextColumnFilter',\r\n width: 130,\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n sortingOrder: ['asc', 'desc'],\r\n comparator: this.caseInsensitiveComparator,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'First Name', field: 'firstName',\r\n filter: 'agTextColumnFilter',\r\n filterParams: { newRowsAction: 'keep', apply: true }, sortingOrder: ['asc', 'desc'],\r\n comparator: this.caseInsensitiveComparator,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Last Name', field: 'lastName', filter: 'agTextColumnFilter',\r\n filterParams: { newRowsAction: 'keep', apply: true }, sortingOrder: ['asc', 'desc'],\r\n comparator: this.caseInsensitiveComparator,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Email', field: 'email', filter: 'agTextColumnFilter',\r\n filterParams: { newRowsAction: 'keep', apply: true }, sortingOrder: ['asc', 'desc'],\r\n comparator: this.caseInsensitiveComparator,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Phone', field: 'phone', filter: 'agTextColumnFilter',\r\n filterParams: { newRowsAction: 'keep', apply: true }, sortingOrder: ['asc', 'desc'],\r\n comparator: this.caseInsensitiveComparator,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Admin',\r\n field: 'isAdmin',\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n sortingOrder: ['asc', 'desc'],\r\n sortable: true,\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Third Party',\r\n field: 'isThirdParty',\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n sortingOrder: ['asc', 'desc'],\r\n sortable: true,\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Verified', field: 'isAccountVerified',\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n sortingOrder: ['asc', 'desc'], sortable: true,\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n hide: !this.hasPortalAdminRole,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Login Allowed', field: 'isLoginAllowed',\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n sortingOrder: ['asc', 'desc'], sortable: true,\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n }, filter: BooleanFilterComponent,\r\n hide: !this.hasPortalAdminRole,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: '',\r\n headerComponent: SendWelcomeEmailHeaderComponent,\r\n hide: this.loggedInUserService.impersonateTab,\r\n width: 110,\r\n field: 'canEditDelete',\r\n suppressColumnsToolPanel: true,\r\n suppressHeaderMenuButton: true,\r\n sortable: false,\r\n resizable: false,\r\n suppressMovable: true,\r\n cellRenderer: CounterpartyUserEditDeleteButtonComponent,\r\n menuTabs: []\r\n },\r\n {\r\n headerName: 'Impersonate',\r\n hide: !this.loggedInUserService.impersonateTab,\r\n width: 110,\r\n //field: 'canEditDelete',\r\n suppressColumnsToolPanel: true,\r\n suppressHeaderMenuButton: true,\r\n sortable: false,\r\n resizable: false,\r\n suppressMovable: true,\r\n cellRenderer: UserImpersonateViewButtonsComponent,\r\n menuTabs: []\r\n },\r\n ];\r\n }\r\n\r\n /** Set the grid datasource */\r\n private setNewDatasource(overrideGetRowsParams?: ICounterpartyUserRowsParams) {\r\n let datasource = {\r\n\r\n getRows: ((params?: any) => {\r\n let _params = params || {};\r\n _params.counterpartyId = this.storedAgGridParams ? this.storedAgGridParams.counterpartyId : null;\r\n _params.filterModel = this.gridService.deleteEmptySetFilterModels(this.gridApi.getFilterModel(), this.gridOptions, this.setFilterColumns);\r\n _params.sortModel = [];\r\n _params.startRow = (this.agGridPager.currentPage - 1) * this.agGridPager.paginationPageSize;\r\n\r\n if (overrideGetRowsParams) {\r\n this.gridApi.paginationGoToPage(_params.startRow / this.agGridPager.paginationPageSize);\r\n }\r\n\r\n this.configureCounterparties().then(loaded => {\r\n this.populateSetFilters();\r\n /** Adding new property \"counterpartyIds\" in grid params object */\r\n _params.counterpartyIds = this.filterCounterparty(_params);\r\n _params.pageSize = this.agGridPager.paginationPageSize;\r\n this.counterpartyUsersService.getCounterpartyUsers(_params)\r\n .subscribe((data: any) => {\r\n let counterpartyUserData = data.counterpartyUsers as CounterpartyUserInfo[];\r\n\r\n this.currentPageGridData = counterpartyUserData;\r\n\r\n // storedAgGridParams gets used after add/edit/remove of a user so the grid knows where to page to after we reset the data source.\r\n this.storedAgGridParams = _params;\r\n\r\n counterpartyUserData = this.expandFilteredChildColumns(counterpartyUserData, _params.filterModel);\r\n\r\n this.gridService.selectEverythingOnSetFilters(this.gridApi, this.setFilterColumns);\r\n\r\n //this.gridApi.setRowData(counterpartyUserData);\r\n this.gridApi.setGridOption('rowData', counterpartyUserData);\r\n\r\n this.gridService.selectNothingOnSetFiltersWhenAllSelected(this.gridApi, this.setFilterColumns);\r\n this.showResetCounterpartyUsersGridFilter = this.gridApi.isAnyFilterPresent();\r\n\r\n this.agGridPager.refreshPager(Math.ceil(data.rowCount / this.agGridPager.paginationPageSize));\r\n });\r\n\r\n overrideGetRowsParams = null;\r\n });\r\n\r\n })\r\n };\r\n return datasource;\r\n }\r\n\r\n /** Expand user rows when a filter is applied to a user column */\r\n private expandFilteredChildColumns(userData: CounterpartyUserInfo[], filterModel: any) {\r\n let modelProps = Object.getOwnPropertyNames(filterModel);\r\n let hasChildFilter = _.some(modelProps, val => {\r\n return (val === 'salutation' || val === 'firstName' || val === 'lastName' || val === 'email' || val === 'isAdmin' || val === 'isThirdParty' || val === 'isAccountVerified'\r\n || val === 'isLoginAllowed' || val === 'phone');\r\n });\r\n userData.forEach(x => x.isExpanded = hasChildFilter);\r\n return userData;\r\n }\r\n\r\n\t/** \r\n\t * Returned the filter counterpartyIds after applying filtering if any\r\n\t */\r\n private filterCounterparty(options: any): number[] {\r\n this.requestedCounterPartyIds = [];\r\n let filteredData: CounterpartyActive[] = _.cloneDeep(this.allUserCounterparties);\r\n let isFilterApplied: boolean = false;\r\n\r\n _.forOwn(options.filterModel, function (value, key) {\r\n isFilterApplied = true;\r\n });\r\n\r\n let isNonCpFilterApplied: boolean = false;\r\n Object.getOwnPropertyNames(options.filterModel).forEach(val => {\r\n if (!(val.toLowerCase().indexOf('counterpartydisplayname') > -1)) {\r\n isNonCpFilterApplied = true;\r\n }\r\n });\r\n\r\n if (isFilterApplied) {\r\n /** Apply the counterparty filter if user applied any */\r\n if (options.filterModel.counterpartyDisplayName != undefined) {\r\n if (Array.isArray(options.filterModel.counterpartyDisplayName)) {\r\n let selectedCounterParties: any = options.filterModel.counterpartyDisplayName;\r\n filteredData = _.filter(filteredData, (v: CounterpartyActive) => {\r\n return _.includes(selectedCounterParties, v.shortName);\r\n });\r\n }\r\n }\r\n }\r\n\r\n filteredData.forEach((v) => {\r\n this.requestedCounterPartyIds.push(v.counterpartyId);\r\n });\r\n return this.requestedCounterPartyIds;\r\n }\r\n}\r\n\r\n","/** Solutions counterpartyactive api data model */\r\nimport { IAgGridFilterModel, IAgGridSetFilterModel, IAgGridSortModel } from '../../shared/grid/ag-grid.model';\r\nimport { IUserData } from '../../shared/services/logged-in-user.service';\r\nexport class CounterpartyActive {\r\n counterpartyId: number;\r\n shortName: string;\r\n legalName: string;\r\n portalActive: boolean;\r\n}\r\nexport enum Group {\r\n Internal = 1,\r\n Scheduler,\r\n PortalAdministrator,\r\n BillingDataView,\r\n CounterpartyAdministrator,\r\n ThirdPartyVendor,\r\n DownloadInvoice,\r\n InvoiceSummaryReport,\r\n BillingSettlements,\r\n BankingInformationForms\r\n}\r\nexport class Counterparty {\r\n counterpartyId: number;\r\n shortName: string;\r\n legalName: string;\r\n active: boolean;\r\n modifiedOn: Date;\r\n portalActive: boolean;\r\n customerPoints: CustomerPoint[];\r\n}\r\nexport class CustomerPoint {\r\n customerPointId: number;\r\n customerPointName: string;\r\n}\r\n\r\nexport class CounterpartyUsersGrid {\r\n counterpartyId: number;\r\n counterpartyDisplayName: string;\r\n portalActive: boolean;\r\n counterpartyUsers: CounterpartyUserInfo[];\r\n isExpanded?: boolean;\r\n}\r\nexport class CounterpartyUserInfo {\r\n salutation?: string;\r\n firstName?: string;\r\n lastName?: string;\r\n email: string;\r\n isAdmin?: boolean;\r\n isThirdParty?: boolean;\r\n isAccountVerified?: boolean;\r\n isLoginAllowed?: boolean;\r\n phone?: string;\r\n counterparties?: UserCounterparty[];\r\n roles?: any;\r\n isExpanded?: boolean;\r\n newEmail?: string;\r\n rowIndex: number;\r\n isPortalAdmin?: boolean;\r\n globalRoles?: string[];\r\n impersonateRoles?: string[];\r\n}\r\nexport class UserCounterparty {\r\n counterpartyId: number;\r\n counterpartyRoles: CounterpartyUserRole[];\r\n customerPoints: number[];\r\n customerPointNames: string[];\r\n customerPointNamesDisplay: string[];\r\n counterpartyName: string;\r\n}\r\nexport class CounterpartyUserRole {\r\n roleId: number;\r\n roleName: string;\r\n}\r\n\r\nexport class CounterpartyUserPageParameterModel {\r\n counterpartyIds: number[];\r\n searchModel: CounterpartyUserSearchModel;\r\n}\r\nexport class CounterpartyUserSearchModel {\r\n pageNumber: number;\r\n pageSize: number;\r\n sortBy: IAgGridSortModel[];\r\n filters: IAgGridFilterModel[];\r\n setFilters: IAgGridSetFilterModel[];\r\n}\r\n\r\nexport class RemoveUserModalParams {\r\n counterpartyId: number;\r\n email: string;\r\n}\r\n\r\nexport class EditUserModalParams {\r\n counterpartyId: number;\r\n counterpartyDisplayName: string;\r\n userInfo: IUserData;\r\n rowIndex: any;\r\n hasPortalAdminRole: boolean;\r\n}\r\nexport class AddEditUserModalParams {\r\n isAdd: boolean; // true if add, false if edit\r\n isNewUser: boolean;\r\n userInfo?: IUserData;\r\n hasPortalAdminRole: boolean;\r\n id?: string;\r\n counterpartyId: number;\r\n counterpartyName: string;\r\n rowIdx: number;\r\n isFromUsersTab?: boolean;\r\n}\r\n\r\nexport class PostCounterpartyIsPortalActiveParams {\r\n counterpartyId: number;\r\n isPortalActive: boolean;\r\n}\r\n\r\nexport class AddCustomerPointsByNameToUserParams {\r\n userId: number;\r\n customerPointNames: string[];\r\n}\r\n","import { Subject, Observable, of } from 'rxjs';\r\nimport { Injectable } from '@angular/core';\r\n\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { CounterpartyUserPageParameterModel, AddEditUserModalParams, RemoveUserModalParams, PostCounterpartyIsPortalActiveParams, AddCustomerPointsByNameToUserParams, UserCounterparty } from './counterparty-users.model';\r\nimport { GridService } from '../../shared/grid/grid.service';\r\n\r\n@Injectable()\r\nexport class CounterpartyUsersService {\r\n private openRemoveUserDialogSource = new Subject();;\r\n private openWelcomeEmailDialogSource = new Subject();;\r\n private openAddNewUserDialogSource = new Subject();;\r\n private openAddEditUserDialogSource = new Subject();;\r\n \r\n openRemoveUserDialog$ = this.openRemoveUserDialogSource.asObservable();\r\n openWelcomeEmailDialog$ = this.openWelcomeEmailDialogSource.asObservable();\r\n openAddEditUserDialog$ = this.openAddEditUserDialogSource.asObservable();\r\n \r\n constructor(private apiGateway: ApiGatewayService,\r\n private loggedInUserService: LoggedInUserService,\r\n private gridService: GridService) { }\r\n\r\n /**\r\n * Read Counterparty users info from UserAccounts table of identityserver db.\r\n */\r\n public getCounterpartyUsers(params: any): Observable {\r\n\r\n let dataPage: CounterpartyUserPageParameterModel = {\r\n counterpartyIds: params.counterpartyIds,\r\n searchModel: {\r\n pageNumber: Math.floor(params.startRow / params.pageSize),\r\n pageSize: params.pageSize,\r\n sortBy: [],\r\n filters: [],\r\n setFilters: []\r\n }\r\n };\r\n\r\n this.gridService.prepareDataPageModel(dataPage, params.sortModel, params.filterModel);\r\n let getUsersURL: string = PORTAL_API_PATH + 'Admin/GetCounterpartyUsers';\r\n return this.apiGateway.post(getUsersURL, {}, dataPage);\r\n }\r\n public postCounterpartyIsPortalActive(params: any): Observable {\r\n let dataPage: PostCounterpartyIsPortalActiveParams = {\r\n counterpartyId: params.counterpartyId,\r\n isPortalActive: params.isPortalActive\r\n };\r\n let postCounterpartyIsPortalActiveURL: string = PORTAL_API_PATH + 'Admin/PostCounterpartyIsPortalActive';\r\n return this.apiGateway.post(postCounterpartyIsPortalActiveURL, {}, dataPage);\r\n }\r\n\r\n public getCounterpartiesByRole(roleName: string) {\r\n let userId = this.loggedInUserService.getLoggedInUser().key;\r\n \r\n let url: string = PORTAL_IDENTITY_PATH \r\n + 'api/UserInfo/GetUserCounterpartiesByRole?accountId=' + userId \r\n + \"&roleName=\" + encodeURIComponent(roleName);\r\n return this.apiGateway.get(url, null);\r\n }\r\n public getCounterpartiesByLoggedInUserId() : Observable {\r\n if (this.loggedInUserService.activeCounterparties.length > 0) {\r\n return of(this.loggedInUserService.activeCounterparties);\r\n }\r\n return this.loggedInUserService.getCounterpartiesByLoggedInUserId();\r\n }\r\n\r\n public createNewUser(userModel: any): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/AddUserFromPortal';\r\n return this.apiGateway.post(url, {}, userModel);\r\n }\r\n\r\n public searchEmails(searchText: string, counterpartyId): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/SearchUsers?searchText=' + encodeURIComponent(searchText) + \"&counterpartyID=\" + counterpartyId;\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public checkEmailExists(email: string, counterpartyId: number): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/CheckEmailExists?email=' + encodeURIComponent(email) + '&counterpartyId=' + counterpartyId;\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public getUser(guid: string): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/profile?userGUID=' + encodeURIComponent(guid);\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public AddExistingUserToCounterpartyWithRoles(userID: string, counterpartyID: number, globalRoles: string[], counterpartyRoles: number[]): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/AddExistingUserToCounterpartyWithRoles';\r\n let model = {\r\n userID,\r\n counterpartyID,\r\n globalRoles,\r\n counterpartyRoles\r\n };\r\n return this.apiGateway.post(url, null, model);\r\n }\r\n\r\n public updateUserInfo(userModel: any): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/UpdateUserFromPortal';\r\n return this.apiGateway.post(url, {}, userModel);\r\n }\r\n\r\n public sendWelcomeEmail(userEmail: string) {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/SendWelcomeEmail';\r\n return this.apiGateway.post(url, {}, userEmail);\r\n }\r\n\r\n public getAddUserRoles() {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/GetAddUserRoles';\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public removeUserFromCounterparty(counterpartyId: number, userEmail: string): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/RemoveUserFromCounterparty';\r\n let model = {\r\n counterpartyId,\r\n userEmail\r\n };\r\n return this.apiGateway.post(url, {}, model);\r\n }\r\n public getCustomerPointsByCounterpartyId(counterpartyId: number) {\r\n let url: string =\r\n PORTAL_API_PATH + 'CustomerPoints/GetCustomerPointsByCounterpartyId?counterpartyid='\r\n + counterpartyId;\r\n return this.apiGateway.get(url, null);\r\n }\r\n public addCustomerPointsByNametoUser(userAccountId: number, customerPointNames: string[]): Observable {\r\n let requestBody: AddCustomerPointsByNameToUserParams = {\r\n userId: userAccountId,\r\n customerPointNames: customerPointNames\r\n };\r\n let url: string = PORTAL_API_PATH + 'UserAccountSummary/AddByCustomerPointNames';\r\n return this.apiGateway.post(url, {}, requestBody);\r\n }\r\n public getGetImpersonationRoles(): Observable {\r\n let url: string = PORTAL_API_PATH + 'Admin/GetImpersonationRoles';\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public SetSchedulerCounterparty(userid: string, counterparty: UserCounterparty): Observable {\r\n let url: string = PORTAL_API_PATH + 'DynamicSchedulingUser/SetUserCounterparty?userid=' + encodeURIComponent(userid);\r\n return this.apiGateway.post(url, {}, counterparty);\r\n }\r\n public DeleteUserCounterparty(userid: string): Observable {\r\n let url: string = PORTAL_API_PATH + 'DynamicSchedulingUser/DeleteUserCounterparty?userid=' + encodeURIComponent(userid);\r\n return this.apiGateway.post(url, {}, {});\r\n }\r\n openRemoveUserDialog(params: RemoveUserModalParams) {\r\n this.openRemoveUserDialogSource.next(params);\r\n }\r\n\r\n openWelcomeUserDialog(params: any) {\r\n this.openWelcomeEmailDialogSource.next(params);\r\n }\r\n openAddNewUserDialog(params: any) {\r\n this.openAddNewUserDialogSource.next(params);\r\n }\r\n openAddEditUserDialog(params: AddEditUserModalParams) {\r\n this.openAddEditUserDialogSource.next(params);\r\n }\r\n}\r\n","import { Component, ViewChild, ChangeDetectionStrategy, Output, EventEmitter, Input, OnInit } from '@angular/core';\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service'\r\n\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'\r\n\r\n@Component({\r\n selector: 'send-welcome-email-dialog',\r\n template: require('./send-welcome-email-dialog.component.html'),\r\n changeDetection: ChangeDetectionStrategy.Default\r\n})\r\nexport class SendWelcomeEmailDialogComponent implements OnInit {\r\n public showSpinner: boolean;\r\n public userEmail: string;\r\n public allUsers: boolean;\r\n\r\n @Input() public params: string;\r\n @Output() sendEmail: EventEmitter = new EventEmitter();\r\n\r\n constructor(\r\n private counterpartyUsersService: CounterpartyUsersService,\r\n private loggedInUserService: LoggedInUserService,\r\n private activeModal: NgbActiveModal\r\n ) { }\r\n \r\n ngOnInit() {\r\n setTimeout(() => {\r\n this.setupDialogBox(this.params);\r\n }, 1000);\r\n }\r\n\r\n setupDialogBox(userEmail: string) {\r\n this.showSpinner = false;\r\n this.userEmail = userEmail;\r\n this.allUsers = this.userEmail == '-1';\r\n }\r\n \r\n sendUserEmail() {\r\n this.counterpartyUsersService.sendWelcomeEmail(this.userEmail)\r\n .subscribe(() => {\r\n this.sendEmail.emit(this.userEmail);\r\n });\r\n this.activeModal.close('success');\r\n }\r\n\r\n public cancel() {\r\n this.activeModal.close('cancel');\r\n }\r\n}","import { Component, OnInit } from '@angular/core';\r\nimport { IHeaderAngularComp } from 'ag-grid-angular';\r\nimport { IHeaderParams } from 'ag-grid-community';\r\n\r\nimport { CounterpartyUsersService } from './counterparty-users.service';\r\nimport { AuthenticationService } from './../../authentication/authentication.service';\r\n\r\n@Component({\r\n selector: 'send-email-header-button',\r\n template: `\r\n
\r\n \r\n
\r\n `\r\n})\r\n\r\nexport class SendWelcomeEmailHeaderComponent implements IHeaderAngularComp {\r\n hasPortalAdminRole: boolean;\r\n params: IHeaderParams;\r\n\r\n constructor(private authService: AuthenticationService, private counterpartyUserService: CounterpartyUsersService) { }\r\n\r\n agInit(params: IHeaderParams): void {\r\n this.params = params;\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n }\r\n\r\n refresh(params: IHeaderParams): boolean {\r\n this.params = params;\r\n return true; // Return true to signal the header refreshed successfully\r\n }\r\n\r\n openSendAllWelcomeEmailDialog() {\r\n this.counterpartyUserService.openWelcomeUserDialog(-1);\r\n }\r\n \r\n\r\n}","import { Component, OnInit } from '@angular/core';\r\nimport { IHeaderAngularComp } from 'ag-grid-angular';\r\nimport { IHeaderParams } from 'ag-grid-community';\r\n\r\nimport { CounterpartyUsersService } from '../counterparty-users/counterparty-users.service';\r\nimport { AuthenticationService } from './../../authentication/authentication.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { AddEditUserModalParams, RemoveUserModalParams } from '../counterparty-users/counterparty-users.model';\r\n\r\n\r\n\r\n@Component({\r\n selector: 'add-new-user-header-button',\r\n template: `\r\n
\r\n \r\n
\r\n `\r\n})\r\n\r\nexport class AddNewUserHeaderComponent implements IHeaderAngularComp {\r\n hasPortalAdminRole: boolean;\r\n params: IHeaderParams;\r\n\r\n constructor(\r\n private authService: AuthenticationService,\r\n private counterpartyUserService: CounterpartyUsersService,\r\n private loggedInUserService: LoggedInUserService) { }\r\n\r\n agInit(params: IHeaderParams): void {\r\n this.params = params;\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n }\r\n\r\n refresh(params: IHeaderParams): boolean {\r\n this.params = params;\r\n return true; // Return true to signal the header refreshed successfully\r\n }\r\n\r\n openAddNewUserDialog() {\r\n\r\n let params: AddEditUserModalParams = {\r\n isAdd: true,\r\n isNewUser: true,\r\n userInfo: this.loggedInUserService.getLoggedInUser(),\r\n hasPortalAdminRole: this.authService.isPortalAdminUser(),\r\n counterpartyId: 0,\r\n counterpartyName: '',\r\n rowIdx: 0\r\n };\r\n\r\n\r\n\r\n this.counterpartyUserService.openAddEditUserDialog(params);\r\n }\r\n \r\n\r\n}","import { Component, ViewChild, Input, ChangeDetectionStrategy, Output, EventEmitter, OnInit } from '@angular/core';\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'\r\nimport { UsersService } from './users.service';\r\nimport { RemoveUserModalParams } from '../counterparty-users/counterparty-users.model';\r\n\r\n@Component({\r\n selector: 'users-remove-dialog',\r\n template: require('./users-remove-dialog.component.html'),\r\n changeDetection: ChangeDetectionStrategy.Default\r\n})\r\nexport class UsersRemoveDialogComponent implements OnInit {\r\n public userEmail: string;\r\n public showSpinner: boolean;\r\n\r\n @Input() public user: RemoveUserModalParams;\r\n @Output() userRemoved: EventEmitter = new EventEmitter();\r\n\r\n constructor(private usersService: UsersService, private activeModal: NgbActiveModal) { }\r\n \r\n ngOnInit() {\r\n this.setupDialogBox(this.user.email);\r\n }\r\n\r\n setupDialogBox(userEmail: string) {\r\n this.showSpinner = false;\r\n this.userEmail = userEmail;\r\n }\r\n \r\n save() {\r\n this.showSpinner = true;\r\n this.usersService.removeUser(this.userEmail)\r\n .subscribe(() => {\r\n this.userRemoved.emit(this.userEmail);\r\n this.activeModal.close('save');\r\n });\r\n }\r\n\r\n cancel() {\r\n this.activeModal.close('cancelled');\r\n }\r\n}","import { Subscription, Subject } from 'rxjs';\r\nimport { ChangeDetectionStrategy, Component, EventEmitter, OnInit, ViewChild, OnDestroy } from '@angular/core';\r\nimport { GridOptions, IGetRowsParams, ColumnApi, GridApi, GridReadyEvent, TextFilterModel, SetFilterModel, GridSizeChangedEvent } from 'ag-grid-community';\r\nimport * as _ from 'lodash';\r\n\r\nimport { UsersGrid, RemoveUserModalParams } from './users.model';\r\nimport { UsersRemoveDialogComponent } from './users-remove-dialog.component';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { GridService } from '../../shared/grid/grid.service';\r\nimport { CalpineAgGridPagerComponent } from '../../shared/pager/pager.component';\r\nimport { UsersService } from './users.service';\r\nimport { UsersEditDeleteButtonComponent } from '../../shared/edit-delete-button/users-edit-delete-button.component';\r\nimport { UserImpersonateViewButtonsComponent } from '../../shared/impersonate-button/user-impersonate-view-buttons.component';\r\nimport { AddNewUserHeaderComponent } from './add-new-user-header-button.component';\r\nimport { CounterpartyUsersAddEditDialogComponent } from '../counterparty-users/counterparty-users-add-edit-dialog.component';\r\nimport { CounterpartyUsersService } from '../counterparty-users/counterparty-users.service';\r\nimport { AddEditUserModalParams, CounterpartyUserInfo } from '../counterparty-users/counterparty-users.model';\r\nimport { SendWelcomeEmailDialogComponent } from '../counterparty-users/send-welcome-email-dialog.component';\r\nimport { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';\r\nimport { BooleanFilterComponent } from '../../shared/grid/grid.boolean-filter.component';\r\ninterface IUserRowsParams extends IGetRowsParams {\r\n userAccountId: number;\r\n}\r\n\r\n@Component({\r\n selector: 'users',\r\n template: require('./users.component.html'),\r\n changeDetection: ChangeDetectionStrategy.Default,\r\n styles: [require('./users.component.css').toString()]\r\n})\r\nexport class UsersComponent implements OnInit, OnDestroy {\r\n @ViewChild('usersPager') agGridPager: CalpineAgGridPagerComponent;\r\n gridColumnApi!: ColumnApi;\r\n gridApi!: GridApi;\r\n\r\n gridOptions: GridOptions;\r\n storedAgGridParams: IUserRowsParams;\r\n\r\n users: any[];\r\n allUsers: UsersGrid[];\r\n currentPageGridData: UsersGrid[];\r\n isAnyColumnFilterApplied: boolean;\r\n initialGridLoad: boolean;\r\n showResetUsersGridFilter: boolean = false;\r\n setFilterColumns: string[] = ['firstName', 'lastName', 'email'];\r\n firstNameFilterValues: string[];\r\n lastNameFilterValues: string[];\r\n emailFilterValues: string[];\r\n booleanFilterValues: boolean[] = [true, false];\r\n\r\n quickUsersGridFilter: string;\r\n quickUsersGridFilterSource = new Subject();\r\n quickUsersGridFilter$ = this.quickUsersGridFilterSource.asObservable();\r\n usersGridPrepFinished: EventEmitter = new EventEmitter()\r\n\r\n frameworkComponents: any;\r\n\r\n openAddNewUserDialogSub: Subscription;\r\n openRemoveUserDialogSub: Subscription;\r\n openWelcomeEmailDialogSub: Subscription;\r\n\r\n modalReference: NgbModalRef;\r\n\r\n constructor(private usersService: UsersService,\r\n private authService: AuthenticationService,\r\n private loggedInUserService: LoggedInUserService,\r\n private gridService: GridService,\r\n private counterpartyUsersService: CounterpartyUsersService,\r\n private modalService: NgbModal) {\r\n\r\n this.users = [];\r\n this.allUsers = [];\r\n this.currentPageGridData = [];\r\n this.isAnyColumnFilterApplied = false;\r\n this.storedAgGridParams = null;\r\n this.firstNameFilterValues = [];\r\n this.lastNameFilterValues = [];\r\n this.emailFilterValues = [];\r\n this.initialGridLoad = false;\r\n }\r\n\r\n ngOnInit() {\r\n\r\n this.gridOptions = {\r\n headerHeight: 50,\r\n //serverSideSortOnServer: true,\r\n //serverSideFilterOnServer: true,\r\n rowSelection: 'multiple',\r\n columnDefs: this.createColumnDefs(),\r\n defaultColDef: {\r\n resizable: true,\r\n filterParams: {\r\n buttons: ['apply', 'clear'],\r\n closeOnApply: true\r\n }\r\n },\r\n\r\n onGridReady: (params: GridReadyEvent) => {\r\n this.gridColumnApi = params.columnApi;\r\n this.gridApi = params.api;\r\n this.setUsersGridDataSource().getRows(params);\r\n },\r\n onModelUpdated: (params) => {\r\n //if (this.gridApi) {\r\n // this.gridApi.sizeColumnsToFit();\r\n //}\r\n },\r\n onGridSizeChanged(params: GridSizeChangedEvent) {\r\n // Only resize columns if the grid container actually has a width\r\n if (params.clientWidth > 0) {\r\n params.api.sizeColumnsToFit();\r\n }\r\n },\r\n suppressMenuHide: true,\r\n suppressPaginationPanel: true,\r\n overlayLoadingTemplate:\r\n '
',\r\n icons: {\r\n menu: '',\r\n groupExpanded: '',\r\n groupContracted: ''\r\n },\r\n onFilterChanged: (params) => {\r\n this.agGridPager.currentPage = 1;\r\n this.gridService.onBeforeSetFilterChange(this.gridApi, this.setFilterColumns);\r\n this.setUsersGridDataSource().getRows(params);\r\n let filterMenu = $('.ag-menu');\r\n filterMenu.hide();\r\n },\r\n onSortChanged: () => {\r\n this.setUsersGridDataSource().getRows();\r\n },\r\n onPaginationChanged: (params) => {\r\n //if (params.newPage) {\r\n // this.setUsersGridDataSource().getRows(params);\r\n //}\r\n }\r\n }\r\n\r\n this.openAddNewUserDialogSub = this.counterpartyUsersService.openAddEditUserDialog$.subscribe((addEditUserParams: AddEditUserModalParams) => {\r\n addEditUserParams.isFromUsersTab = true;\r\n this.modalReference = this.modalService.open(CounterpartyUsersAddEditDialogComponent);\r\n this.modalReference.componentInstance.user = addEditUserParams;\r\n this.modalReference.result.then((result) => {\r\n console.log(`Closed with: ${result}`);\r\n }, (reason) => {\r\n console.log(`Dismissed ${reason}`);\r\n });\r\n });\r\n this.openRemoveUserDialogSub = this.usersService.openRemoveUserDialog$.subscribe((removeUserModalParams: RemoveUserModalParams) => {\r\n this.modalReference = this.modalService.open(UsersRemoveDialogComponent);\r\n this.modalReference.componentInstance.user = removeUserModalParams;\r\n this.modalReference.result.then((result) => {\r\n console.log(`Closed with: ${result}`);\r\n }, (reason) => {\r\n console.log(`Dismissed ${reason}`);\r\n });\r\n });\r\n this.openWelcomeEmailDialogSub = this.counterpartyUsersService.openWelcomeEmailDialog$.subscribe(params => {\r\n this.modalReference = this.modalService.open(SendWelcomeEmailDialogComponent);\r\n this.modalReference.componentInstance.params = params;\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.openRemoveUserDialogSub.unsubscribe();\r\n this.openAddNewUserDialogSub.unsubscribe();\r\n }\r\n\r\n public paginationChanged(params) {\r\n if (params.newPage) {\r\n this.setUsersGridDataSource().getRows(params);\r\n }\r\n }\r\n\r\n private populateSetFilters() {\r\n if (this.firstNameFilterValues.length == 0) {\r\n this.allUsers.map(u => {\r\n this.firstNameFilterValues.push(u.firstName)\r\n });\r\n this.gridApi.destroyFilter('firstName');\r\n this.gridService.initSetFilters(this.gridApi, this.setFilterColumns);\r\n }\r\n if (this.lastNameFilterValues.length == 0) {\r\n this.allUsers.map(u => {\r\n this.lastNameFilterValues.push(u.lastName);\r\n });\r\n this.gridApi.destroyFilter('lastName');\r\n this.gridService.initSetFilters(this.gridApi, this.setFilterColumns);\r\n }\r\n if (this.emailFilterValues.length == 0) {\r\n this.allUsers.map(u => {\r\n this.emailFilterValues.push(u.email);\r\n });\r\n this.gridApi.destroyFilter('email');\r\n this.gridService.initSetFilters(this.gridApi, this.setFilterColumns);\r\n }\r\n }\r\n private configureAllUsers(startRow: number) {\r\n return new Promise((resolve, reject) => {\r\n if (this.allUsers != null && this.allUsers.length > 0) {\r\n resolve(true);\r\n }\r\n this.usersService.getAllUsers(startRow,\r\n 1,\r\n [],\r\n [],\r\n []).subscribe((data: any) => {\r\n if (startRow == 0) {\r\n let userData = data.users as UsersGrid[];\r\n this.allUsers = userData;\r\n }\r\n this.populateSetFilters();\r\n resolve(true);\r\n });\r\n\r\n });\r\n }\r\n private createColumnDefs(): any {\r\n return [\r\n {\r\n headerName: 'First Name',\r\n field: 'firstName',\r\n filter: 'agSetColumnFilter',\r\n filterParams: {\r\n values: this.firstNameFilterValues,\r\n newRowsAction: 'keep',\r\n apply: true,\r\n selectAllOnMiniFilter: true\r\n },\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Last Name',\r\n field: 'lastName',\r\n filter: 'agSetColumnFilter',\r\n filterParams: {\r\n values: this.lastNameFilterValues,\r\n newRowsAction: 'keep',\r\n apply: true,\r\n selectAllOnMiniFilter: true\r\n },\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Email',\r\n field: 'email',\r\n filter: 'agSetColumnFilter',\r\n filterParams: {\r\n values: this.emailFilterValues,\r\n newRowsAction: 'keep',\r\n apply: true,\r\n selectAllOnMiniFilter: true\r\n },\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Phone',\r\n field: 'phone',\r\n suppressHeaderMenuButton: true\r\n },\r\n {\r\n headerName: 'Admin',\r\n field: 'isAdmin',\r\n suppressHeaderMenuButton: true,\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n }\r\n },\r\n {\r\n headerName: 'Third Party',\r\n field: 'isThirdParty',\r\n suppressHeaderMenuButton: false,\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Verified',\r\n field: 'isAccountVerified',\r\n suppressHeaderMenuButton: false,\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Login Allowed',\r\n field: 'isLoginAllowed',\r\n suppressHeaderMenuButton: false,\r\n filterParams: { newRowsAction: 'keep', apply: true },\r\n cellClass: 'counter-party-column-align-center',\r\n cellRenderer: (params) => { // Function cell renderer\r\n return this.booleanIndicator(params)\r\n },\r\n filter: BooleanFilterComponent,\r\n menuTabs: ['filterMenuTab']\r\n },\r\n {\r\n headerName: 'Impersonate',\r\n width: 110,\r\n hide: !this.loggedInUserService.impersonateTab,\r\n suppressHeaderMenuButton: true,\r\n sortable: false,\r\n resizable: false,\r\n suppressMovable: true,\r\n cellRenderer: UserImpersonateViewButtonsComponent,\r\n },\r\n {\r\n headerName: '',\r\n headerComponent: AddNewUserHeaderComponent,\r\n hide: this.loggedInUserService.impersonateTab,\r\n width: 110,\r\n field: 'canEditDelete',\r\n suppressColumnsToolPanel: true,\r\n suppressHeaderMenuButton: true,\r\n sortable: false,\r\n resizable: false,\r\n suppressMovable: true,\r\n cellRenderer: UsersEditDeleteButtonComponent,\r\n menuTabs: []\r\n },\r\n ]\r\n }\r\n private booleanIndicator(params): any {\r\n if (params.node.level === 0) {\r\n return params.value === true ? \"\" : '';\r\n } else {\r\n return '';\r\n }\r\n }\r\n private caseInsensitiveComparator(valueA, valueB) {\r\n let valueAMissing = valueA === null || valueA === undefined;\r\n let valueBMissing = valueB === null || valueB === undefined;\r\n if (valueAMissing && valueBMissing) {\r\n return 0;\r\n }\r\n if (valueAMissing) {\r\n return -1;\r\n }\r\n if (valueBMissing) {\r\n return 1;\r\n }\r\n\r\n valueA = valueA.toLowerCase();\r\n valueB = valueB.toLowerCase();\r\n\r\n if (valueA < valueB) {\r\n return -1;\r\n } else if (valueA > valueB) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n }\r\n private setUsersGridDataSource(overrideGetRowsParams?: IUserRowsParams) {\r\n let dataSource = {\r\n getRows: ((params?: any) => {\r\n const columnState = this.gridApi.getColumnState();\r\n const sortModel = columnState\r\n .filter(col => col.sort != null)\r\n .map(col => ({\r\n colId: col.colId,\r\n sort: col.sort\r\n }));\r\n\r\n let _params = params || {};\r\n _params.userAccountId = this.storedAgGridParams ? this.storedAgGridParams.userAccountId : null;\r\n _params.filterModel = this.gridService.deleteEmptySetFilterModels(this.gridApi.getFilterModel(),\r\n this.gridOptions,\r\n this.setFilterColumns);\r\n _params.sortModel = sortModel;\r\n _params.startRow = (this.agGridPager.currentPage - 1) * this.agGridPager.paginationPageSize;\r\n\r\n if (overrideGetRowsParams) {\r\n this.gridApi.paginationGoToPage(_params.startRow / this.agGridPager.paginationPageSize);\r\n }\r\n \r\n if (this.loggedInUserService.isPortalAdmin() || this.loggedInUserService.isAllCounterparties()) {\r\n this.configureAllUsers(_params.startRow).then(loaded => {\r\n this.usersService.getAllUsers(_params.startRow,\r\n this.agGridPager.paginationPageSize,\r\n sortModel,\r\n _params.filterModel,\r\n this.quickUsersGridFilter).subscribe((data: any) => {\r\n let userData = data.users as UsersGrid[];\r\n\r\n //this.allUsers = userData;\r\n this.currentPageGridData = userData;\r\n\r\n this.gridService.selectEverythingOnSetFilters(this.gridApi, this.setFilterColumns);\r\n\r\n //this.gridApi.setRowData(userData);\r\n this.gridApi.setGridOption('rowData', userData);\r\n\r\n this.gridService.selectNothingOnSetFiltersWhenAllSelected(this.gridApi, this.setFilterColumns);\r\n\r\n this.showResetUsersGridFilter = this.gridApi.isAnyFilterPresent();\r\n this.agGridPager.refreshPager(Math.ceil(this.allUsers.length / this.agGridPager.paginationPageSize));\r\n this.filterCheck();\r\n });\r\n });\r\n }\r\n else {\r\n this.configureAllUsers(_params.startRow).then(loaded => {\r\n this.populateSetFilters();\r\n /** Adding new property \"counterpartyIds\" in grid params object */\r\n _params.counterpartyIds = this.loggedInUserService.getLoggedInUserActiveCounterpartyIds();\r\n _params.pageSize = this.agGridPager.paginationPageSize;\r\n this.counterpartyUsersService.getCounterpartyUsers(_params)\r\n .subscribe((data: any) => {\r\n let userData = data.counterpartyUsers as UsersGrid[];\r\n\r\n //Remove duplicates from the list\r\n let uniqueUserData: UsersGrid[] = [];\r\n for (let i = 0; i < userData.length; i++) {\r\n if (!uniqueUserData.some(x => x.id == userData[i].id)) {\r\n uniqueUserData.push(userData[i]);\r\n }\r\n }\r\n\r\n //this.allUsers = uniqueUserData;\r\n this.currentPageGridData = uniqueUserData;\r\n\r\n this.gridService.selectEverythingOnSetFilters(this.gridApi, this.setFilterColumns);\r\n\r\n this.gridApi.setRowData(uniqueUserData);\r\n\r\n this.gridService.selectNothingOnSetFiltersWhenAllSelected(this.gridApi, this.setFilterColumns);\r\n\r\n this.showResetUsersGridFilter = this.gridApi.isAnyFilterPresent();\r\n this.agGridPager.refreshPager(Math.ceil(this.allUsers.length / this.agGridPager.paginationPageSize));\r\n this.filterCheck();\r\n });\r\n });\r\n }\r\n overrideGetRowsParams = null;\r\n })\r\n };\r\n return dataSource;\r\n }\r\n public updateUserCounterpartyInfo(user: CounterpartyUserInfo) {\r\n this.setUsersGridDataSource().getRows(this.storedAgGridParams);\r\n }\r\n private resetUsersGridFilters() {\r\n this.showResetUsersGridFilter = false;\r\n if (this.gridApi.isAnyFilterPresent()) {\r\n this.gridApi.setFilterModel(null);\r\n\r\n this.gridApi.onFilterChanged();\r\n this.gridService.initSetFilters(this.gridApi, this.setFilterColumns);\r\n }\r\n }\r\n public onGridFilterChanged() {\r\n this.gridApi.onFilterChanged();\r\n }\r\n public onUsersGridFilterChanged(filterValue) {\r\n this.quickUsersGridFilterSource.next(filterValue);\r\n }\r\n private filterCheck() {\r\n let filteredUsers: UsersGrid[] = this.allUsers;\r\n\r\n let columns: string[] = ['email', 'firstName', 'lastName'];\r\n let filterApplied = false;\r\n\r\n columns.forEach(column => {\r\n let filterModel = this.gridApi.getColumnFilterModel(column) as SetFilterModel;\r\n if (filterModel && filterModel.values.length > 0 && filterModel.values[0].length > 0) {\r\n filteredUsers = filteredUsers.filter(x => filterModel.values[0].includes(x[column]));\r\n filterApplied = true;\r\n }\r\n });\r\n\r\n if (filterApplied) {\r\n this.agGridPager.refreshPager(Math.ceil(filteredUsers.length / this.agGridPager.paginationPageSize));\r\n }\r\n return;\r\n }\r\n}","import { Subject, Observable } from 'rxjs';\r\nimport { Injectable } from '@angular/core';\r\n\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { UserPageParameterModel, EditUserModalParams, RemoveUserModalParams } from './users.model';\r\nimport { GridService } from '../../shared/grid/grid.service';\r\n\r\n@Injectable()\r\nexport class UsersService {\r\n private openAddUserDialogSource = new Subject();\r\n private openEditUserDialogSource = new Subject();\r\n private openRemoveUserDialogSource = new Subject();\r\n\r\n openAddUserDialog$ = this.openAddUserDialogSource.asObservable();\r\n openEditUserDialog$ = this.openEditUserDialogSource.asObservable();\r\n openRemoveUserDialog$ = this.openRemoveUserDialogSource.asObservable();\r\n\r\n constructor(private apiGateway: ApiGatewayService,\r\n private loggedInUserService: LoggedInUserService,\r\n private gridService: GridService) { }\r\n public getAllUsers(startRow: number, pageSize: number, sortModel: any, filterModel: any, quickFilter: any): Observable {\r\n\r\n let dataPage: UserPageParameterModel = {\r\n searchModel: {\r\n pageNumber: Math.floor(startRow / pageSize),\r\n pageSize: pageSize,\r\n sortBy: [],\r\n filters: [],\r\n setFilters: []\r\n }\r\n };\r\n this.gridService.prepareDataPageModel(dataPage, sortModel, filterModel);\r\n let getUsersUrl: string = PORTAL_API_PATH + 'Admin/GetAllUsers';\r\n return this.apiGateway.post(getUsersUrl, {}, dataPage);\r\n }\r\n\r\n public getCounterpartiesByRole(roleName: string) {\r\n let userId = this.loggedInUserService.getLoggedInUser().key;\r\n \r\n let url: string = PORTAL_IDENTITY_PATH \r\n + 'api/UserInfo/GetUserCounterpartiesByRole?accountId=' + userId \r\n + \"&roleName=\" + encodeURIComponent(roleName);\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public createNewUser(userModel: any): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/AddUserFromPortal';\r\n return this.apiGateway.post(url, {}, userModel);\r\n }\r\n\r\n public searchEmails(searchText: string, counterpartyId): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/SearchUsers?searchText=' + encodeURIComponent(searchText) + \"&counterpartyID=\" + counterpartyId;\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public checkEmailExists(email: string, counterpartyId: number): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/CheckEmailExists?email=' + encodeURIComponent(email) + '&counterpartyId=' + counterpartyId;\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public getUser(guid: string): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/profile?userGUID=' + encodeURIComponent(guid);\r\n return this.apiGateway.get(url, null);\r\n }\r\n \r\n\r\n public AddExistingUserToCounterpartyWithRoles(userID: string, counterpartyID: number, globalRoles: string[], counterpartyRoles: number[]): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/AddExistingUserToCounterpartyWithRoles';\r\n let model = {\r\n userID,\r\n counterpartyID,\r\n globalRoles,\r\n counterpartyRoles\r\n };\r\n return this.apiGateway.post(url, null, model);\r\n }\r\n\r\n public updateUserInfo(userModel: any): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/UpdateUserFromPortal';\r\n return this.apiGateway.post(url, {}, userModel);\r\n }\r\n\r\n public sendWelcomeEmail(userEmail: string) {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/SendWelcomeEmail';\r\n return this.apiGateway.post(url, {}, userEmail);\r\n }\r\n\r\n public getAddUserRoles() {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/GetAddUserRoles';\r\n return this.apiGateway.get(url, null);\r\n }\r\n\r\n public removeUserFromCounterparty(counterpartyId: number, userEmail: string): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/RemoveUserFromCounterparty';\r\n let model = {\r\n counterpartyId,\r\n userEmail\r\n };\r\n return this.apiGateway.post(url, {}, model);\r\n }\r\n public removeUser(userEmail: string): Observable {\r\n let url: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/RemoveUser';\r\n let model = {\r\n userEmail\r\n };\r\n return this.apiGateway.post(url, {}, model);\r\n }\r\n \r\n openAddUserDialog(params: any) {\r\n this.openAddUserDialogSource.next(params);\r\n }\r\n\r\n openEditUserDialog(params: EditUserModalParams) {\r\n this.openEditUserDialogSource.next(params);\r\n }\r\n openRemoveUserDialog(params: RemoveUserModalParams) {\r\n this.openRemoveUserDialogSource.next(params);\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n@Injectable()\r\nexport class Configuration {\r\n // Application Servers\r\n public JsAppServerUrl: string = PORTAL_WEB_PATH; // url of this client application\r\n public ApiUrl: string = PORTAL_API_PATH; // url of the api called by this application\r\n\r\n // Authorization Server Connectivity Information\r\n public AuthorizationServerUrl: string = PORTAL_IDENTITY_PATH + 'core/'; // url for the authorization server\r\n public AuthorizationPath: string = 'connect/authorize'; // path on the auth server to call to log in\r\n public AuthorizationClientId: string = 'nesClientPortalJsClient'; // id for this client application as configured on the auth server\r\n public AuthorizationRedirectPath: string = ''; // path in this client application for auth server to redirect to with auth token after login\r\n public LogoutPath: string = 'connect/endsession'; // path on the auth server to call to log out\r\n public LogoutRedirectPath: string = ''; // path in this client application for auth server to redirect to after logout\r\n public AuthorizationScopeId: string = 'nesClientPortalApi'; // scope configured in the auth server, and requested in authorization calls from this client app, to gain access to the NES Portal Api resource\r\n public UserAdministrationUrl: string = PORTAL_IDENTITY_PATH + 'useradmin/'; // url for adding and updating user accounts on the authorization server\r\n public InternalRoleName: string = 'Internal';\r\n public static ShowHighLimitWarningDialogEvent: string = 'showHighLimitWarningDialog'; // static because we can't inject this class into the reducer\r\n public static DestroyunloadhandlersEvent: string = 'destroyunloadhandlers';\r\n\r\n public static USER_ROLES = class {\r\n static PORTAL_ADMIN: string = \"Portal Administrator\";\r\n static SCHEDULER: string = \"Scheduler\";\r\n static INTERNAL: string = \"Internal\";\r\n static COUNTERPARTY_ADMIN = 'Counterparty Administrator';\r\n static BILLING_DATA_VIEW: string = \"Billing Data View\";\r\n static BILLING_SETTLEMENTS = 'Billing Settlements';\r\n static INVOICE_SUMMARY_REPORT = 'Invoice Summary Report';\r\n static DOWNLOAD_INVOICE = 'Download Invoice';\r\n static BANKING_INFORMATION_FORMS = 'Banking Information Forms';\r\n static MONTHLY_REPORTS = 'View Monthly Perspectives Report';\r\n static DAILY_REPORTS = 'View Daily Report';\r\n static IMPERSONATE_SCHEDULER = 'Impersonate: Scheduler';\r\n static IMPERSONATE_BILLING = 'Impersonate: Billing';\r\n static IMPERSONATE_ADMIN = 'Impersonate: Administration';\r\n }\r\n\r\n public static LOCAL_STORAGE = class { \r\n static readonly IS_SERVER_CACHE_READY: string = 'isServerCacheReady';\r\n\r\n static readonly RENEW_TOKEN: string = 'nes.renewToken';\r\n }\r\n\r\n public static ROUTE_PATHS = class {\r\n static readonly BILLING: string = 'billing';\r\n static readonly ADMIN: string = 'administration';\r\n static readonly REPORTS: string = 'reports';\r\n static readonly DYNAMIC_SCHEDULING: string = 'dynamic-scheduling';\r\n static readonly IMPERSONATE: string = 'impersonate';\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { Configuration } from '../app.configuration';\r\nimport { LoggedInUserService } from '../shared/services/logged-in-user.service';\r\nimport { UserRole } from '../shared/services/user-role.service';\r\nimport { AuthenticationService } from './authentication.service';\r\n\r\n\r\n@Injectable()\r\nexport class CanActivateAuthGuard implements CanActivate, CanActivateChild {\r\n constructor(private router: Router, \r\n private authService: AuthenticationService, \r\n private loggedInUserService: LoggedInUserService,\r\n private userRole: UserRole) { }\r\n /**\r\n * Check whether user is allowed to access the page or not.\r\n */\r\n canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {\r\n if (IS_DYNAMIC_SCHEDULING_LANDING_PAGE && state.url === '/') {\r\n this.router.navigate(['dynamic-scheduling/schedule-upload']);\r\n }\r\n\r\n if (!this.isUserSessionActive()) {\r\n this.authService.removeLocalStorageLoggedIn();\r\n this.authService.signIn();\r\n // return false because we don't want routing to be authorized (i.e. return true) while sign in is being processed\r\n return new Promise(resolve => {\r\n return false;\r\n });\r\n }\r\n\r\n sessionStorage.setItem('originalUri', PORTAL_WEB_PATH + '#' + state.url);\r\n\r\n let routeData: any = route.data;\r\n return this.loggedInUserService.getLoggedInUserProfile().then(userLoaded => {\r\n let roles = this.userRole.getAllRolesFromUserProfile(this.loggedInUserService.getLoggedInUser());\r\n\r\n let portalAdmin = this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.PORTAL_ADMIN + '&&' + Configuration.USER_ROLES.INTERNAL);\r\n\r\n\r\n\r\n if (portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, routeData.requiredRoles)) {\r\n return userLoaded;\r\n } else if (routeData.alternateRoute != null) {\r\n sessionStorage.setItem('originalUri', PORTAL_WEB_PATH + '#' + routeData.alternateRoute);\r\n this.router.navigate([routeData.alternateRoute]);\r\n } else {\r\n sessionStorage.setItem('originalUri', PORTAL_WEB_PATH);\r\n this.router.navigate(['/unauthorized-access']);\r\n }\r\n\r\n });\r\n }\r\n \r\n canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise {\r\n return this.canActivate(route, state);\r\n }\r\n\r\n /**\r\n * Checks if user is already logged in and user session is active \r\n * i.e after login user just closed the browser before clicking on logout.\r\n * in this case browser localstorage contains older user info.\r\n * based on these info validates whether user session is active or not\r\n */\r\n private isUserSessionActive(): boolean {\r\n if (this.authService.getLocalStorageLoggedIn() !== 1 // No local storage entry for logged in\r\n || !this.authService.loggedInUser \r\n || !this.authService.loggedInUser.expires_at) { // No token expiry on user \r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n \r\n}\r\n\r\n@Injectable()\r\nexport class DynamicSchedulingAuthGuard implements CanLoad, CanActivate {\r\n constructor() { }\r\n\r\n // Using canLoad as a feature flagging mechanism. \r\n // Currently supporting showing/hiding lazy loaded modules based on feature flags\r\n canLoad(route: Route): boolean {\r\n return true;\r\n }\r\n\r\n canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {\r\n return true;\r\n }\r\n\r\n}\r\n\r\n@Injectable()\r\nexport class CanLoadAuthGuard implements CanLoad {\r\n constructor() { }\r\n \r\n private canLoadRoute(routePath: string): boolean {\r\n let routes = {\r\n 'billing': () => {\r\n return CAN_LOAD_BILLING_MODULE;\r\n },\r\n 'administration': () => {\r\n return CAN_LOAD_ADMIN_MODULE;\r\n },\r\n 'reports': () => {\r\n return CAN_LOAD_REPORTS_MODULE;\r\n },\r\n 'dynamic-scheduling': () => {\r\n return CAN_LOAD_POWER_OPS_MODULE;\r\n },\r\n 'default': () => {\r\n return true;\r\n }\r\n }\r\n\r\n return (routes[routePath] || routes['default'])();\r\n }\r\n\r\n canLoad(route: Route): boolean | Observable | Promise {\r\n return this.canLoadRoute(route.path); \r\n }\r\n\r\n}\r\n","import { EventEmitter, Injectable } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\nimport { UserManager, UserManagerSettings } from 'oidc-client';\r\n\r\nimport { Configuration } from '../app.configuration';\r\nimport { AppGlobalsComponent } from '../shared/app-globals.component';\r\nimport type { IPopupMessageOptions } from '../shared/modal/popup-message-options.component';\r\n\r\n@Injectable()\r\nexport class AuthenticationService {\r\n // Show expiration popup 2 mins before expiration\r\n public accessTokenExpiringNotificationTime: number = 120;\r\n public isAuthorized: boolean;\r\n public loggedInUser: Oidc.User;\r\n public tokenExpiresIn: number;\r\n public userLoadedEvent: EventEmitter = new EventEmitter();\r\n \r\n private isInternalUser: boolean;\r\n private manager: UserManager;\r\n private settings: UserManagerSettings | any;\r\n\r\n constructor(private configuration: Configuration,\r\n private globals: AppGlobalsComponent,\r\n private router: Router) {\r\n\r\n this.OidcClientSettings();\r\n this.manager = new UserManager(this.settings);\r\n this.manager.events.addUserLoaded((e) => {\r\n this.isAuthorized = true;\r\n });\r\n this.manager.events.addUserUnloaded(() => {\r\n this.isAuthorized = false;\r\n });\r\n\r\n /**\r\n * The below is used to handle special scenario\r\n * i.e After login into the system user click the brower refresh button so currently system don't show the loggedInuserName\r\n */\r\n this.setUser();\r\n }\r\n\r\n /**\r\n * Set the user info from session storage as the current default storage for oidc-client is session storage \r\n * rather than localstorage.\r\n */\r\n setUser() {\r\n let user: Oidc.User = JSON.parse(localStorage.getItem('oidc.user:' + this.configuration.AuthorizationServerUrl + ':' + this.configuration.AuthorizationClientId));\r\n if (user != null) {\r\n this.loggedInUser = user;\r\n this.isAuthorized = true;\r\n }\r\n }\r\n\r\n /**\r\n * Get the user manager\r\n */\r\n public getUserManager(): UserManager {\r\n return this.manager;\r\n }\r\n\r\n public IsAuthorized() {\r\n return this.isAuthorized;\r\n }\r\n\r\n public IsInternalUser() {\r\n this.isInternalUser = this.loggedInUser.profile.role === 'Internal'\r\n || (this.loggedInUser.profile.role instanceof Array && this.loggedInUser.profile.role.indexOf('Internal') > -1) ? true : false;\r\n return this.isInternalUser;\r\n }\r\n public isPortalAdminUser() {\r\n return this.loggedInUser != null \r\n && this.loggedInUser.profile.role \r\n && this.loggedInUser.profile.role.indexOf('Portal Administrator') !== -1;\r\n }\r\n getSilentRenewFileName(): string {\r\n let fileName = 'silent_renew.html';\r\n if (this.globals.isInternetExplorer()) {\r\n fileName = 'silent_renew_ie.html';\r\n }\r\n return fileName;\r\n }\r\n\r\n /**\r\n * Settings used oidc client UserManager\r\n */\r\n OidcClientSettings() {\r\n let storageSettings = {\r\n store: localStorage\r\n };\r\n let storage: any = new WebStorageStateStore(storageSettings);\r\n this.settings = {\r\n authority: this.configuration.AuthorizationServerUrl,\r\n client_id: this.configuration.AuthorizationClientId,\r\n redirect_uri: this.configuration.JsAppServerUrl,\r\n post_logout_redirect_uri: this.configuration.JsAppServerUrl,\r\n /**\r\n * These two will be done dynamically from any other place also for e.g. from the buttons clicked, \r\n * but are needed if you want to use the silent_renew\r\n */\r\n response_type: 'id_token token',\r\n scope: 'roles profile openid ' + this.configuration.AuthorizationScopeId,\r\n /**\r\n * Silent renew will get a new access_token via an iframe just prior to the old access_token expiring (60 seconds prior)\r\n */\r\n silent_redirect_uri: this.configuration.JsAppServerUrl + this.getSilentRenewFileName(),\r\n automaticSilentRenew: false,\r\n\r\n // will raise events for when user has performed a logout at IdentityServer\r\n monitorSession: true,\r\n\r\n /**\r\n * will raise events for when user has performed a logout at IdentityServer\r\n */\r\n\r\n accessTokenExpiringNotificationTime: this.accessTokenExpiringNotificationTime.toString(),\r\n silentRequestTimeout: 10000,\r\n /**\r\n * This will allow all the OIDC protocol claims to vbe visible in the window. normally a client app \r\n * wouldn't care about them or want them taking up space\r\n */\r\n filterProtocolClaims: true,\r\n /**\r\n * This will use the user info endpoint if it's an OIDC request and there's an access_token\r\n */\r\n loadUserInfo: true,\r\n userStore: storage\r\n };\r\n };\r\n\r\n /**\r\n * Opens login page of Identiy Server\r\n */\r\n signIn(saveUri: boolean = true) {\r\n /**\r\n * If user loggedOut either manually or by token expiration force to show login screen\r\n */\r\n let loginParam: any = {};\r\n\r\n if (this.getLocalStorageLoggedIn() !== 1) {\r\n this.clearStaleState();\r\n loginParam = { prompt: 'login' };\r\n }\r\n\r\n if (!this.uriContainsExcludedRoute(window.location.href)) {\r\n sessionStorage.removeItem('originalUri');\r\n sessionStorage.setItem('originalUri', window.location.href);\r\n\r\n if (saveUri) {\r\n localStorage.removeItem('originalUri');\r\n localStorage.setItem('originalUri', window.location.hash.replace('#/', ''));\r\n }\r\n }\r\n\r\n this.manager.signinRedirect(loginParam)\r\n .then(() => { })\r\n .catch((err) => {\r\n let modalData: IPopupMessageOptions;\r\n modalData = {\r\n headerText: 'Internal Server Error',\r\n bodyText: \"Please refresh and try again. If problem persists you may contact support at \" + SUPPORT_EMAIL + ' or ' + SUPPORT_PHONE + '.',\r\n buttonText: 'Ok',\r\n show: true,\r\n iconName: 'fa-warning'\r\n };\r\n this.globals.TogglePopupService.next(modalData);\r\n });\r\n }\r\n\r\n /**\r\n * does current uri match a route that we don't want to revert to after login?\r\n * @param originalUri\r\n */\r\n uriContainsExcludedRoute(originalUri: string): boolean {\r\n let excludedRoutes: string[] = ['confirmemail', \r\n 'forgotpassword', \r\n 'confirmresetpassword',\r\n 'login'];\r\n\r\n for (let excludedRoute of excludedRoutes) {\r\n if (originalUri.includes(excludedRoute))\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Manage token after getting it from the token service.\r\n */\r\n endSigninMainWindow() {\r\n this.manager.signinRedirectCallback().then((user) => {\r\n if (user != null) {\r\n this.setLocalStorageLoggedIn();\r\n localStorage.setItem('nes.expires_in', user.expires_in.toString());\r\n sessionStorage.setItem('originalUri', '/');\r\n this.tokenExpiresIn = user.expires_in;\r\n this.loggedInUser = JSON.parse(JSON.stringify(user));\r\n\r\n this.userLoadedEvent.next(user);\r\n this.globals.ToggleMenuService.next(true);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n\r\n let redir_uri: string = localStorage.getItem('originalUri');\r\n localStorage.removeItem('originalUri');\r\n if (redir_uri == null || this.uriContainsExcludedRoute(redir_uri))\r\n redir_uri = '/';\r\n this.router.navigateByUrl(redir_uri);\r\n }\r\n }).catch(function (err) {\r\n console.log(err);\r\n });\r\n }\r\n\r\n /**\r\n * Logout the user\r\n */\r\n signOut() {\r\n this.removeLocalStorageLoggedIn();\r\n localStorage.removeItem('originalUri');\r\n this.signIn(false);\r\n };\r\n\r\n /**\r\n * Get access_token token from brower storage\r\n */\r\n public GetToken(): any {\r\n let user: Oidc.User = JSON.parse(localStorage.getItem('oidc.user:' + this.configuration.AuthorizationServerUrl + ':' + this.configuration.AuthorizationClientId));\r\n if (user != null) {\r\n return user.access_token;\r\n }\r\n }\r\n\r\n public clearStaleState() {\r\n localStorage.clear();\r\n sessionStorage.clear();\r\n this.manager.clearStaleState();\r\n }\r\n\r\n public isCurrentTokenExpired() {\r\n let result: boolean = false;\r\n let lastTimeUserClickedBrowser = +localStorage.getItem('nes.lastClick');\r\n if (lastTimeUserClickedBrowser !== undefined) {\r\n let lastWindowClicked = (Date.now() - lastTimeUserClickedBrowser) / 1000;\r\n if (lastWindowClicked < (this.tokenExpiresIn - this.accessTokenExpiringNotificationTime)) {\r\n result = true;\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n public removeLocalStorageLoggedIn(): void {\r\n localStorage.removeItem('nes.loggedIn');\r\n }\r\n\r\n public setLocalStorageLoggedIn(): void {\r\n localStorage.setItem('nes.loggedIn', '1');\r\n }\r\n\r\n public getLocalStorageLoggedIn(): number {\r\n return +localStorage.getItem('nes.loggedIn');\r\n }\r\n}\r\n","\r\nimport { Injectable } from '@angular/core';\r\nimport { Subject, BehaviorSubject, Observable } from 'rxjs';\r\nimport * as _ from 'lodash';\r\n\r\nimport { ApiGatewayService } from '../shared/services/api-gateway.service';\r\nimport { LoggedInUserService } from '../shared/services/logged-in-user.service';\r\nimport { IInvoiceData, IAccountData, IInvoicesNPaymentData, IBillingAccountOverviewPageParameterModel, AgGridFilterOptions, ISelectedInvoiceDownload, IBillingPageFilterParameterModel } from './billing-account.model';\r\nimport { GridService } from '../shared/grid/grid.service';\r\nimport { IGridFilterObject } from '../shared/grid/grid.service';\r\nimport { Configuration } from '../app.configuration';\r\n\r\n@Injectable()\r\nexport class BillingAccountSummaryService {\r\n private isAccountHistoryVisibleSource = new BehaviorSubject(false);\r\n private accountSummariesSelectedSource = new BehaviorSubject(0);\r\n private selectedInvoicesForDownloadSource = new Subject(); \r\n private invoiceRemovedFromDownloadQueueSource = new Subject();\r\n\r\n isAccountHistoryVisible$ = this.isAccountHistoryVisibleSource.asObservable();\r\n accountSummariesSelected$ = this.accountSummariesSelectedSource.asObservable();\r\n selectedInvoicesForDownload$ = this.selectedInvoicesForDownloadSource.asObservable();\r\n invoiceRemovedFromDownloadQueue$ = this.invoiceRemovedFromDownloadQueueSource.asObservable();\r\n\r\n selectedInvoicesList: ISelectedInvoiceDownload[] = [];\r\n \r\n constructor(private loggedInUserService: LoggedInUserService, \r\n private gridMethods: GridService, \r\n private apiGateway: ApiGatewayService) { }\r\n\r\n public getAccountOverviewPage(startRow: number, pageSize: number, sortModel: any, filterModel: any, quickFilter: string,\r\n selectedBillingAccountIds: number[]): Observable {\r\n \r\n let dataPage: IBillingAccountOverviewPageParameterModel = {\r\n counterparties: this.loggedInUserService.getUserCounterpartyIdsWithRole(Configuration.USER_ROLES.BILLING_DATA_VIEW),\r\n searchModel: {\r\n pageNumber: Math.floor(startRow / pageSize),\r\n pageSize: pageSize,\r\n masterFilter: quickFilter,\r\n sortBy: [],\r\n filters: [],\r\n setFilters: []\r\n },\r\n userAccountId: this.loggedInUserService.getLoggedInUser().key\r\n };\r\n\r\n this.prepareDataPageModel(dataPage, sortModel, filterModel);\r\n\r\n let url: string = PORTAL_API_PATH + 'Billing/GetBillingAccountOverviewDataPage';\r\n return this.apiGateway.post(url, {}, dataPage);\r\n }\r\n\r\n public getAccountIdsForSelectAll(sortModel: any, filterModel: any, quickFilter: string) {\r\n let dataPage: IBillingAccountOverviewPageParameterModel = {\r\n counterparties: this.loggedInUserService.getUserCounterpartyIdsWithRole(Configuration.USER_ROLES.BILLING_DATA_VIEW),\r\n searchModel: {\r\n pageNumber: 0, // non-nullable but not used \r\n pageSize: 0,\r\n masterFilter: quickFilter,\r\n sortBy: [],\r\n filters: [],\r\n setFilters: []\r\n },\r\n userAccountId: this.loggedInUserService.getLoggedInUser().key\r\n };\r\n\r\n this.prepareDataPageModel(dataPage, sortModel, filterModel);\r\n\r\n let url: string = PORTAL_API_PATH + 'Billing/GetAccountIdsForSelectAll';\r\n return this.apiGateway.post(url, {}, dataPage);\r\n }\r\n\r\n public getInvoiceNPaymentData(startRow: number, endRow: number, sortModel: any, filterModel: any,\r\n selectedInvoicesFilterValue: string, pageSize: number, selectedAccountIds, masterFilter: string, monthFilter: string): Observable {\r\n\r\n let dataPage = {\r\n accountIds: selectedAccountIds ? selectedAccountIds : null,\r\n searchModel: {\r\n pageNumber: Math.floor(startRow / pageSize),\r\n pageSize: pageSize,\r\n sortBy: [],\r\n filters: [],\r\n masterFilter: masterFilter,\r\n monthFilter: monthFilter,\r\n setFilters: []\r\n }\r\n };\r\n \r\n this.prepareDataPageModel(dataPage, sortModel, filterModel);\r\n\r\n let url: string = PORTAL_API_PATH + 'Billing/GetInvoiceHistoryDataPage';\r\n return this.apiGateway.post(url, {}, dataPage);\r\n }\r\n\r\n public getInvoiceHistoryData(startRow: number, \r\n pageSize: number, \r\n sortModel: any, \r\n filterModel: any,\r\n selectedInvoicesFilterValue: string, \r\n selectedAccountIds: number[], \r\n masterFilter: string, \r\n monthFilter: string): Observable {\r\n\r\n //let accountIds = _(selectedAccountIds).drop(startRow).take(pageSize).value(); \r\n let dataPage = {\r\n accountIds: selectedAccountIds ? selectedAccountIds : null,\r\n searchModel: {\r\n pageNumber: Math.floor(startRow / pageSize),\r\n pageSize: pageSize,\r\n sortBy: [],\r\n filters: [],\r\n masterFilter: masterFilter,\r\n monthFilter: monthFilter,\r\n setFilters: []\r\n }\r\n };\r\n \r\n this.prepareDataPageModel(dataPage, sortModel, filterModel);\r\n\r\n let url: string = PORTAL_API_PATH + 'Billing/GetInvoiceHistoryDataPage';\r\n return this.apiGateway.post(url, {}, dataPage);\r\n }\r\n\r\n private prepareDataPageModel(dataPage, sortModel, filterModel) {\r\n sortModel.forEach(x => {\r\n dataPage.searchModel.sortBy.push({ colId: x.colId, sortDir: x.sort });\r\n });\r\n\r\n Object.getOwnPropertyNames(filterModel).forEach(val => {\r\n let filterObject: any = filterModel[val];\r\n\r\n if (filterObject.filterType === 'text') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: null, numericFilterToVal: null, stringFilterVal: filterObject.filter, dateFilterVal: null\r\n });\r\n } else if (filterObject.filterType === 'number') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: filterObject.filter, numericFilterToVal: filterObject.filterTo, stringFilterVal: null, dateFilterVal: null\r\n });\r\n } else if (filterObject.filterType === 'set') {\r\n dataPage.searchModel.setFilters.push({ colId: val, stringFilterVals: filterObject.values });\r\n } else if (new Date(filterObject.filter).toString() !== 'Invalid Date') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: null, numericFilterToVal: null, stringFilterVal: null, dateFilterVal: new Date(filterObject.filter)\r\n });\r\n }\r\n }); \r\n }\r\n\r\n private sortParentListInvoicesNPaymentData(invoiceInvoicesNPaymentDataList: IInvoicesNPaymentData[], sortModel: any) {\r\n let greaterThan: number = 1;\r\n let lessThan: number = -1;\r\n if (sortModel[0].sort === 'desc') {\r\n greaterThan = -1;\r\n lessThan = 1;\r\n }\r\n\r\n switch (sortModel[0].colId) {\r\n case 'accountNumber':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.accountNumber > b.accountNumber) { return greaterThan; }\r\n if (a.accountNumber < b.accountNumber) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'previousBalance':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.previousBalance > b.previousBalance) { return greaterThan; }\r\n if (a.previousBalance < b.previousBalance) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'currentCharges':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.currentCharges > b.currentCharges) { return greaterThan; }\r\n if (a.currentCharges < b.currentCharges) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'paymentsReceived':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.paymentsReceived > b.paymentsReceived) { return greaterThan; }\r\n if (a.paymentsReceived < b.paymentsReceived) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'dueDate':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.dueDate > b.dueDate) { return greaterThan; }\r\n if (a.dueDate < b.dueDate) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'counterpartyName':\r\n invoiceInvoicesNPaymentDataList.sort(function (a, b) {\r\n if (a.counterpartyName > b.counterpartyName) { return greaterThan; }\r\n if (a.counterpartyName < b.counterpartyName) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n return invoiceInvoicesNPaymentDataList;\r\n }\r\n\r\n private sortParentList(invoiceList: IInvoiceData[], sortModel: any) {\r\n let greaterThan: number = 1;\r\n let lessThan: number = -1;\r\n if (sortModel[0].sort === 'desc') {\r\n greaterThan = -1;\r\n lessThan = 1;\r\n }\r\n\r\n switch (sortModel[0].colId) {\r\n case '0':\r\n invoiceList.sort(function (a, b) {\r\n if (a.AccountNumber > b.AccountNumber) { return greaterThan; }\r\n if (a.AccountNumber < b.AccountNumber) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'previousBalance':\r\n invoiceList.sort(function (a, b) {\r\n if (a.PreviousBalance > b.PreviousBalance) { return greaterThan; }\r\n if (a.PreviousBalance < b.PreviousBalance) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'dueDate':\r\n invoiceList.sort(function (a, b) {\r\n if (a.DueDate > b.DueDate) { return greaterThan; }\r\n if (a.DueDate < b.DueDate) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n return invoiceList;\r\n }\r\n\r\n private sortChildList(accountList: IAccountData[], sortModel: any) {\r\n let greaterThan: number = 1;\r\n let lessThan: number = -1;\r\n if (sortModel[0].sort === 'desc') {\r\n greaterThan = -1;\r\n lessThan = 1;\r\n }\r\n\r\n switch (sortModel[0].colId) {\r\n case 'utilityAccountNumber':\r\n accountList.sort(function (a, b) {\r\n if (a.UtilityAccountNumber > b.UtilityAccountNumber) { return greaterThan; }\r\n if (a.UtilityAccountNumber < b.UtilityAccountNumber) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'serviceAddress':\r\n accountList.sort(function (a, b) {\r\n if (a.ServiceAddress > b.ServiceAddress) { return greaterThan; }\r\n if (a.ServiceAddress < b.ServiceAddress) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'stateAbbr':\r\n accountList.sort(function (a, b) {\r\n if (a.StateAbbr > b.StateAbbr) { return greaterThan; }\r\n if (a.StateAbbr < b.StateAbbr) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'postalCode':\r\n accountList.sort(function (a, b) {\r\n if (a.PostalCode > b.PostalCode) { return greaterThan; }\r\n if (a.PostalCode < b.PostalCode) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n case 'customerPoint':\r\n accountList.sort(function (a, b) {\r\n if (a.CustomerPoint > b.CustomerPoint) { return greaterThan; }\r\n if (a.CustomerPoint < b.CustomerPoint) { return lessThan; }\r\n return 0;\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n return accountList;\r\n }\r\n\r\n private filterParentColumns(invoiceData: IInvoiceData[], filterModel: any) {\r\n // Filter only on parent columns on grid, excluding dupicate properties from child list\r\n let filteredInvoiceData: IInvoiceData[] = _.cloneDeep(invoiceData);\r\n\r\n Object.getOwnPropertyNames(filterModel).forEach(val => {\r\n if (val === 'counterpartyName' || val === '0' || val === 'previousBalance' || val === 'invoiceDate'\r\n || val === 'totalDueAmount' || val === 'accountNumber' ) {\r\n let filterObject: IGridFilterObject = filterModel[val];\r\n if (val === '0') val = 'accountNumber';\r\n filteredInvoiceData = this.gridMethods.filterColumn(filteredInvoiceData, val, filterObject);\r\n }\r\n });\r\n return filteredInvoiceData;\r\n }\r\n\r\n private filterParentColumnsinvoicesNPaymentData(invoicesNPaymentData: IInvoicesNPaymentData[], filterModel: any) {\r\n // Filter only on parent columns on grid, excluding dupicate properties from child list\r\n let filteredInvoiceData: IInvoicesNPaymentData[] = _.cloneDeep(invoicesNPaymentData);\r\n\r\n Object.getOwnPropertyNames(filterModel).forEach(val => {\r\n if (val === 'counterpartyName' || val === '0' || val === 'previousBalance' || val === 'dueDate') {\r\n let filterObject: IGridFilterObject = filterModel[val];\r\n if (val === '0') val = 'accountNumber';\r\n filteredInvoiceData = this.gridMethods.filterColumn(filteredInvoiceData, val, filterObject);\r\n }\r\n });\r\n\r\n return filteredInvoiceData;\r\n }\r\n toggleAccountHistory() {\r\n this.isAccountHistoryVisibleSource.next(!this.isAccountHistoryVisibleSource.value);\r\n }\r\n\r\n countAccountSummariesSelection(count: number) {\r\n this.accountSummariesSelectedSource.next(count);\r\n }\r\n\r\n setSelectedInvoicesForDownload(selectedInvoice: ISelectedInvoiceDownload) {\r\n let inInvoiceList = _.some(this.selectedInvoicesList, invoice => {\r\n return invoice.invoiceNumber === selectedInvoice.invoiceNumber\r\n });\r\n\r\n if (inInvoiceList) {\r\n _.remove(this.selectedInvoicesList,\r\n function (i) {\r\n let doInvoicesMatch = i.accountId === selectedInvoice.accountId && i.invoiceNumber === selectedInvoice.invoiceNumber\r\n && i.invoiceUrl === selectedInvoice.invoiceUrl && i.invoiceDate === selectedInvoice.invoiceDate\r\n && i.counterpartyName === selectedInvoice.counterpartyName && i.accountNumber === selectedInvoice.accountNumber;\r\n return doInvoicesMatch;\r\n });\r\n } else {\r\n this.selectedInvoicesList.push(selectedInvoice);\r\n }\r\n this.selectedInvoicesForDownloadSource.next(this.selectedInvoicesList);\r\n }\r\n onInvoiceRemovedFromDownloadQueue(invoice: ISelectedInvoiceDownload) {\r\n this.invoiceRemovedFromDownloadQueueSource.next(invoice.invoiceNumber);\r\n }\r\n clearSelectedInvoicesList() {\r\n this.selectedInvoicesList = [];\r\n }\r\n}","export interface IInvoiceData {\r\n AccountId: number; // For mapping child Accounts to Invoices\r\n AccountNumber: string; // Calpine Account number\r\n CounterpartyId: number;\r\n Counterparty: string; // counterParty\r\n CurrentCharges: number;\r\n CustomerId: number;\r\n CustomerPoint: string;\r\n DueDate: number; // Last Invoice Date\r\n Id: number;\r\n InvoiceNumber: number;\r\n PaymentsReceived: number;\r\n PreviousBalance: number; // Tot. Amt Due Last Invoice\r\n StateAbbr: string;\r\n TotalDueAmount: number;\r\n UtilityAccountCount: number;\r\n InvoiceUrl: string;\r\n Accounts: IAccountData[];\r\n isSelected: boolean;\r\n IsExpanded: boolean;\r\n}\r\n\r\nexport interface IAccountData {\r\n AccountBalance: number;\r\n AccountId: number; // Calpine Account number\r\n AccountName: string;\r\n AccountNumber: string;\r\n CompanyLastName: string;\r\n CounterpartyId: number;\r\n Counterparty: string;\r\n CustomerId: number;\r\n CustomerPoint: string; // Customer Point\r\n Id: number;\r\n InvoiceAddress: string;\r\n InvoiceDistribution: string;\r\n MaxInvoiceDate: number;\r\n PostalCode: string; // Zip\r\n ServiceAddress: string; // Service Address\r\n StateAbbr: string; // State\r\n UtilityAccountId: number;\r\n UtilityAccountNumber: string; // Utility Account number\r\n}\r\n\r\n\r\nexport interface IInvoicesNPaymentData {\r\n counterpartyId: number;\r\n counterpartyName: string; // counterParty\r\n accountId: number;\r\n accountNumber: string;\r\n dueDate: number; //lastInvoiceDate: number;\r\n currentCharges: number;\r\n previousBalance: number;//totalAmountDueasofLastInvoice: number;\r\n paymentsReceived: number;//paymentsReceivedSinceLastInvoice: number;\r\n utilityAccountCount: number;\r\n invoiceUrl: string;\r\n invoiceDate: number;\r\n lastPaymentDate: number;\r\n totalDueAmount: number;\r\n accountHistoryData: IAccountHistoryData[];\r\n}\r\n\r\nexport interface IAccountHistoryData {\r\n id: number;\r\n counterpartyId: number;\r\n customerId: number;\r\n accountId: number;\r\n accountNumber: string;\r\n customerPoint: string;\r\n utilityAccountCount: number;\r\n invoiceUrl: string;\r\n invoiceNumber: number;\r\n stateAbbr: string;\r\n previousBalance: number;\r\n paymentsReceived: number;\r\n currentCharges: number;\r\n totalDueAmount: number;\r\n dueDate: number;\r\n invoiceDate: number;\r\n hideDownloadInvoiceColumn: boolean;\r\n counterpartyName: string;\r\n}\r\n\r\nexport interface IBillingSettlement {\r\n wacoeId: number;\r\n customerPoint: string;\r\n startTime: string;\r\n endTime: string;\r\n modifiedOn: string;\r\n lastUpdated: string;\r\n stateAbbr: string;\r\n counterpartyId: number;\r\n counterparty: string;\r\n customerFileUrl: string;\r\n customerFileReferenceCode: string;\r\n customerDocumentTypeId: number;\r\n customerFileId: number;\r\n customerFileDatePosted: string;\r\n customerFileIsPublic: boolean;\r\n customerFileLoaded: boolean;\r\n meterDataFileUrl: string;\r\n meterDataFileReferenceCode: string;\r\n meterDataDocumentTypeId: number;\r\n meterDataFileId: string;\r\n meterDataFileDatePosted: string;\r\n meterDataFileIsPublic: boolean;\r\n meterDataFileLoaded: boolean;\r\n validationFileUrl: string;\r\n validationFileReferenceCode: string;\r\n validationDocumentTypeId: number;\r\n validationFileId: number;\r\n validationFileDatePosted: string;\r\n validationFileIsPublic: boolean;\r\n validationFileLoaded: boolean;\r\n otherFileUrl: string;\r\n otherFileReferenceCode: string;\r\n otherDocumentTypeId: number;\r\n otherFileId: number;\r\n otherFileDatePosted: string;\r\n otherFileIsPublic: boolean;\r\n otherFileLoaded: boolean;\r\n unknownFileUrl: string;\r\n unknownFileReferenceCode: string;\r\n unknownDocumentTypeId: number;\r\n unknownFileId: number;\r\n unknownFileDatePosted: string;\r\n unknownFileIsPublic: boolean;\r\n unknownFileLoaded: boolean;\r\n}\r\n\r\nexport interface ISelectedInvoiceDownload {\r\n accountId: number;\r\n invoiceNumber: number;\r\n invoiceUrl: string;\r\n invoiceDate: string;\r\n counterpartyName: string;\r\n accountNumber: string;\r\n}\r\n\r\nexport interface IBillingSettlementPageParameterModel {\r\n counterparties: CounterpartyFilterModel[];\r\n searchModel: IBillingAccountOverviewSearchModel;\r\n userAccountId: number;\r\n}\r\n\r\nexport class CounterpartyFilterModel {\r\n constructor(counterpartyId: number, customerPoints: number[]) {\r\n this.counterpartyId = counterpartyId;\r\n this.customerPoints = customerPoints;\r\n }\r\n\r\n counterpartyId: number;\r\n customerPoints: number[];\r\n}\r\n\r\nexport interface IBillingAccountOverviewPageParameterModel {\r\n counterparties: CounterpartyFilterModel[];\r\n searchModel: IBillingAccountOverviewSearchModel;\r\n userAccountId: number;\r\n}\r\nexport interface IBillingPageFilterParameterModel {\r\n requestColumns: string[];\r\n counterparties: CounterpartyFilterModel[];\r\n}\r\nexport interface IBillingAccountOverviewSearchModel {\r\n pageNumber: number;\r\n pageSize: number;\r\n masterFilter: string;\r\n sortBy: IAgGridSortModel[];\r\n filters: IAgGridFilterModel[];\r\n setFilters: IAgGridSetFilterModel[];\r\n}\r\nexport interface IBillingPageFilterValuesFilteredParameterModel {\r\n requestColumns: string[];\r\n counterpartyIds: number[];\r\n}\r\nexport interface IAgGridSortModel {\r\n colId: string;\r\n sortDir: string;\r\n}\r\nexport interface IAgGridFilterModel {\r\n colId: string;\r\n filterType: AgGridFilterOptions;\r\n numericFilterVal: number;\r\n numericFilterToVal: number;\r\n stringFilterVal: string;\r\n dateFilterVal: Date;\r\n}\r\nexport interface IAgGridSetFilterModel {\r\n colId: string;\r\n stringFilterVals: string[];\r\n}\r\nexport enum AgGridFilterOptions {\r\n contains = 0,\r\n equals = 1,\r\n startsWith = 2,\r\n endsWith = 3,\r\n notEqual = 4,\r\n lessThan = 5,\r\n lessThanOrEqual = 6,\r\n greaterThan = 7,\r\n greaterThanOrEqual = 8,\r\n before = 9,\r\n after = 10,\r\n inRange = 11,\r\n notContains = 12\r\n}\r\n\r\nexport class AccountInvoicesFilterValueModel {\r\n gridDictionary: AccountSummaryFilterColumns;\r\n invoiceSummaryLevel: InvoicePaymentsFilterColumns;\r\n filterSetsEqual: boolean;\r\n}\r\n\r\nexport class AccountSummaryFilterColumns {\r\n Counterparty: Array;\r\n StateAbbr: Array;\r\n AccountNumber: Array;\r\n CustomerPoint: Array;\r\n}\r\n\r\nexport class InvoicePaymentsFilterColumns {\r\n Counterparty: Array;\r\n StateAbbr: Array;\r\n AccountNumber: Array;\r\n}\r\n\r\nexport class SettlementsFilterValueModel {\r\n gridDictionary: SettlementsFilterColumns; \r\n}\r\n\r\nexport class SettlementsFilterColumns {\r\n Counterparty: Array;\r\n StateAbbr: Array;\r\n CustomerPoint: Array;\r\n DatePosted: Array;\r\n StartDate: Array;\r\n EndDate: Array;\r\n FileId: Array;\r\n}","import { Injectable } from '@angular/core';\r\nimport { AccountHistoryCheckboxColumnComponent } from './invoice-n-payment/account-history-chb-column.component';\r\n\r\n@Injectable()\r\nexport class CheckboxService {\r\n public checkedCheckboxes: AccountHistoryCheckboxColumnComponent[];\r\n constructor() {\r\n this.checkedCheckboxes = [];\r\n }\r\n public addCheckbox(checkboxComponent: AccountHistoryCheckboxColumnComponent) {\r\n this.checkedCheckboxes.push(checkboxComponent);\r\n }\r\n public uncheckAllCheckedCheckboxes() {\r\n this.checkedCheckboxes.forEach(checkbox => {\r\n checkbox.checked = false;\r\n });\r\n this.checkedCheckboxes = [];\r\n }\r\n}","import { Component, ViewChild, Optional } from '@angular/core';\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'\r\n\r\n@Component({\r\n selector: 'invoice-download-error-dialog',\r\n template: require('./invoice-download-error-dialog.component.html')\r\n})\r\n\r\nexport class InvoiceDownloadErrorDialogComponent {\r\n\r\n supportEmail: string = SUPPORT_EMAIL;\r\n supportPhone: string = SUPPORT_PHONE;\r\n\r\n constructor(@Optional() private activeModal: NgbActiveModal) { }\r\n\r\n public close() {\r\n if (this.activeModal) {\r\n this.activeModal.close('Closed');\r\n } \r\n }\r\n}\r\n","import { Injectable, EventEmitter } from '@angular/core';\r\nimport { Store } from '@ngrx/store';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { IScheduleUploadModel, IScheduleUploadBundle, IScheduleUploadInfo, ScheduleUpload } from './schedule-upload.reducer';\r\nimport { HE_RANGE } from '../shared/he-range';\r\nimport { AppData } from '../../app.data';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\n\r\n@Injectable()\r\nexport class ScheduleUploadService {\r\n scheduleUploadModel: Observable;\r\n userEmail: string;\r\n hasGottenPrevious: boolean;\r\n \r\n constructor(private store: Store, private apiGateway: ApiGatewayService, private auth: AuthenticationService, private httpClient: HttpClient) {\r\n this.scheduleUploadModel = store.select(appData => appData.scheduleUploadModel);\r\n //we don't want to grab previous again if the user navigates to a different part of the site. The data's still in the model\r\n this.hasGottenPrevious = false;\r\n\r\n // grab logged in user \r\n if (this.auth.loggedInUser != null) {\r\n this.userEmail = this.auth.loggedInUser.profile.preferred_username;\r\n }\r\n }\r\n\r\n //public getScheduleUploadModel(): Observable {\r\n // return new Observable(observer => {\r\n // this.scheduleUploadModel.subscribe((data) => { observer.next(data); });\r\n // });\r\n //}\r\n\r\n public initializeDynamicScheduling(uploadID: number, email: string) {\r\n\r\n if (!this.hasGottenPrevious) {\r\n this.apiGateway.get(PORTAL_API_PATH + 'DynamicSchedulingEntries/IsDynamicSchedulingAvailable', null)\r\n .subscribe(isDynamicSchedulingAvailable => {\r\n this.store.dispatch({ type: 'SET_DYNAMIC_SCHEDULING_AVAILABLE', payload: isDynamicSchedulingAvailable });\r\n if (isDynamicSchedulingAvailable && email != null) {\r\n this.getPreviousScheduleUpload(uploadID, email);\r\n } else {\r\n // hide the load bar. We're done here\r\n this.hasGottenPrevious = true;\r\n }\r\n });\r\n } else {\r\n // we already have the previous submission. Just reset the UI\r\n this.store.dispatch({ type: 'RESET_DYNAMIC_SCHEDULING'});\r\n }\r\n }\r\n\r\n public getPreviousScheduleUpload(uploadID: number, email: string) {\r\n this.apiGateway.get(PORTAL_API_PATH + 'DynamicSchedulingEntries/GetPreviousScheduleUpload?userEmail=' + encodeURIComponent(email) + (uploadID !== null ? '&uploadID=' + uploadID : ''), null)\r\n .subscribe(data => {\r\n let uploadBundle: any = data; \r\n let fullUploadBundle: IScheduleUploadBundle = {\r\n ScheduleUploadInfo: uploadBundle.ScheduleUploadInfo,\r\n UploadID: uploadBundle.UploadID,\r\n UploadTime: uploadBundle.UploadTime,\r\n Outcome: uploadBundle.Outcome,\r\n isNewUpload: false\r\n };\r\n\r\n this.hasGottenPrevious = true;\r\n this.store.dispatch({ type: 'SET_DYNAMIC_SCHEDULES', payload: fullUploadBundle });\r\n });\r\n }\r\n\r\n public postScheduleWithWarnings(userID: string, uploadID: number, acceptSchedule: boolean): Observable {\r\n let url: string = PORTAL_API_PATH + 'DynamicSchedulingEntries/PostScheduleWithWarnings?userID=' + encodeURIComponent(userID) +\r\n '&uploadID=' + uploadID + '&acceptSchedule=' + acceptSchedule;\r\n\r\n return this.apiGateway.post(url, null, null);\r\n }\r\n\r\n public saveEditedSchedules(schedules: ScheduleUpload[]) {\r\n this.store.dispatch({ type: 'SHOW_LOAD_BAR' }); \r\n var simplifiedSchedules = schedules.map(function (schedule: ScheduleUpload) {\r\n var dynSchedule = Object.assign({}, schedule.DynamicSchedule)\r\n for (var i of HE_RANGE) {\r\n // get rid of the HEValue class.\r\n dynSchedule['HE' + i] = dynSchedule['HE' + i].value;\r\n dynSchedule['HEValidation' + i] = []; \r\n }\r\n return dynSchedule;\r\n });\r\n let model = {\r\n userID: this.userEmail,\r\n schedules: simplifiedSchedules\r\n };\r\n let url: string = PORTAL_API_PATH + 'DynamicSchedulingEntries/PostRevisedUISchedules';\r\n this.apiGateway.post(url, {}, model).subscribe(results => {\r\n let schedules: any = results;\r\n var dataBundle: IScheduleUploadBundle = {\r\n ScheduleUploadInfo: schedules,\r\n UploadTime: null, // clear out the last-submitted time\r\n UploadID: schedules[0].UploadID,\r\n Outcome: null,\r\n isNewUpload: true\r\n };\r\n this.store.dispatch({ type: 'SET_DYNAMIC_SCHEDULES', payload: dataBundle }); \r\n });\r\n }\r\n\r\n public uploadDynamicSchedule(data: FormData): Observable {\r\n\r\n const headers = new HttpHeaders({\r\n 'Authorization': 'Bearer ' + this.auth.GetToken()\r\n });\r\n\r\n return this.httpClient.post(PORTAL_API_PATH + 'DynamicSchedulingEntries/UploadDynamicSchedule', data, { headers });\r\n \r\n }\r\n}\r\n","export const HE_RANGE: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];","import { Injectable, EventEmitter } from '@angular/core';\r\n\r\n@Injectable()\r\nexport class AppGlobalsComponent {\r\n ToggleMenuService: EventEmitter = new EventEmitter();\r\n ToggleFooterMenuService: EventEmitter = new EventEmitter();\r\n TogglePopupService: EventEmitter = new EventEmitter();\r\n ToggleCounterpartyUsersGrid: EventEmitter = new EventEmitter();\r\n ToggleBillingSettlementGrid: EventEmitter = new EventEmitter();\r\n\r\n /** Open the link in new browser window in full screen */\r\n openLinkInBrowserFullScreen(link: string) {\r\n let height: number = screen.availHeight - 100;\r\n let width: number = screen.availWidth - 100;\r\n var popup = window.open(link, \"popup\", \"scrollbars=yes,resizable=yes,status=yes,titlebar=yes,height=\" + height.toString() + \",width=\" + width.toString());\r\n popup.moveTo(0, 0);\r\n }\r\n\r\n /** Check if browser is IE or not. If IE return \"true\" else \"false\"\r\n */\r\n isInternetExplorer() {\r\n return false || !!document.documentMode;\r\n }\r\n\r\n /** Check if browser is Edge or not. If Edge return \"true\" else \"false\"\r\n */\r\n isEdge() {\r\n let ua = navigator.userAgent;\r\n if (ua.indexOf('Edge') > -1) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n isIEorEDGE() {\r\n return this.isInternetExplorer() || this.isEdge();\r\n }\r\n\r\n}\r\n","// src/app/tokens.ts\r\nimport { InjectionToken } from '@angular/core';\r\n\r\nexport const DATEPICKER_FORMAT = new InjectionToken('datepicker.format', {\r\n // Global default value if no overrides exist\r\n providedIn: 'root',\r\n factory: () => 'MM/DD/YYYY'\r\n});\r\n","import { Component, OnInit, EventEmitter, Input, Output, inject } from '@angular/core';\r\nimport { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';\r\nimport { NgbDateCustomParserFormatter } from './ngb-datepicker-custom-formatter';\r\nimport { DATEPICKER_FORMAT } from './datepicker-format.token';\r\n\r\n@Component({\r\n selector: 'datepicker-popup',\r\n template: require('./datepicker-popup.component.html'),\r\n styles: [require('./datepicker-popup.component.css').toString()],\r\n providers: [\r\n { provide: NgbDateParserFormatter, useClass: NgbDateCustomParserFormatter },\r\n ]\r\n})\r\n\r\n\r\nexport class DatePickerPopUpComponent implements OnInit {\r\n @Input() dateDefault: string;\r\n @Input() minDate: Date;\r\n @Input() maxDate: Date;\r\n\r\n @Output() dateSelected: EventEmitter = new EventEmitter ();\r\n date: string;\r\n private mxDate: NgbDateStruct\r\n private miDate: NgbDateStruct\r\n public placeholder: string = inject(DATEPICKER_FORMAT);\r\n constructor(private formatter: NgbDateCustomParserFormatter) {\r\n\r\n }\r\n\r\n ngOnInit() {\r\n this.date = this.dateDefault;\r\n\r\n if (this.maxDate != null) {\r\n this.mxDate = {\r\n year: this.maxDate.getFullYear(),\r\n month: this.maxDate.getMonth() + 1,\r\n day: this.maxDate.getDate()\r\n }\r\n }\r\n\r\n if (this.minDate != null) {\r\n this.miDate = {\r\n year: this.minDate.getFullYear(),\r\n month: this.minDate.getMonth() + 1,\r\n day: this.minDate.getDate()\r\n }\r\n }\r\n }\r\n\r\n dateChanged(event) {\r\n this.dateSelected.emit(this.formatter.format(event));\r\n }\r\n\r\n reset() {\r\n this.date = \"\";\r\n }\r\n}\r\n\r\n ","import { Injectable, inject } from '@angular/core';\r\nimport { NgbDateParserFormatter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';\r\nimport { DATEPICKER_FORMAT } from './datepicker-format.token'\r\n\r\n@Injectable()\r\nexport class NgbDateCustomParserFormatter extends NgbDateParserFormatter {\r\n\r\n protected template: string = inject(DATEPICKER_FORMAT).toUpperCase();\r\n\r\n constructor() {\r\n super(); \r\n }\r\n\r\n parse(value: string): NgbDateStruct | null {\r\n if (value) {\r\n let delimiter = (this.template.replace('MM', ' ').replace('DD', ' ').replace('YYYY', ' ')).trim().split(' ')[0];\r\n const dateParts = value.trim().split(delimiter);\r\n const templateParts = this.template.trim().split(delimiter);\r\n if (dateParts.length === 3) {\r\n return {\r\n month: parseInt(dateParts[templateParts.findIndex(t=>t=='MM')], 10),\r\n day: parseInt(dateParts[templateParts.findIndex(t => t == 'DD')], 10), \r\n year: parseInt(dateParts[templateParts.findIndex(t => t == 'YYYY')], 10),\r\n };\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n format(date: any | null): string {\r\n if (date) {\r\n if (typeof(date) === 'string')\r\n {\r\n if (date.length != this.template.length) {\r\n return date;\r\n }\r\n\r\n if (new Date(date).toString() == 'Invalid Date') {\r\n return date;\r\n }\r\n\r\n return this.formatDate(this.parse(date), this.template);\r\n }\r\n \r\n return this.formatDate(date, this.template);\r\n }\r\n return '';\r\n }\r\n\r\n public formatDate(date: NgbDateStruct | null, template: string | null): string {\r\n\r\n if (template == null) {\r\n template = this.template;\r\n }\r\n if (template != null) {\r\n var result = template.replace('MM', this.padNumber(date.month));\r\n result = result.replace('DD', this.padNumber(date.day));\r\n result = result.replace('YYYY', date.year.toString());\r\n return result;\r\n }\r\n return '';\r\n }\r\n\r\n private padNumber(value: number): string {\r\n if (value !== undefined && value !== null) {\r\n return `0${value}`.slice(-2);\r\n }\r\n return '';\r\n }\r\n}","import { Directive, ElementRef, Input, OnInit, OnChanges, OnDestroy } from '@angular/core';\r\n\r\n//declare var bootstrap: any;\r\nimport * as bootstrap from 'bootstrap';\r\n\r\n\r\n\r\n@Directive({ selector: '[tooltip]' }) \r\nexport class Tooltip implements OnInit, OnChanges, OnDestroy {\r\n // Using mdbootstrap (really just bootstrap) tooltip. The ignite one sucks.\r\n @Input('tooltip') tooltipText: string;\r\n @Input('tooltip-class') tooltipClass: string; \r\n @Input('tooltip-hidden') tooltipHidden: boolean;\r\n @Input('tooltip-placement') tooltipPlacement: string;\r\n private element: HTMLElement;\r\n private tooltip: any;\r\n constructor(public el: ElementRef) {\r\n this.element = el.nativeElement;\r\n }\r\n\r\n ngOnInit() {\r\n if (!this.tooltipHidden) {\r\n this.initTooltip();\r\n }\r\n }\r\n\r\n ngOnChanges() {\r\n // just destroy the old one and make a new one. Bootstrap doesn't have a method for altering tooltip text\r\n if (this.tooltip) {\r\n this.tooltip.dispose();\r\n this.tooltip = null;\r\n }\r\n \r\n if (!this.tooltipHidden) {\r\n this.initTooltip();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.tooltip) {\r\n this.tooltip.dispose();\r\n this.tooltip = null;\r\n }\r\n }\r\n\r\n getOptions() {\r\n var options: TooltipOptions = {};\r\n if (this.tooltipText) {\r\n options.title = this.tooltipText.toString();\r\n }\r\n if (this.tooltipClass) {\r\n //use the default template, just add the class to it so you can style it how you want\r\n options.template = '
';\r\n }\r\n if (this.tooltipPlacement) {\r\n options.placement = this.tooltipPlacement;\r\n }\r\n\r\n options.container = \"body\";\r\n return options;\r\n }\r\n\r\n initTooltip() {\r\n this.tooltip = new bootstrap.Tooltip(this.element, this.getOptions());\r\n\r\n }\r\n\r\n public hide() {\r\n if (this.tooltip) {\r\n this.tooltip.hide();\r\n }\r\n }\r\n}","import { Subscription } from 'rxjs';\r\nimport { Component, OnInit, ViewChild, OnDestroy, Output, EventEmitter, Input } from '@angular/core';\r\nimport { ISelectedInvoiceDownload } from './../../billing/billing-account.model';\r\nimport { BillingAccountSummaryService } from './../../billing/billing-account-summary.service';\r\nimport { ApiGatewayService } from './../services/api-gateway.service';\r\nimport { DownloadFileService } from './../services/download-file.service';\r\nimport { InvoiceDownloadErrorDialogComponent } from '../../billing/invoice-n-payment/invoice-download-error-dialog.component';\r\nimport { AuthenticationService } from './../../authentication/authentication.service';\r\nimport { NgbModal, NgbModalRef, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\r\n\r\n@Component({\r\n selector: 'document-download-list',\r\n template: require('./document-download-list.component.html')\r\n})\r\n\r\nexport class DocumentDownloadListComponent implements OnInit, OnDestroy {\r\n //setSelectedInvoicesForDownloadSub: Subscription;\r\n selectedInvoices: ISelectedInvoiceDownload[];\r\n modalReference: NgbModalRef;\r\n bulkDownloadProcessing: boolean = false;\r\n\r\n @Input() invoices: ISelectedInvoiceDownload[];\r\n @Output() downloadAllEvent = new EventEmitter();\r\n\r\n constructor(private billingAccountService: BillingAccountSummaryService, \r\n private apiGateway: ApiGatewayService, \r\n private fileService: DownloadFileService,\r\n private authService: AuthenticationService,\r\n private modalService: NgbModal,\r\n private activeModal: NgbActiveModal) { }\r\n\r\n ngOnInit() {\r\n this.selectedInvoices = this.invoices;\r\n }\r\n\r\n ngOnDestroy() {\r\n //this.setSelectedInvoicesForDownloadSub.unsubscribe();\r\n }\r\n\r\n downloadSelectedInvoice(invoice: ISelectedInvoiceDownload) {\r\n this.downloadInvoice((success) => {\r\n let fileName: string = invoice.invoiceUrl.split('/').pop();\r\n this.fileService.downloadFileFromStream(success, fileName);\r\n }, invoice.invoiceUrl)\r\n }\r\n\r\n downloadAll() {\r\n if (!this.bulkDownloadProcessing && this.selectedInvoices.length > 0) {\r\n this.bulkDownloadProcessing = true;\r\n this.downloadInvoiceZip((success) => {\r\n let fileName: string = 'SelectedInvoices.zip';\r\n this.fileService.downloadFileFromStream(success, fileName);\r\n this.bulkDownloadProcessing = false;\r\n this.clearSelectedInvoices();\r\n this.downloadAllEvent.emit(success);\r\n }, this.selectedInvoices);\r\n }\r\n }\r\n clearSelectedInvoices() {\r\n this.selectedInvoices = null;\r\n this.billingAccountService.clearSelectedInvoicesList();\r\n }\r\n\r\n removeInvoice(invoice: ISelectedInvoiceDownload) {\r\n this.selectedInvoices = this.selectedInvoices.filter(x => x !== invoice);\r\n this.billingAccountService.setSelectedInvoicesForDownload(invoice);\r\n this.billingAccountService.onInvoiceRemovedFromDownloadQueue(invoice);\r\n }\r\n\r\n public cancel() {\r\n this.activeModal.close('cancel');\r\n }\r\n\r\n private downloadInvoice(success, invoiceUrl) {\r\n let xhr = new XMLHttpRequest();\r\n let fileDownload = PORTAL_API_PATH + 'Billing/DownloadBillingInvoice?fileUrl=' + invoiceUrl;\r\n\r\n xhr.open('GET', fileDownload, true);\r\n xhr.setRequestHeader('Authorization', 'Bearer ' + this.authService.GetToken());\r\n xhr.responseType = 'blob';\r\n\r\n xhr.onreadystatechange = () => {\r\n if (xhr.readyState === 4) {\r\n if (success) {\r\n if (xhr.status === 400 || xhr.status === 401 || xhr.status === 403 || xhr.status === 404 || xhr.status === 500) {\r\n this.modalReference = this.modalService.open(InvoiceDownloadErrorDialogComponent);\r\n } else {\r\n success(xhr.response);\r\n }\r\n }\r\n }\r\n };\r\n\r\n xhr.send(null);\r\n }\r\n\r\n private downloadInvoiceZip(success, invoices: ISelectedInvoiceDownload[]) {\r\n setTimeout(() => {\r\n let xhr = new XMLHttpRequest();\r\n let fileDownload = PORTAL_API_PATH + 'Billing/DownloadBillingInvoicesArchive';\r\n \r\n xhr.open('POST', fileDownload, true);\r\n xhr.setRequestHeader('Authorization', 'Bearer ' + this.authService.GetToken());\r\n xhr.setRequestHeader('Content-Type', 'application/json');\r\n xhr.responseType = 'blob';\r\n \r\n xhr.onreadystatechange = () => {\r\n if (xhr.readyState === 4) {\r\n if (success) {\r\n if (xhr.status === 400 || xhr.status === 401 || xhr.status === 403 || xhr.status === 404 || xhr.status === 500) {\r\n this.modalReference = this.modalService.open(InvoiceDownloadErrorDialogComponent);\r\n } else {\r\n success(xhr.response);\r\n }\r\n }\r\n }\r\n };\r\n \r\n xhr.send(JSON.stringify(invoices));\r\n }, 1000)\r\n\r\n }\r\n\r\n\r\n}","import { ConfirmEmailModel } from './../../user-management/shared/confirm-email.model';\r\nimport { AuthenticationService } from './../../authentication/authentication.service';\r\nimport { CounterpartyUsersService } from '../../administration/counterparty-users/counterparty-users.service';\r\nimport { UsersService } from '../../administration/users/users.service';\r\nimport { Component, OnInit } from '@angular/core';\r\nimport { ICellRendererAngularComp } from 'ag-grid-angular';\r\nimport { ICellRendererParams } from 'ag-grid-community';\r\nimport { RemoveUserModalParams } from '../../administration/users/users.model';\r\nimport { AddEditUserModalParams } from '../../administration/counterparty-users/counterparty-users.model';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\n\r\n@Component({\r\n selector: 'users-edit-delete-button',\r\n template: `\r\n
\r\n \r\n
\r\n `\r\n})\r\n\r\nexport class UsersEditDeleteButtonComponent implements ICellRendererAngularComp {\r\n params: ICellRendererParams;\r\n hasPortalAdminRole: boolean;\r\n \r\n constructor(private counterpartyUserService: CounterpartyUsersService,\r\n private userService: UsersService,\r\n private authService: AuthenticationService,\r\n private loggedInUserService: LoggedInUserService) { }\r\n \r\n agInit(params: ICellRendererParams): void {\r\n this.params = params;\r\n this.hasPortalAdminRole = this.authService.isPortalAdminUser();\r\n }\r\n refresh(params: any): boolean {\r\n return false;\r\n }\r\n openEditUserModal() {\r\n let params: AddEditUserModalParams =\r\n {\r\n isAdd: false,\r\n isNewUser: false,\r\n id: this.params.data.id,\r\n userInfo: this.loggedInUserService.getLoggedInUser(),\r\n hasPortalAdminRole: this.authService.isPortalAdminUser(),\r\n counterpartyId: 0,\r\n counterpartyName: '',\r\n rowIdx: this.params.rowIndex\r\n };\r\n this.counterpartyUserService.openAddEditUserDialog(params);\r\n }\r\n openRemoveUserModal() {\r\n let params: RemoveUserModalParams = {\r\n email: this.params.data.email\r\n };\r\n\r\n this.userService.openRemoveUserDialog(params);\r\n }\r\n}","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'forbidden',\r\n template: require('./forbidden.component.html')\r\n})\r\nexport class ForbiddenComponent {\r\n constructor(){}\r\n}","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'not-found',\r\n template: require('./not-found.component.html')\r\n})\r\nexport class NotFoundComponent {\r\n constructor(){}\r\n}","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'unauthorized-access',\r\n template: require('./unauthorized-access.component.html')\r\n})\r\nexport class UnauthorizedAccessComponent {\r\n constructor(){}\r\n}","import { Component } from '@angular/core';\r\nimport { IFilterAngularComp } from 'ag-grid-angular';\r\nimport { IFilterParams, IDoesFilterPassParams } from 'ag-grid-community';\r\n\r\n@Component({\r\n selector: 'ag-grid-boolean-filter',\r\n template: require('./grid.boolean-filter.component.html'),\r\n})\r\n\r\nexport class BooleanFilterComponent implements IFilterAngularComp {\r\n params!: IFilterParams;\r\n public filter: boolean|null;\r\n\r\n agInit(params: IFilterParams): void {\r\n this.params = params;\r\n }\r\n\r\n doesFilterPass(params: IDoesFilterPassParams): boolean {\r\n\r\n if (this.filter == null) {\r\n return true;\r\n }\r\n\r\n const colId = this.params.column.getColId();\r\n const cellValue = this.params.api.getCellValue({\r\n rowNode: params.node,\r\n colKey: colId\r\n }); //.getValue(colId, params.node);\r\n\r\n if (cellValue == null || cellValue === '') {\r\n if (this.filter == null) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n if (this.filter === cellValue) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n isFilterActive(): boolean {\r\n return this.filter != null;\r\n }\r\n\r\n filterChanged(filter): void {\r\n this.filter = filter;\r\n }\r\n\r\n getModel() {\r\n if (this.isFilterActive()) {\r\n let model: any = { filterType: 'boolean', filter: this.filter };\r\n return model;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n setModel(model: any): void {\r\n if (model) {\r\n this.filter = model.filter || null;\r\n this.applyFilter();\r\n } else {\r\n this.clearFilter();\r\n }\r\n }\r\n\r\n public applyFilter() {\r\n this.params.filterChangedCallback();\r\n }\r\n\r\n public clearFilter() {\r\n this.filter = null;\r\n this.params.filterChangedCallback();\r\n }\r\n\r\n public checkboxClicked(value: boolean): void {\r\n if (value && (this.filter === false || this.filter == null)) {\r\n this.filter = true;\r\n }\r\n else if (!value && (this.filter === true || this.filter == null)) {\r\n this.filter = false;\r\n }\r\n else {\r\n this.filter = null;\r\n }\r\n }\r\n\r\n}","import { Component } from '@angular/core';\r\nimport { IFilterAngularComp } from 'ag-grid-angular';\r\nimport { IFilterParams, IDoesFilterPassParams } from 'ag-grid-community';\r\n\r\n@Component({\r\n selector: 'ag-grid-date-filter',\r\n template: require('./grid.date-filter.component.html'),\r\n})\r\nexport class DateFilterComponent implements IFilterAngularComp {\r\n params!: IFilterParams;\r\n filterDate: string = '';\r\n filterChoices = [{ name: 'Before', value: 'before' }, { name: 'After', value: 'after' } ];\r\n filterSelection: string = 'before';\r\n dateSelected: Date;\r\n\r\n agInit(params: IFilterParams): void {\r\n this.params = params;\r\n }\r\n\r\n doesFilterPass(params: IDoesFilterPassParams): boolean {\r\n const colId = this.params.column.getColId();\r\n const cellValue = this.params.api.getCellValue({\r\n rowNode: params.node,\r\n colKey: colId\r\n }); //.getValue(colId, params.node);\r\n\r\n if (cellValue == null || cellValue === '') {\r\n return false;\r\n }\r\n\r\n const rowDate = new Date(cellValue);\r\n\r\n if (this.filterSelection === 'before') {\r\n return this.dateSelected > rowDate;\r\n } else if (this.filterSelection === 'after') {\r\n return this.dateSelected < rowDate;\r\n } else {\r\n return true;\r\n }\r\n }\r\n\r\n isFilterActive(): boolean {\r\n return this.filterDate !== '';\r\n }\r\n\r\n filterDateChanged(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n this.filterDate = input.value;\r\n this.dateSelected = new Date(this.filterDate);\r\n }\r\n\r\n getModel() {\r\n if (this.isFilterActive()) {\r\n let model: any = { filter: new Date(this.filterDate), type: this.filterSelection };\r\n return model;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n setModel(model: any): void {\r\n if (model) {\r\n this.filterDate = model.filterDate || '';\r\n }\r\n else {\r\n this.filterDate = '';\r\n }\r\n this.params.filterChangedCallback();\r\n }\r\n\r\n public applyFilter() {\r\n if (this.filterDate !== '') {\r\n this.params.filterChangedCallback();\r\n }\r\n }\r\n\r\n public clearFilter(input: HTMLInputElement) {\r\n this.filterDate = '';\r\n input.value = '';\r\n this.params.filterChangedCallback();\r\n }\r\n}\r\n\r\n","export interface IAgGridSortModel {\r\n colId: string;\r\n sortDir: string;\r\n}\r\nexport interface IAgGridFilterModel {\r\n colId: string;\r\n filterType: AgGridFilterOptions;\r\n numericFilterVal: number;\r\n numericFilterToVal: number;\r\n stringFilterVal: string;\r\n dateFilterVal: Date;\r\n}\r\nexport interface IAgGridSetFilterModel {\r\n colId: string;\r\n stringFilterVals: string[];\r\n}\r\nexport enum AgGridFilterOptions {\r\n contains = 0,\r\n equals = 1,\r\n startsWith = 2,\r\n endsWith = 3,\r\n notEqual = 4,\r\n lessThan = 5,\r\n lessThanOrEqual = 6,\r\n greaterThan = 7,\r\n greaterThanOrEqual = 8,\r\n before = 9,\r\n after = 10,\r\n inRange = 11,\r\n notContains = 12\r\n}\r\n\r\nexport interface IAgGridPaginationChangedEvent {\r\n type: string;\r\n newPage: boolean,\r\n pageSize: number,\r\n currentPage: number,\r\n}","import { Injectable } from '@angular/core';\r\nimport * as _ from 'lodash';\r\nimport * as momentImport from 'moment';\r\nconst moment = (momentImport as any).default || momentImport;\r\nimport { GridOptions, NumberFilter, NumberFilterModel, GridApi } from 'ag-grid-community';\r\n\r\nimport { AgGridFilterOptions } from './ag-grid.model';\r\n@Injectable()\r\nexport class GridService {\r\n\r\n // This is a generic method that will filter on a specified column\r\n // and return the filtered list. Specific for Ag-Grid.\r\n public filterColumn(list: any[], filterProperty: string, filterObject: IGridFilterObject) {\r\n\r\n let colType: string = typeof(filterObject.filter);\r\n let filterType: string = filterObject.type;\r\n let filterVal: any = filterObject.filter;\r\n\r\n if (colType === 'string') {\r\n switch (filterType) {\r\n case 'contains':\r\n list = _.filter(list, (v: any) => {\r\n return _.includes(v[filterProperty].toLowerCase(), filterVal.toLowerCase());\r\n });\r\n break;\r\n case 'equals':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty].toLowerCase() === filterVal.toLowerCase();\r\n });\r\n break;\r\n case 'notEquals':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty].toLowerCase() !== filterVal.toLowerCase();\r\n });\r\n break;\r\n case 'startsWith':\r\n list = _.filter(list, (v: any) => {\r\n return _.startsWith(v[filterProperty].toLowerCase(), filterVal.toLowerCase());\r\n });\r\n break;\r\n case 'endsWith':\r\n list = _.filter(list, (v: any) => {\r\n return _.endsWith(v[filterProperty].toLowerCase(), filterVal.toLowerCase());\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n } else if (colType === 'number') {\r\n switch (filterType) {\r\n case 'equals':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] === filterVal;\r\n });\r\n break;\r\n case 'notEqual':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] !== filterVal;\r\n });\r\n break;\r\n case 'lessThan':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] < filterVal;\r\n });\r\n break;\r\n case 'lessThanOrEqual':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] <= filterVal;\r\n });\r\n break;\r\n case 'greaterThan':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] > filterVal;\r\n });\r\n break;\r\n case 'greaterThanOrEqual':\r\n list = _.filter(list, (v: any) => {\r\n return v[filterProperty] >= filterVal;\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n } else if (new Date(filterObject.filter).toString() !== 'Invalid Date') {\r\n switch (filterType) {\r\n case 'before':\r\n list = _.filter(list, (v: any) => {\r\n let colDate: Date = new Date(v[filterProperty]);\r\n return colDate < filterVal;\r\n });\r\n break;\r\n case 'after':\r\n list = _.filter(list, (v: any) => {\r\n let colDate: Date = new Date(v[filterProperty]);\r\n return colDate > filterVal;\r\n });\r\n break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n return list;\r\n }\r\n\r\n // Date Comparator for sorting date columns in grid. \r\n // Takes two dates as strings, converts them to moments, then returns the difference.\r\n public dateColumnComparator(date1: string, date2: string) {\r\n let moment1: moment.Moment = moment(date1);\r\n let moment2: moment.Moment = moment(date2);\r\n let dateDiff = moment1.diff(moment2, 'days');\r\n return dateDiff;\r\n }\r\n\r\n public initSetFilters(gridApi: GridApi, setFilterColumns: string[]) {\r\n this.selectNothingOnSetFilters(gridApi, setFilterColumns);\r\n }\r\n\r\n public onBeforeSetFilterChange(gridApi: GridApi, setFilterColumns: string[]) {\r\n setFilterColumns.forEach(setFilter => {\r\n const model: any = gridApi.getColumnFilterModel(setFilter);\r\n if (!model || !model.values || model.values.length === 0) {\r\n gridApi.setColumnFilterModel(setFilter, { values: [] });\r\n }\r\n });\r\n }\r\n\r\n public deleteEmptySetFilterModels(paramsFilterModel: any, gridOptions: GridOptions, setFilterColumns: string[]): any {\r\n setFilterColumns.forEach(setFilter => {\r\n let filter = paramsFilterModel[setFilter];\r\n var values = filter && filter.values ? filter.values : []; \r\n if (values.length === 0)\r\n delete paramsFilterModel[setFilter];\r\n });\r\n\r\n return paramsFilterModel;\r\n }\r\n\r\n public areSetFiltersLoaded(gridApi: GridApi, setFilterColumns: string[]): boolean {\r\n let areReady = false;\r\n areReady = _.every(setFilterColumns, (colString) => {\r\n\r\n const filterInstance = gridApi.getColumnFilterInstance(colString) as any;\r\n\r\n if (filterInstance) {\r\n // 2. Access the values directly through the internal values array or helper\r\n if (typeof filterInstance.getFilterValues === 'function') {\r\n const uniqueValues = filterInstance.getFilterValues();\r\n \r\n return uniqueValues.length > 0;\r\n } else {\r\n // Fallback: If it's a legacy version, pull from the underlying filter values list\r\n const fallbackValues = filterInstance.getValues ? filterInstance.getValues() : [];\r\n \r\n return fallbackValues.length > 0;\r\n }\r\n }\r\n\r\n return false;\r\n });\r\n return areReady;\r\n }\r\n \r\n public onBeforeNumberFilterChange(gridApi: GridApi, numberFilterColumns: string[]) {\r\n numberFilterColumns.forEach(numberColumn => {\r\n // Remove commas from text entered by user; Ag-Grid cuts off number at comma by default\r\n //let filter: NumberFilter = gridOptions.api.getFilterInstance(numberColumn);\r\n //let filterVal: string = (filter).eFilterTextField.value;\r\n //filterVal = filterVal.replace('$', '');\r\n //filter.filterNumber = parseFloat(filterVal.replace(',', ''));\r\n });\r\n }\r\n\r\n\r\n public selectNothingOnSetFilters(gridApi: GridApi, setFilterColumns: string[]) {\r\n setFilterColumns.forEach(setFilter => {\r\n gridApi.setColumnFilterModel(setFilter, { values: [] });\r\n });\r\n }\r\n\r\n public selectNothingOnSetFiltersWhenAllSelected(gridApi: GridApi, setFilterColumns: string[]) {\r\n setFilterColumns.forEach(setFilter => {\r\n const model: any = gridApi.getColumnFilterModel(setFilter);\r\n gridApi.getColumnFilterInstance(setFilter).then((setFilterInstance: any)=> {\r\n if (!model && !setFilterInstance.getMiniFilter()) {\r\n gridApi.setColumnFilterModel(setFilter, { values: [] });\r\n }\r\n });\r\n });\r\n }\r\n\r\n public selectEverythingOnSetFilters(gridApi: GridApi, setFilterColumns: string[]) {\r\n setFilterColumns.forEach(setFilter => {\r\n const model: any = gridApi.getColumnFilterModel(setFilter);\r\n if (!model || !model.values || model.values.length === 0) {\r\n gridApi.setColumnFilterModel(setFilter, null);\r\n }\r\n });\r\n }\r\n\r\n public prepareDataPageModel(dataPage, sortModel, filterModel) {\r\n sortModel.forEach(x => {\r\n dataPage.searchModel.sortBy.push({ colId: x.colId, sortDir: x.sort });\r\n });\r\n\r\n Object.getOwnPropertyNames(filterModel).forEach(val => {\r\n let filterObject: any = filterModel[val];\r\n\r\n if (filterObject.filterType === 'text') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: null, numericFilterToVal: null, stringFilterVal: filterObject.filter, dateFilterVal: null\r\n });\r\n } else if (filterObject.filterType === 'number') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: filterObject.filter, numericFilterToVal: filterObject.filterTo, stringFilterVal: null, dateFilterVal: null\r\n });\r\n } else if (filterObject.filterType === 'set') {\r\n dataPage.searchModel.setFilters.push({ colId: val, stringFilterVals: filterObject.values });\r\n } else {\r\n var f = filterObject.filter != null ? filterObject.filter.toString() : '';\r\n if (f === 'false' || f === 'true') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: null,\r\n numericFilterVal: null, numericFilterToVal: null, stringFilterVal: f, dateFilterVal: null\r\n });\r\n }\r\n else if (new Date(filterObject.filter).toString() !== 'Invalid Date') {\r\n dataPage.searchModel.filters.push({\r\n colId: val, filterType: AgGridFilterOptions[filterObject.type],\r\n numericFilterVal: null, numericFilterToVal: null, stringFilterVal: null, dateFilterVal: new Date(filterObject.filter)\r\n });\r\n }\r\n }\r\n }); \r\n }\r\n}\r\n\r\nexport interface IGridFilterObject {\r\n type: string;\r\n filter: any;\r\n filterTo: any;\r\n}\r\n","import { Component } from '@angular/core';\r\nimport { ICellRendererParams } from 'ag-grid-community';\r\nimport { ICellRendererAngularComp } from 'ag-grid-angular';\r\nimport { LoggedInUserService } from '../services/logged-in-user.service';\r\nimport { ScheduleUploadService } from '../../dynamic-scheduling/schedule-upload/schedule-upload.service';\r\nimport { CounterpartyUsersService } from '../../administration/counterparty-users/counterparty-users.service';\r\nimport { AddEditUserModalParams, Counterparty } from '../../administration/counterparty-users/counterparty-users.model';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\n\r\n\r\n@Component({\r\n selector: 'user-impersonate-view-buttons',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n `\r\n})\r\n\r\nexport class UserImpersonateViewButtonsComponent implements ICellRendererAngularComp {\r\n params: ICellRendererParams;\r\n\r\n constructor(\r\n private counterpartyUserService: CounterpartyUsersService,\r\n public loggedInUserService: LoggedInUserService,\r\n private authService: AuthenticationService,\r\n private scheduleUploadService: ScheduleUploadService) { }\r\n\r\n agInit(params: ICellRendererParams): void {\r\n this.params = params;\r\n }\r\n\r\n async Impersonate() {\r\n let name = this.params.data.firstName + ' ' + this.params.data.lastName;\r\n this.loggedInUserService.impersonateUsername = name;\r\n this.loggedInUserService.impersonateEmail = this.params.data.email;\r\n this.loggedInUserService.enabledReports = null;\r\n this.scheduleUploadService.hasGottenPrevious = false;\r\n await this.loggedInUserService.impersonate(this.params.data.id);\r\n window.location.assign(window.location.origin + '/#');\r\n }\r\n\r\n openAddEditUserModal() {\r\n let params: AddEditUserModalParams = {\r\n isAdd: false,\r\n isNewUser: false,\r\n id: this.params.data.id,\r\n userInfo: this.loggedInUserService.getLoggedInUser(),\r\n hasPortalAdminRole: this.authService.isPortalAdminUser(),\r\n counterpartyId: this.params.data.counterpartyId,\r\n counterpartyName: this.params.data.shortName,\r\n rowIdx: this.params.rowIndex\r\n };\r\n this.counterpartyUserService.openAddEditUserDialog(params);\r\n }\r\n\r\n refresh(params: any): boolean {\r\n return false;\r\n }\r\n\r\n}","/*\r\n * Angular 2 Dropdown Multiselect for Bootstrap\r\n *\r\n * Simon Lindh\r\n * https://github.com/softsimon/angular-2-dropdown-multiselect\r\n */\r\n\r\nimport {\r\n NgModule,\r\n Component,\r\n Pipe,\r\n OnInit,\r\n DoCheck,\r\n HostListener,\r\n Input,\r\n ElementRef,\r\n Output,\r\n EventEmitter,\r\n forwardRef,\r\n IterableDiffers\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule, NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\r\n\r\nconst MULTISELECT_VALUE_ACCESSOR: any = {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => MultiselectDropdown),\r\n multi: true\r\n};\r\n\r\nexport interface IMultiSelectOption {\r\n id: any;\r\n name: string;\r\n}\r\n\r\nexport interface IMultiSelectSettings {\r\n pullRight?: boolean;\r\n enableSearch?: boolean;\r\n checkedStyle?: 'checkboxes' | 'glyphicon' | 'fontawsome';\r\n buttonClasses?: string;\r\n selectionLimit?: number;\r\n closeOnSelect?: boolean;\r\n autoUnselect?: boolean;\r\n showCheckAll?: boolean;\r\n showUncheckAll?: boolean;\r\n dynamicTitleMaxItems?: number;\r\n maxHeight?: string;\r\n layout?: string;\r\n}\r\n\r\nexport interface IMultiSelectTexts {\r\n checkAll?: string;\r\n uncheckAll?: string;\r\n checked?: string;\r\n checkedPlural?: string;\r\n searchPlaceholder?: string;\r\n defaultTitle?: string;\r\n}\r\n\r\n@Pipe({\r\n name: 'searchFilter'\r\n})\r\nexport class MultiSelectSearchFilter {\r\n transform(options: Array, args: string): Array {\r\n return options.filter((option: IMultiSelectOption) =>\r\n option.name\r\n .toLowerCase()\r\n .indexOf((args || '').toLowerCase()) > -1);\r\n }\r\n}\r\n\r\n@Component({\r\n selector: 'ss-multiselect-dropdown',\r\n providers: [MULTISELECT_VALUE_ACCESSOR],\r\n styles: [`\r\n\t a { outline: none !important; }\r\n `],\r\n template: require('./multiselect-dropdown.html')\r\n})\r\nexport class MultiselectDropdown implements OnInit, DoCheck, ControlValueAccessor {\r\n\r\n @Input() options: Array;\r\n @Input() settings: IMultiSelectSettings;\r\n @Input() texts: IMultiSelectTexts;\r\n @Output() selectionLimitReached = new EventEmitter();\r\n @Output() dropdownClosed = new EventEmitter();\r\n @Output() selectedItems: EventEmitter = new EventEmitter();\r\n @Output() selectedItemNames: EventEmitter = new EventEmitter();\r\n\r\n @HostListener('document: click', ['$event.target'])\r\n onClick(target: HTMLElement) {\r\n let parentFound = false;\r\n while (target != null && !parentFound) {\r\n if (target === this.element.nativeElement) {\r\n parentFound = true;\r\n }\r\n target = target.parentElement;\r\n }\r\n if (!parentFound) {\r\n this.isVisible = false;\r\n }\r\n }\r\n\r\n model: number[];\r\n namesModel: string[];\r\n title: string;\r\n differ: any;\r\n numSelected: number = 0;\r\n isVisible: boolean = false;\r\n searchFilterText: string = '';\r\n defaultSettings: IMultiSelectSettings = {\r\n pullRight: false,\r\n enableSearch: false,\r\n checkedStyle: 'checkboxes',\r\n buttonClasses: 'btn btn-default btn-secondary',\r\n selectionLimit: 0,\r\n closeOnSelect: false,\r\n autoUnselect: false,\r\n showCheckAll: false,\r\n showUncheckAll: false,\r\n dynamicTitleMaxItems: 3,\r\n maxHeight: '300px',\r\n };\r\n defaultTexts: IMultiSelectTexts = {\r\n checkAll: 'Check all',\r\n uncheckAll: 'Uncheck all',\r\n checked: 'checked',\r\n checkedPlural: 'checked',\r\n searchPlaceholder: 'Search...',\r\n defaultTitle: 'Select',\r\n };\r\n\r\n constructor(private element: ElementRef,\r\n private differs: IterableDiffers) {\r\n this.differ = this.differs.find([]).create(null);\r\n }\r\n\r\n ngOnInit() {\r\n this.settings = Object.assign(this.defaultSettings, this.settings);\r\n this.texts = Object.assign(this.defaultTexts, this.texts);\r\n this.title = this.texts.defaultTitle;\r\n this.settings.layout = this.settings.pullRight ? \"row\" : \"column\";\r\n }\r\n\r\n onModelChange: Function = (_: any) => { };\r\n onModelTouched: Function = () => { };\r\n\r\n\r\n writeValue(value: any): void {\r\n if (value !== undefined) {\r\n this.model = value;\r\n }\r\n }\r\n\r\n registerOnChange(fn: Function): void {\r\n this.onModelChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: Function): void {\r\n this.onModelTouched = fn;\r\n }\r\n\r\n ngDoCheck() {\r\n let changes = this.differ.diff(this.model);\r\n if (changes) {\r\n this.updateNumSelected();\r\n this.updateTitle();\r\n }\r\n }\r\n\r\n clearSearch() {\r\n this.searchFilterText = '';\r\n }\r\n\r\n toggleDropdown() {\r\n this.isVisible = !this.isVisible;\r\n if (!this.isVisible) {\r\n this.dropdownClosed.emit();\r\n }\r\n }\r\n\r\n isSelected(option: IMultiSelectOption): boolean {\r\n return this.model && this.model.indexOf(option.id) > -1;\r\n }\r\n\r\n setSelected(event: Event, option: IMultiSelectOption) {\r\n if (!this.model) {\r\n this.model = [];\r\n }\r\n if (!this.namesModel) {\r\n this.namesModel = [];\r\n }\r\n let index = this.model.indexOf(option.id);\r\n if (index > -1) {\r\n this.model.splice(index, 1);\r\n } else {\r\n if (this.settings.selectionLimit === 0 || this.model.length < this.settings.selectionLimit) {\r\n this.model.push(option.id);\r\n this.namesModel.push(option.name);\r\n } else {\r\n if (this.settings.autoUnselect) {\r\n this.model.push(option.id);\r\n this.namesModel.push(option.name);\r\n this.model.shift();\r\n } else {\r\n this.selectionLimitReached.emit(this.model.length);\r\n return;\r\n }\r\n }\r\n }\r\n if (this.settings.closeOnSelect) {\r\n this.toggleDropdown();\r\n }\r\n this.selectedItems.emit(this.model);\r\n this.selectedItemNames.emit(this.namesModel);\r\n this.onModelChange(this.model);\r\n }\r\n\r\n updateNumSelected() {\r\n this.numSelected = this.model && this.model.length || 0;\r\n }\r\n\r\n updateTitle() {\r\n if (this.numSelected === 0) {\r\n this.title = this.texts.defaultTitle;\r\n } else if (this.settings.dynamicTitleMaxItems >= this.numSelected) {\r\n let title = this.options\r\n .filter((option: IMultiSelectOption) =>\r\n this.model && this.model.indexOf(option.id) > -1\r\n )\r\n .map((option: IMultiSelectOption) => option.name)\r\n .join(', ');\r\n\r\n let limit: number;\r\n let screenWidth = window.screen.availWidth;\r\n if (screenWidth == 1280) {\r\n limit = 25;\r\n }\r\n else if (screenWidth > 1280) {\r\n limit = 34;\r\n }\r\n let trail = '...';\r\n this.title = title.length > limit ? title.substring(0, limit) + trail : title;\r\n\r\n } else {\r\n this.title = (this.numSelected === this.options.length ? 'All selected (' : 'Selected (') + this.numSelected + ')';\r\n }\r\n }\r\n\r\n checkAll() {\r\n this.model = this.options.map(option => option.id);\r\n this.selectedItems.emit(this.model);\r\n this.onModelChange(this.model);\r\n }\r\n\r\n uncheckAll() {\r\n this.model = [];\r\n this.selectedItems.emit(this.model);\r\n this.onModelChange(this.model);\r\n }\r\n}\r\n\r\n@NgModule({\r\n imports: [CommonModule, FormsModule],\r\n exports: [MultiselectDropdown],\r\n declarations: [MultiselectDropdown, MultiSelectSearchFilter],\r\n})\r\nexport class MultiselectDropdownModule { }\r\n","import { Component, OnInit, Input, OnDestroy, Output, EventEmitter } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\nimport { GridOptions, PaginationChangedEvent, GridApi } from 'ag-grid-community';\r\nimport * as _ from 'lodash';\r\nimport { IAgGridPaginationChangedEvent } from '../grid/ag-grid.model';\r\n\r\n@Component({\r\n selector: 'calpine-ag-grid-pager',\r\n template: require('./pager.component.html'),\r\n styles: [require('./pager.component.css').toString()]\r\n})\r\n\r\nexport class CalpineAgGridPagerComponent implements OnInit, OnDestroy {\r\n @Input()\r\n gridApi: GridApi;\r\n @Input()\r\n paginationPageSize: number = 10;\r\n\r\n @Output()\r\n onPaginationChanged = new EventEmitter();\r\n\r\n pageChangeEvent: PaginationChangedEvent;\r\n\r\n isLoading: boolean = false;\r\n pageSizes: Array = [10, 25, 50, 100];\r\n pagerNumbers: Array;\r\n totalPages: number;\r\n currentPageNumber$ = new Subject();\r\n currentPage: number = 1;\r\n pagerPageNumberListLength: number = 10;\r\n isBtnPreviousPagesVisible: boolean;\r\n isBtnNextPagesVisible: boolean;\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n this.isLoading = true;\r\n\r\n this.currentPageNumber$.subscribe((value: number) => {\r\n this.isBtnPreviousPagesVisible = (this.currentPage - 1) >= this.pagerPageNumberListLength;\r\n this.isBtnNextPagesVisible = this.totalPages > _.last(this.pagerNumbers);\r\n });\r\n\r\n this.pageChangeEvent = {\r\n type: 'paginationChanged',\r\n animate: false,\r\n newData: false,\r\n newPage: true,\r\n keepRenderedRows: false,\r\n api: this.gridApi,\r\n columnApi: null\r\n } as PaginationChangedEvent;\r\n\r\n }\r\n\r\n refreshPager(totalPageCount?: number) {\r\n this.totalPages = totalPageCount;\r\n let totalPageNumArray: number[] = _.range(1, this.totalPages + 1);\r\n\r\n if (this.totalPages < this.currentPage) {\r\n this.onBtnPageNumber(this.totalPages);\r\n }\r\n \r\n let skipNum = (Math.floor((this.currentPage - 1) / this.pagerPageNumberListLength)) * this.pagerPageNumberListLength;\r\n\r\n let pagerDisplayedPageNumsArray: number[] = _(totalPageNumArray).drop(skipNum).take(this.pagerPageNumberListLength).value();\r\n this.pagerNumbers = pagerDisplayedPageNumsArray;\r\n\r\n this.currentPageNumber$.next(this.currentPage);\r\n\r\n this.isLoading = false;\r\n }\r\n\r\n onBtnFirst() {\r\n this.currentPage = 1;\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnLast() {\r\n this.currentPage = this.totalPages;\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnPrevious() {\r\n if (this.currentPage == 1) return;\r\n this.currentPage = this.currentPage - 1;\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnNext() {\r\n if (this.currentPage == this.totalPages) return;\r\n this.currentPage = this.currentPage + 1;\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnPageNumber(pageNumber: number) {\r\n if (pageNumber !== this.currentPage) {\r\n this.currentPage = pageNumber;\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n }\r\n\r\n onBtnNextPages() {\r\n let totalPages = this.totalPages;\r\n let totalPageNumArray: number[] = _.range(1, totalPages + 1);\r\n \r\n let pageNum = this.currentPage - 1;\r\n let skipNum = (Math.floor(pageNum / this.pagerPageNumberListLength)) * this.pagerPageNumberListLength;\r\n\r\n let pagerDisplayedPageNumsArray: number[] = _(totalPageNumArray).drop(skipNum + this.pagerPageNumberListLength)\r\n .take(this.pagerPageNumberListLength)\r\n .value();\r\n\r\n this.pagerNumbers = pagerDisplayedPageNumsArray; \r\n this.currentPage = this.pagerNumbers[0];\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnPreviousPages() {\r\n let totalPageNumArray: number[] = _.range(1, this.totalPages + 1);\r\n \r\n let pageNum = this.currentPage - 1;\r\n let skipNum = (Math.floor(pageNum / this.pagerPageNumberListLength)) * this.pagerPageNumberListLength;\r\n\r\n let pagerDisplayedPageNumsArray: number[] = _(totalPageNumArray).drop(skipNum - this.pagerPageNumberListLength)\r\n .take(this.pagerPageNumberListLength)\r\n .value();\r\n\r\n this.pagerNumbers = pagerDisplayedPageNumsArray; \r\n this.currentPage = this.pagerNumbers[0];\r\n this.onPaginationChanged.emit(this.getPaginationChangedEvent());\r\n }\r\n\r\n onBtnPageSizeChanged(pageSize: number) {\r\n this.paginationPageSize = pageSize;\r\n this.gridApi.paginationSetPageSize(pageSize);\r\n this.onBtnFirst();\r\n }\r\n\r\n private getPaginationChangedEvent(): PaginationChangedEvent {\r\n return {\r\n type: 'paginationChanged',\r\n animate: false,\r\n newData: false,\r\n newPage: true,\r\n keepRenderedRows: false,\r\n api: this.gridApi,\r\n columnApi: null\r\n } as PaginationChangedEvent;\r\n }\r\n\r\n ngOnDestroy() {\r\n this.currentPageNumber$.unsubscribe();\r\n }\r\n}","/// Credit goes to Ben Nadel and Sam Storie who wrote and translated to Typescript the ApiGateway logic: https://blog.sstorie.com/adapting-ben-nadels-apigateway-to-pure-typescript/\r\n\r\nimport { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { Observable, Subject, throwError } from 'rxjs';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { catchError, map, finalize } from 'rxjs/operators';\r\n\r\nexport enum HttpRequestMethod {\r\n Get = 'GET',\r\n Post = 'POST'\r\n}\r\n\r\nexport class ApiGatewayOptions {\r\n method: HttpRequestMethod;\r\n url: string;\r\n headers = new HttpHeaders();\r\n params = {};\r\n data = {};\r\n}\r\n\r\n\r\n@Injectable()\r\nexport class ApiGatewayService {\r\n\r\n // Define the internal Subject we'll use to push errors\r\n private errorsSubject = new Subject();\r\n\r\n // Provide the *public* Observable that clients can subscribe to\r\n errors$: Observable;\r\n\r\n // Define the internal Subject we'll use to push the command count\r\n private pendingCommandsSubject = new Subject();\r\n private pendingCommandCount = 0;\r\n\r\n // Provide the *public* Observable that clients can subscribe to\r\n pendingCommands$: Observable;\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private securityService: AuthenticationService\r\n ) {\r\n // Create our observables from the subjects\r\n this.errors$ = this.errorsSubject.asObservable();\r\n this.pendingCommands$ = this.pendingCommandsSubject.asObservable();\r\n\r\n }\r\n\r\n // I perform a GET request to the API, appending the given params\r\n // as URL search parameters. Returns a stream.\r\n get(url: string, params: any): Observable {\r\n let options = new ApiGatewayOptions();\r\n options.method = HttpRequestMethod.Get;\r\n options.url = url;\r\n options.params = params;\r\n\r\n return this.request(options);\r\n }\r\n\r\n\r\n // I perform a POST request to the API. If both the params and data\r\n // are present, the params will be appended as URL search parameters\r\n // and the data will be serialized as a JSON payload. If only the\r\n // data is present, it will be serialized as a JSON payload. Returns\r\n // a stream.\r\n post(url: string, params: any, data: any): Observable {\r\n if (!data) {\r\n data = params;\r\n params = {};\r\n }\r\n let options = new ApiGatewayOptions();\r\n options.method = HttpRequestMethod.Post;\r\n options.url = url;\r\n options.params = params;\r\n options.data = data;\r\n\r\n return this.request(options);\r\n }\r\n\r\n\r\n private request(options: ApiGatewayOptions): Observable {\r\n\r\n //this.interpolateUrl(options);\r\n this.addXsrfToken(options);\r\n this.addBearerToken(options);\r\n this.addContentType(options);\r\n\r\n let requestOptions = {\r\n headers: options.headers,\r\n params: this.buildUrlSearchParams(options.params),\r\n body: JSON.stringify(options.data)\r\n }\r\n\r\n //console.log('Request Method - Url:', options.method, options.url);\r\n //console.log('ApiGatewayService.request() - requestOptions:', requestOptions);\r\n let isCommand = (options.method !== HttpRequestMethod.Get);\r\n\r\n if (isCommand) {\r\n this.pendingCommandsSubject.next(++this.pendingCommandCount);\r\n }\r\n\r\n let stream = this.http.request(options.method, options.url, requestOptions)\r\n .pipe(\r\n catchError((error: any) => {\r\n this.errorsSubject.next(error); // Keeps ApiGateway simple. Search codebase for \"apiGateway.errors$.subscribe\" to find where the error is handled\r\n return throwError(error);\r\n }),\r\n map(response => response),\r\n catchError((error: any) => {\r\n return throwError(error);\r\n }),\r\n finalize(() => {\r\n if (isCommand) {\r\n this.pendingCommandsSubject.next(--this.pendingCommandCount);\r\n }\r\n })\r\n );\r\n\r\n return stream;\r\n }\r\n\r\n\r\n private addContentType(options: ApiGatewayOptions): ApiGatewayOptions {\r\n if (options.method !== HttpRequestMethod.Get) {\r\n options.headers = options.headers.append(\"Content-Type\", \"application/json;charset=UTF-8\");\r\n }\r\n return options;\r\n }\r\n\r\n private extractValue(collection: any, key: string): any {\r\n var value = collection[key];\r\n delete (collection[key]);\r\n return value;\r\n }\r\n\r\n private addBearerToken(options: ApiGatewayOptions): ApiGatewayOptions {\r\n let authToken = this.securityService.GetToken();\r\n if (authToken) {\r\n options.headers = options.headers.append('Authorization', 'Bearer ' + authToken);\r\n }\r\n return options;\r\n }\r\n\r\n private addXsrfToken(options: ApiGatewayOptions): ApiGatewayOptions {\r\n var xsrfToken = this.getXsrfCookie();\r\n if (xsrfToken) {\r\n options.headers = options.headers.append('X-XSRF-TOKEN', xsrfToken);\r\n }\r\n return options;\r\n }\r\n\r\n private getXsrfCookie(): string {\r\n var matches = document.cookie.match(/\\bXSRF-TOKEN=([^\\s;]+)/);\r\n try {\r\n return (matches && decodeURIComponent(matches[1]));\r\n } catch (decodeError) {\r\n return (\"\");\r\n }\r\n }\r\n\r\n private buildUrlSearchParams(params: any): HttpParams {\r\n var searchParams: HttpParams = new HttpParams();\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n searchParams = searchParams.set(key, value.toString())\r\n }\r\n }\r\n return searchParams;\r\n }\r\n\r\n private interpolateUrl(options: ApiGatewayOptions): ApiGatewayOptions {\r\n // Note - assumes there are no unnecessary repeating slashes in the Url.\r\n\r\n options.url = options.url.replace(\r\n /:([a-zA-Z]+[\\w-]*)/g,\r\n ($0, token) => {\r\n // Try to move matching token from the params collection.\r\n if (options.params.hasOwnProperty(token)) {\r\n return (this.extractValue(options.params, token));\r\n }\r\n // Try to move matching token from the data collection.\r\n if (options.data.hasOwnProperty(token)) {\r\n return (this.extractValue(options.data, token));\r\n }\r\n // If a matching value couldn't be found, just replace\r\n // the token with the empty string.\r\n return (\"\");\r\n }\r\n );\r\n\r\n // Clean up any trailing slashes.\r\n options.url = options.url.replace(/\\/+$/g, '');\r\n\r\n return options;\r\n }\r\n\r\n //private unwrapHttpError(error: any): any {\r\n // try {\r\n // return (error.json());\r\n // } catch (jsonError) {\r\n // return ({\r\n // code: -1,\r\n // message: 'An unexpected error occurred.'\r\n // });\r\n // }\r\n //}\r\n\r\n //private unwrapHttpValue(value: HttpResponse): any {\r\n // return (value.json());\r\n //}\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\n\r\n@Injectable()\r\nexport class DownloadFileService {\r\n\r\n constructor(private globals: AppGlobalsComponent) {}\r\n\r\n public downloadFileFromStream(fileData: any, fileName: string, fileType?: string){\r\n let blob;\r\n\r\n const nav = window.navigator as any;\r\n if (nav && nav.msSaveBlob) {\r\n blob = new Blob([fileData]);\r\n nav.msSaveBlob(blob, fileName);\r\n }\r\n else {\r\n if (fileType != null) {\r\n blob = new Blob([fileData], { type: fileType });\r\n } else {\r\n blob = new Blob([fileData]);\r\n }\r\n let url = window.URL.createObjectURL(blob);\r\n let a = document.createElement('a');\r\n a.setAttribute('style', 'display:none;');\r\n document.body.appendChild(a);\r\n a.href = url;\r\n a.setAttribute('download', fileName);\r\n a.click();\r\n }\r\n }\r\n}\r\n","import { Injectable, EventEmitter } from '@angular/core';\r\nimport { Observable, of } from 'rxjs'\r\nimport { map } from 'rxjs/operators';\r\nimport { ApiGatewayService } from './api-gateway.service';\r\nimport { Configuration } from '../../app.configuration';\r\n\r\nimport { Counterparty } from '../../administration/counterparty-users/counterparty-users.model'\r\nimport { CounterpartyFilterModel } from '../../billing/billing-account.model'\r\nimport config from 'config';\r\n\r\n@Injectable()\r\nexport class LoggedInUserService {\r\n // Logged in user data\r\n private _activeCounterpartiesForPortalAdmin: Counterparty[];\r\n get activeCounterpartiesForPortalAdmin(): Counterparty[] {\r\n return this._activeCounterpartiesForPortalAdmin;\r\n }\r\n set activeCounterpartiesForPortalAdmin(counterparties: Counterparty[]) {\r\n this.isPortalAdmin() ?\r\n this._activeCounterpartiesForPortalAdmin = counterparties\r\n : this._activeCounterpartiesForPortalAdmin = [];\r\n }\r\n public activeCounterparties: Counterparty[];\r\n public userLoadedEvent: EventEmitter = new EventEmitter();\r\n public isCounterPartyActiveDataLoaded: boolean;\r\n private loggedInUser: IUserData;\r\n private impersonatedUser: IUserData;\r\n public isImpersonate: boolean = false;\r\n public impersonateUsername: string;\r\n public impersonateEmail: string;\r\n public impersonateTab: boolean;\r\n public enabledReports?: any[] = null;\r\n\r\n constructor(private apiGateway: ApiGatewayService) { }\r\n\r\n public getLoggedInUser(): IUserData {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser;\r\n }\r\n return this.loggedInUser;\r\n }\r\n\r\n public getImpersonateAndLoggedInUser(){\r\n let users: any;\r\n if (this.loggedInUser != null && this.impersonatedUser != null) {\r\n users = {\r\n 'impersonated': this.impersonatedUser,\r\n 'loggedInUser': this.loggedInUser\r\n }\r\n }\r\n return users;\r\n }\r\n\r\n public async impersonate(userId: string) {\r\n this.isImpersonate = true;\r\n this.resetImpersonatedProfile();\r\n await this.getImpersonateProfile(userId);\r\n }\r\n\r\n public resetImpersonatedProfile() {\r\n this.impersonatedUser = undefined;\r\n }\r\n\r\n public getLoggedInUserActiveCounterpartyIds(): number[] {\r\n let counterpartyIds: number[] = [];\r\n\r\n if (this.isImpersonate) {\r\n this.impersonatedUser.counterparties.forEach(cp => {\r\n counterpartyIds.push(cp.counterpartyId);\r\n });\r\n }\r\n else {\r\n this.loggedInUser.counterparties.forEach(cp => {\r\n counterpartyIds.push(cp.counterpartyId);\r\n });\r\n }\r\n return counterpartyIds;\r\n }\r\n\r\n /**\r\n * Get counterparties by role (Or all if Portal Admin or 'ALL COUNTERPARTIES' is selected).\r\n * @param role \r\n */\r\n public getUserCounterpartyIdsWithRole(role: string): CounterpartyFilterModel[] {\r\n let counterparties: CounterpartyFilterModel[] = [];\r\n let currentCounterparties = this.getLoggedInUserActiveCounterpartyIds();\r\n if (this.isPortalAdmin()) {\r\n counterparties = this.activeCounterparties.map(x => new CounterpartyFilterModel(x.counterpartyId, null));\r\n }\r\n else if(currentCounterparties.some(x => x == ALL_COUNTERPARTIES_COUNTERPARTY_ID)\r\n &&\r\n (this.isImpersonate &&\r\n this.impersonatedUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) &&\r\n this.impersonatedUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID).counterpartyRoles.some(x => x.roleName == role)\r\n ||\r\n (!this.isImpersonate &&\r\n this.loggedInUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) &&\r\n this.loggedInUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID).counterpartyRoles.some(x => x.roleName == role)))){\r\n counterparties = this.activeCounterparties.map(x => new CounterpartyFilterModel(x.counterpartyId, null));\r\n }\r\n else {\r\n if (this.isImpersonate) {\r\n this.impersonatedUser.counterparties.forEach(cp => {\r\n if (cp.counterpartyRoles.find(x => x.roleName === role) !== undefined) {\r\n counterparties.push(new CounterpartyFilterModel(cp.counterpartyId, cp.customerPoints));\r\n }\r\n });\r\n }\r\n else {\r\n this.loggedInUser.counterparties.forEach(cp => {\r\n if (cp.counterpartyRoles.find(x => x.roleName === role) !== undefined) {\r\n counterparties.push(new CounterpartyFilterModel(cp.counterpartyId, cp.customerPoints));\r\n }\r\n });\r\n }\r\n }\r\n return counterparties;\r\n }\r\n\r\n public getUserCounterpartyIdsArrayWithRole(role: string): number[] {\r\n let counterpartyIds: number[] = [];\r\n let currentCounterparties = this.getLoggedInUserActiveCounterpartyIds();\r\n if (this.isPortalAdmin() || currentCounterparties.some(x => x == ALL_COUNTERPARTIES_COUNTERPARTY_ID)) {\r\n counterpartyIds = this.activeCounterparties.map(x => x.counterpartyId);\r\n } else {\r\n if (this.isImpersonate) {\r\n this.impersonatedUser.counterparties.forEach(cp => {\r\n if (cp.counterpartyRoles.find(x => x.roleName === role) !== undefined) {\r\n counterpartyIds.push(cp.counterpartyId);\r\n }\r\n });\r\n }\r\n else {\r\n this.loggedInUser.counterparties.forEach(cp => {\r\n if (cp.counterpartyRoles.find(x => x.roleName === role) !== undefined) {\r\n counterpartyIds.push(cp.counterpartyId);\r\n }\r\n });\r\n }\r\n }\r\n return counterpartyIds;\r\n }\r\n\r\n /**\r\n * Return logged in user and assign activeCounterparties to assigned counterparties.\r\n * Emits a userLoadedEvent.\r\n */\r\n public getLoggedInUserProfile() {\r\n return new Promise((resolve, reject) => {\r\n if (this.loggedInUser) {\r\n resolve(true);\r\n } else {\r\n let userAccountDetailsUrl: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/Profile';\r\n this.apiGateway.get(userAccountDetailsUrl, null)\r\n .subscribe(response => {\r\n let data: any = response;\r\n this.loggedInUser = data;\r\n this.getCounterpartiesByLoggedInUserId().subscribe(counterparties => {\r\n let cpData: any = counterparties;\r\n this.activeCounterparties = cpData;\r\n this.userLoadedEvent.emit(data);\r\n resolve(true);\r\n })\r\n\r\n });\r\n }\r\n });\r\n }\r\n\r\n public getImpersonateProfile(userId: string) {\r\n return new Promise((resolve, reject) => {\r\n if (this.impersonatedUser) {\r\n resolve(true);\r\n } else {\r\n let userAccountDetailsUrl: string = PORTAL_IDENTITY_PATH + 'api/UserInfo/Profile?userGUID=' + userId;\r\n this.apiGateway.get(userAccountDetailsUrl, null)\r\n .subscribe(response => {\r\n let data: any = response;\r\n this.impersonatedUser = data;\r\n this.getCounterpartiesByLoggedInUserId().subscribe(counterparties => {\r\n let cpData: any = counterparties;\r\n this.activeCounterparties = cpData;\r\n this.userLoadedEvent.emit(data);\r\n resolve(true);\r\n })\r\n\r\n });\r\n }\r\n });\r\n }\r\n\r\n public getCounterpartiesByLoggedInUserId(role: string = undefined) {\r\n if (this.isPortalAdmin() || (this.isAllCounterparties() && role == undefined) ||\r\n (role != undefined && this.isAllCounterparties(role))) {\r\n return this.getAllCounterpartiesAndCustomerPoints();\r\n }\r\n //This returns impersonated user's counterparties if isImpersonate is true\r\n let cpIds = this.getLoggedInUser().counterparties.map(cp => { return cp.counterpartyId });\r\n let url = PORTAL_API_PATH + 'Counterparty/GetCounterpartiesByIds';\r\n return this.apiGateway.post(url, {}, cpIds);\r\n }\r\n\r\n public isInternal() {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser !== undefined && this.impersonatedUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.impersonatedUser.roles !== null &&\r\n (\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.INTERNAL));\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.INTERNAL));\r\n }\r\n\r\n public isPortalAdmin() {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser !== undefined && this.impersonatedUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.impersonatedUser.roles !== null &&\r\n (\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.INTERNAL) &&\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN));\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.INTERNAL) &&\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN));\r\n }\r\n\r\n public hasReportsRole() {\r\n if (this.isImpersonate) {\r\n if (this.impersonatedUser == undefined || this.impersonatedUser == null ||\r\n this.impersonatedUser.roles == undefined || this.impersonatedUser.roles == null) {\r\n return false;\r\n }\r\n \r\n let userReports = ENABLED_REPORTS.filter(r => this.loggedInUser.roles.some(x => x === r.ImpersonateClaim) == true);\r\n let impersonatedUserReports = ENABLED_REPORTS.filter(r => this.impersonatedUser.roles.some(x => x === r.Claim) == true);\r\n let combinedReports = userReports.filter(r => this.impersonatedUser.roles.some(x => x === r.Claim) == true);\r\n\r\n return (this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) && impersonatedUserReports.length > 0) ||\r\n combinedReports.length > 0;\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n ENABLED_REPORTS.some(r => this.loggedInUser.roles.some(x => x === r.Claim));\r\n }\r\n\r\n public hasDynamicSchedulingRole() {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser !== undefined && this.impersonatedUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.impersonatedUser.roles !== null &&\r\n (this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.SCHEDULER)) &&\r\n (this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.IMPERSONATE_SCHEDULER));\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.SCHEDULER));\r\n }\r\n\r\n public hasBillingRole() {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser !== undefined && this.impersonatedUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.impersonatedUser.roles !== null &&\r\n (\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.COUNTERPARTY_ADMIN) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.BILLING_DATA_VIEW) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.BILLING_SETTLEMENTS) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.INVOICE_SUMMARY_REPORT) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.BANKING_INFORMATION_FORMS)) &&\r\n (this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.IMPERSONATE_BILLING)\r\n );\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.COUNTERPARTY_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.BILLING_DATA_VIEW) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.BILLING_SETTLEMENTS) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.INVOICE_SUMMARY_REPORT) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.BANKING_INFORMATION_FORMS)\r\n );\r\n }\r\n\r\n public hasAdminRole() {\r\n if (this.isImpersonate) {\r\n return this.impersonatedUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.impersonatedUser.roles.some(x => x === Configuration.USER_ROLES.COUNTERPARTY_ADMIN)\r\n ) &&\r\n (\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.IMPERSONATE_ADMIN)\r\n );\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN) ||\r\n this.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.COUNTERPARTY_ADMIN));\r\n }\r\n\r\n public hasImpersonateRole() {\r\n if (this.isImpersonate) {\r\n if (this.impersonatedUser!= undefined && this.impersonatedUser.roles != undefined) {\r\n return this.impersonatedUser !== undefined && this.impersonatedUser.roles !== undefined &&\r\n this.impersonatedUser !== null && this.impersonatedUser.roles !== null &&\r\n (\r\n this.impersonatedUser.roles.some(x => x.includes('Impersonate'))\r\n );\r\n }\r\n return false;\r\n }\r\n return this.loggedInUser !== undefined && this.loggedInUser.roles !== undefined &&\r\n this.loggedInUser !== null && this.loggedInUser.roles !== null &&\r\n (\r\n this.loggedInUser.roles.some(x => x.includes('Impersonate'))\r\n );\r\n }\r\n\r\n public getReportEmbedToken(report: \"monthly\" | \"daily\", isPaginated: boolean): Observable<{ token: string, embedUrl: string, reportId: string }> {\r\n let url = PORTAL_IDENTITY_PATH + 'api/PowerBI/GetEmbedInfo'\r\n if (this.isImpersonate) { url = url +'?userGuid=' + this.impersonatedUser.guid }\r\n return this.apiGateway.get(url, { report: report, isPaginated: isPaginated, isImpersonate: this.isImpersonate })\r\n .pipe(map(response => {\r\n return (response as any) as { token: string, embedUrl: string, reportId: string };\r\n }));\r\n }\r\n\r\n /** Load the Counterpartyactive data from calpine api */\r\n public getAllCounterparties() {\r\n if (this.isPortalAdmin()) {\r\n let counterPartyURL = PORTAL_API_PATH + 'Counterparty/GetAllCounterparty';\r\n return this.apiGateway.get(counterPartyURL, null);\r\n } else {\r\n return of();\r\n }\r\n }\r\n\r\n public isAllCounterparties(role: string = undefined): boolean {\r\n //When a role is added, it will check if ALL COUNTERPARTIES contains specified role\r\n //If no role is added, then it will just check if ALL COUNTERPARTIES was added\r\n if (this.isImpersonate) {\r\n if ((this.impersonatedUser.counterparties.some(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) && role != undefined && \r\n this.impersonatedUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID)\r\n .counterpartyRoles.some(x => x.roleName == role)) ||\r\n (this.impersonatedUser.counterparties.some(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) && role == undefined)) {\r\n return true;\r\n }\r\n }\r\n else {\r\n if ((this.loggedInUser.counterparties.some(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) && role != undefined &&\r\n this.loggedInUser.counterparties.find(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID)\r\n .counterpartyRoles.some(x => x.roleName == role)) ||\r\n (this.loggedInUser.counterparties.some(x => x.counterpartyId == ALL_COUNTERPARTIES_COUNTERPARTY_ID) && role == undefined)) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n public getAllCounterpartiesAndCustomerPoints(): Observable {\r\n //if (this.isPortalAdmin()) {\r\n let counterpartyAndCustomerPointsURL =\r\n PORTAL_API_PATH + 'Counterparty/GetAllCounterpartiesAndCustomerPoints';\r\n return this.apiGateway.get(counterpartyAndCustomerPointsURL, null);\r\n //} else {\r\n // return Observable.of();\r\n //}\r\n }\r\n}\r\n\r\nexport interface IUserData { // must be in synch with NES.IdentityServer.Models.UserProfile\r\n guid: any; // Guid\r\n key: number;\r\n email: string;\r\n phone: string;\r\n salutation: string;\r\n firstName: string;\r\n lastName: string;\r\n isLoginAllowed: boolean;\r\n isAccountVerified: boolean;\r\n roles: string[];\r\n counterparties: IUserCounterparty[];\r\n counterpartyRoles: number[];\r\n newEmail: string;\r\n}\r\n\r\nexport interface IUserCounterparty {\r\n counterpartyId: number;\r\n counterpartyRoles: IUserCounterpartyRole[];\r\n customerPoints: number[];\r\n}\r\nexport interface IUserCounterpartyRole {\r\n roleId: number;\r\n roleName: string;\r\n}\r\n","import { Injectable } from \"@angular/core\";\r\nimport * as _ from 'lodash';\r\n\r\nimport { IUserData } from '../../shared/services/logged-in-user.service';\r\n\r\n@Injectable()\r\nexport class UserRole {\r\n getAllRolesFromUserProfile(userProfile: IUserData): string[] {\r\n // grab the global roles and then loop through the user's counterparties to grab those roles too\r\n var roles = userProfile.roles;\r\n userProfile.counterparties.forEach(cp => {\r\n cp.counterpartyRoles.forEach(cpr => {\r\n if (roles.indexOf(cpr.roleName) == -1) {\r\n roles.push(cpr.roleName);\r\n }\r\n });\r\n });\r\n\r\n return roles;\r\n }\r\n\r\n matchRolesAndRolesConditions(userRoles: Array, expectedRolesConditions: string): boolean {\r\n // userRoles = \"R1\", R2\", \"R3\" ; expectedRolesConditions = \"R1&&R2||R2&&R4\"\r\n if (!userRoles) { return false; }\r\n if (!expectedRolesConditions) { return true; }\r\n\r\n let expectedRolesWithAnd: Array = expectedRolesConditions.split('||');\r\n\r\n let matches = expectedRolesWithAnd.some((expected, i) => {\r\n let expectedRoles: Array = expectedRolesWithAnd[i].split('&&');\r\n return this.userRolesContainsExpectedRoles(userRoles, expectedRoles);\r\n\r\n });\r\n\r\n return matches;\r\n }\r\n\r\n userRolesContainsExpectedRoles(userRoles: Array, expectedRoles: Array): boolean {\r\n // Expected input\r\n // array1 = \"R1\", R2\", \"R3\" ; array2 = \"R1\", R2\"\r\n let containsExpected = expectedRoles.some(expected => {\r\n return _.includes(userRoles, expected);\r\n });\r\n\r\n return containsExpected;\r\n }\r\n\r\n}","import { Directive, ElementRef, EventEmitter, Input, HostListener, OnInit, OnDestroy} from '@angular/core';\r\n\r\n@Directive({ selector: '[calpine-autofocus]' }) \r\nexport class Autofocus implements OnInit {\r\n private element: HTMLElement;\r\n\r\n constructor(public el: ElementRef) {\r\n this.element = el.nativeElement;\r\n }\r\n\r\n ngOnInit() {\r\n $(this.element).focus(); \r\n }\r\n}","import { Directive, Input, ElementRef, OnInit, HostListener } from '@angular/core';\r\n\r\n@Directive({ selector: '[horizontal-scroll]' })\r\nexport class FixedElementHorizontalScrollDirective implements OnInit {\r\n\r\n @HostListener('scroll', ['$event']) onElementScroll() {\r\n this.scrollDistance = this.element.scrollLeft;\r\n this.scrollFixedElement();\r\n }\r\n\r\n @Input('fixedElementStartPosition') fixedElementStartPosition: number = 0;\r\n @Input('fixedElementID') fixedElementID: string;\r\n\r\n public element: HTMLElement;\r\n public scrollDistance: number;\r\n\r\n constructor(public el: ElementRef) { }\r\n\r\n public scrollFixedElement() {\r\n $('#' + this.fixedElementID).css({\r\n 'left': this.fixedElementStartPosition - this.scrollDistance\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n this.element = this.el.nativeElement;\r\n }\r\n\r\n}","import { Injectable } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\n\r\nimport { ApiGatewayService } from '../services/api-gateway.service';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { AppGlobalsComponent } from '../app-globals.component';\r\nimport type { IPopupMessageOptions } from '../modal/popup-message-options.component';\r\n\r\n@Injectable()\r\nexport class HttpErrorHandlerService {\r\n constructor(private apiService: ApiGatewayService,\r\n private securityService: AuthenticationService,\r\n private router: Router,\r\n private globals: AppGlobalsComponent\r\n ) {\r\n\r\n this.apiService.errors$.subscribe(\r\n (value: any) => {\r\n let modalData: IPopupMessageOptions;\r\n switch (value.status) {\r\n case 400:\r\n break;\r\n // 401 - Unauthorized from the server will come from IdentityServer. \r\n // User should be logged out if not authorized. Unauthorized is likely due to a malformed or expired token.\r\n case 401: \r\n this.securityService.signOut();\r\n break;\r\n case 403:\r\n this.router.navigate(['/forbidden']);\r\n break;\r\n case 404:\r\n this.router.navigate(['/not-found']);\r\n break;\r\n case 500:\r\n modalData = {\r\n headerText: 'Internal Server Error',\r\n bodyText: \"Sorry, something went wrong.
If problem persists, please contact support at \" + SUPPORT_EMAIL + \" .\",\r\n buttonText: 'Ok',\r\n show: true,\r\n iconName: 'fa-warning'\r\n };\r\n this.globals.TogglePopupService.next(modalData);\r\n break;\r\n default:\r\n break;\r\n }\r\n });\r\n }\r\n}","import { ErrorHandler } from '@angular/core';\r\n\r\n/**\r\n * Provides a hook for centralized exception handling\r\n */\r\nexport class CalpineExceptionHandlerService implements ErrorHandler {\r\n constructor() { }\r\n\r\n handleError(error) {\r\n console.log(error);\r\n }\r\n}\r\n","import { Directive, Input, ElementRef, OnInit } from '@angular/core';\r\nimport { UserRole } from '../services/user-role.service';\r\nimport { LoggedInUserService, IUserData } from '../../shared/services/logged-in-user.service';\r\n\r\n@Directive({\r\n selector: '[requiredRoles]'\r\n})\r\n\r\nexport class UserRoleLinkCheck implements OnInit {\r\n\r\n constructor(private loggedInUserService: LoggedInUserService,\r\n private _elementRef: ElementRef,\r\n private userRole: UserRole) {\r\n }\r\n\r\n @Input('requiredRoles') accessRoles: string;\r\n\r\n\r\n ngOnInit() {\r\n let el: HTMLElement = this._elementRef.nativeElement;\r\n if (this.loggedInUserService === undefined || this.loggedInUserService.getLoggedInUser() === undefined) {\r\n el.style.display = 'none';\r\n } else {\r\n let hasAccess: boolean = false;\r\n if (this.loggedInUserService.getLoggedInUser() != null) {\r\n\r\n let userProfile = this.loggedInUserService.getLoggedInUser();\r\n let roles = this.userRole.getAllRolesFromUserProfile(userProfile);\r\n hasAccess = this.userRole.matchRolesAndRolesConditions(roles, this.accessRoles);\r\n }\r\n if (!hasAccess) {\r\n el.parentNode.removeChild(el);\r\n } else {\r\n el.style.removeProperty('display');\r\n }\r\n }\r\n \r\n this.loggedInUserService.userLoadedEvent.subscribe((userProfile: IUserData) => {\r\n let hasAccess: boolean = false;\r\n if (userProfile != null) {\r\n let roles = this.userRole.getAllRolesFromUserProfile(userProfile);\r\n hasAccess = this.userRole.matchRolesAndRolesConditions(roles, this.accessRoles);\r\n }\r\n let el: HTMLElement = this._elementRef.nativeElement;\r\n if (!hasAccess) {\r\n el.parentNode.removeChild(el);\r\n } else {\r\n el.style.removeProperty('display');\r\n }\r\n })\r\n }\r\n}","import { Component, OnInit, Input } from '@angular/core';\r\nimport { SubNavItem } from './sub-nav.model';\r\nlet styles = String(require('./sub-nav-menu.component.css'));\r\n\r\n@Component({\r\n selector: 'sub-nav-menu',\r\n template: require('./sub-nav-menu.component.html'),\r\n styles: [styles]\r\n})\r\n\r\n\r\nexport class SubNavMenuComponent implements OnInit {\r\n\r\n @Input() firstSubNavName: string;\r\n @Input() secondSubNavName: string;\r\n @Input() subNavRouteDetails: SubNavItem[] = [];\r\n subNavRouteDetailsFiltered: SubNavItem[] = [];\r\n @Input() offsetClass: string = 'col-md-offset-0';\r\n @Input() activeClass: string = 'activeSubNav';\r\n @Input() seperatorClass: string = 'subNavSeperator';\r\n\r\n constructor() { }\r\n\r\n ngOnInit() {\r\n this.subNavRouteDetailsFiltered = this.subNavRouteDetails.filter(a => a.isVisible || a.isVisible === undefined);\r\n }\r\n\r\n /*\r\n How to Use:\r\n\r\n Add below variable in your component and initialize it like below in constructor with appropriate values.\r\n\r\n in .ts:\r\n subNavRouteDetails: any[] = [];\r\n firstSubNavName: string;\r\n\r\n constructor() {\r\n this.firstSubNavName = \"SubNav1\";\r\n\r\n this.subNavRouteDetails = [\r\n { \"routerText\": this.firstSubNavName, \"routerLink\": \"RouterLink_PathForSubNav1\" },\r\n { \"routerText\": \"SubNav2\", \"routerLink\": \"RouterLink_PathForSubNav2\" },\r\n { \"routerText\": \"SubNav3\", \"routerLink\": \"../RouterLink_PathForSubNav3\" },\r\n ];\r\n }\r\n **Optional\r\n If a different css is desired, pass it as input similar to firstSubNavName, and add the css to sub-nav-menu.component.css\r\n [activeClass]='\"activeRedSubNav\"'\r\n @Input() activeClass: string = \"activeSubNav\";\r\n @Input() seperatorClass: string = \"subNavSeperator\"; \r\n\r\n In .Html\r\n \r\n
\r\n \r\n
\r\n */\r\n\r\n}","import { Routes, RouterModule } from '@angular/router';\r\n\r\nimport { SubNavMenuComponent } from './sub-nav-menu.component';\r\n\r\nconst subNavMenuRoutes: Routes = [\r\n { path: 'sub-nav-menu', component: SubNavMenuComponent },\r\n];\r\n\r\nexport const subNavMenuRouting = RouterModule.forChild(subNavMenuRoutes);","import { Component, Input, OnInit } from '@angular/core';\r\nimport { Router, ActivatedRoute, NavigationEnd } from '@angular/router';\r\nimport { filter } from 'rxjs/operators';\r\n\r\nlet styles = String(require('./breadcrumb.component.css'));\r\n@Component({\r\n selector: 'breadcrumb',\r\n template: require('./breadcrumb.component.html'),\r\n styles: [styles]\r\n})\r\n\r\nexport class BreadCrumbComponent implements OnInit {\r\n breadcrumbs: Array;\r\n\r\n constructor(private router: Router, private route: ActivatedRoute) { }\r\n ngOnInit() {\r\n this.router.events.pipe(\r\n filter(event => event instanceof NavigationEnd)\r\n ).subscribe(event => { // note, we don't use event\r\n this.breadcrumbs = [];\r\n //Adding home every where irrespective of actual path\r\n this.breadcrumbs.push({\r\n label: 'Home',\r\n url: ''\r\n });\r\n\r\n let currentRoute = this.route.root,\r\n url = '';\r\n do {\r\n let childrenRoutes = currentRoute.children;\r\n currentRoute = null;\r\n childrenRoutes.forEach(route => {\r\n if (route.outlet === 'primary') {\r\n let routeSnapshot = route.snapshot;\r\n url += '/' + routeSnapshot.url.map(segment => segment.path).join('/');\r\n let routeData: any = route.snapshot.data;\r\n if (routeData.title != 'Home' && routeData.title != undefined) {//Home already added above\r\n this.breadcrumbs.push({\r\n label: routeData.title,\r\n url: url\r\n });\r\n }\r\n currentRoute = route;\r\n }\r\n })\r\n } while (currentRoute);\r\n\r\n });\r\n }\r\n}\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'http-code-exception-button',\r\n template: require('./http-code-exception-button.component.html')\r\n})\r\nexport class HttpCodeExceptionButtonComponent {\r\n\r\n @Input() hideHomeButton: boolean;\r\n @Input() message: string = \"Please select an option below.\";\r\n\r\n constructor(){}\r\n}","import { NgModule, ModuleWithProviders, ErrorHandler } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { HttpClientModule } from '@angular/common/http';\r\nimport { NgxPaginationModule } from 'ngx-pagination';\r\n\r\nimport { Tooltip } from './directives/tooltip.component';\r\nimport { Autofocus } from './directives/autofocus.directive';\r\nimport { FixedElementHorizontalScrollDirective } from './directives/fixed-element-horizontal-scroll.directive';\r\nimport { GridService } from './grid/grid.service';\r\n\r\nimport { AuthenticationService } from '../authentication/authentication.service';\r\nimport { Configuration } from '../app.configuration';\r\nimport { ApiGatewayService } from '../shared/services/api-gateway.service';\r\nimport { HttpErrorHandlerService } from '../shared/error/http-error-handler.service';\r\nimport { CalpineExceptionHandlerService } from '../shared/error/exception-handler.service';\r\nimport { AppGlobalsComponent } from '../shared/app-globals.component';\r\n\r\nimport { UserRoleLinkCheck } from '../shared/directives/user-role-link-check.directive';\r\nimport { subNavMenuRouting } from './nav-menu/sub-nav-menu/sub-nav-menu.routing';\r\nimport { SubNavMenuComponent } from './nav-menu/sub-nav-menu/sub-nav-menu.component';\r\nimport { BreadCrumbComponent } from './breadcrumb/breadcrumb.component';\r\nimport { CalpineAgGridPagerComponent } from './pager/pager.component';\r\nimport { UserImpersonateViewButtonsComponent } from './impersonate-button/user-impersonate-view-buttons.component'\r\nimport { UsersEditDeleteButtonComponent } from './edit-delete-button/users-edit-delete-button.component'\r\n\r\nimport { CanActivateAuthGuard, DynamicSchedulingAuthGuard, CanLoadAuthGuard } from '../authentication/auth-guard.service';\r\nimport { UnauthorizedAccessComponent } from '../shared/error/unauthorized-access.component';\r\nimport { ForbiddenComponent } from '../shared/error/forbidden.component';\r\nimport { NotFoundComponent } from '../shared/error/not-found.component';\r\nimport { HttpCodeExceptionButtonComponent } from '../shared/error/http-code-exception-button.component';\r\nimport { UserRole } from '../shared/services/user-role.service';\r\n\r\n\r\nimport { DownloadFileService } from '../shared/services/download-file.service';\r\nimport { DocumentDownloadListComponent } from './document-download/document-download-list.component';\r\nimport { InvoiceDownloadErrorDialogComponent } from '../billing/invoice-n-payment/invoice-download-error-dialog.component';\r\n\r\nimport { CounterpartyUsersAddEditDialogComponent } from '../administration/counterparty-users/counterparty-users-add-edit-dialog.component';\r\nimport { Typeahead } from '../shared/typeahead/cp-typeahead.component';\r\nimport { CounterpartyUsersRemoveDialogComponent } from '../administration/counterparty-users/counterparty-users-remove-dialog.component';\r\nimport { UsersRemoveDialogComponent } from '../administration/users/users-remove-dialog.component';\r\nimport { SendWelcomeEmailDialogComponent } from '../administration/counterparty-users/send-welcome-email-dialog.component';\r\nimport { CounterpartyUsersGroupedRowComponent } from '../administration/counterparty-users/counterparty-users-grouped-row.component';\r\nimport { CounterpartyUserEditDeleteButtonComponent } from '../administration/counterparty-users/counterparty-user-edit-delete-button.component';\r\nimport { SendWelcomeEmailHeaderComponent } from '../administration/counterparty-users/send-welcome-email-header-button.component';\r\nimport { CounterpartyUsersRolesComponent } from '../administration/counterparty-users/counterparty-users-roles.component';\r\nimport { AddNewUserHeaderComponent } from '../administration/users/add-new-user-header-button.component';\r\nimport { MultiselectDropdownModule } from '../shared/multiselect-dropdown/multiselect-dropdown';\r\nimport { AgGridModule } from 'ag-grid-angular';\r\nimport { UsersComponent } from '../administration/users/users.component';\r\nimport { CounterpartyUsersComponent } from '../administration/counterparty-users/counterparty-users.component';\r\nimport { DatePickerPopUpComponent } from './datepicker/datepicker-popup.component';\r\nimport { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';\r\nimport { DateFilterComponent } from './grid/grid.date-filter.component';\r\nimport { BooleanFilterComponent } from './grid/grid.boolean-filter.component';\r\nimport { NgbDateCustomParserFormatter } from './datepicker/ngb-datepicker-custom-formatter';\r\n\r\n@NgModule({\r\n imports: [\r\n CommonModule, \r\n HttpClientModule,\r\n subNavMenuRouting, \r\n NgxPaginationModule,\r\n FormsModule,\r\n MultiselectDropdownModule,\r\n AgGridModule,\r\n NgbDatepickerModule,\r\n ],\r\n\r\n declarations: [\r\n Tooltip, \r\n Autofocus, \r\n UserRoleLinkCheck, \r\n SubNavMenuComponent, \r\n UnauthorizedAccessComponent,\r\n BreadCrumbComponent, \r\n ForbiddenComponent, \r\n NotFoundComponent, \r\n HttpCodeExceptionButtonComponent, \r\n FixedElementHorizontalScrollDirective,\r\n CalpineAgGridPagerComponent,\r\n DocumentDownloadListComponent,\r\n InvoiceDownloadErrorDialogComponent,\r\n UserImpersonateViewButtonsComponent,\r\n UsersEditDeleteButtonComponent,\r\n CounterpartyUsersAddEditDialogComponent,\r\n Typeahead,\r\n CounterpartyUsersRemoveDialogComponent,\r\n UsersRemoveDialogComponent,\r\n SendWelcomeEmailDialogComponent,\r\n CounterpartyUsersGroupedRowComponent,\r\n CounterpartyUserEditDeleteButtonComponent,\r\n SendWelcomeEmailHeaderComponent,\r\n CounterpartyUsersRolesComponent,\r\n AddNewUserHeaderComponent,\r\n UsersComponent,\r\n CounterpartyUsersComponent,\r\n DatePickerPopUpComponent,\r\n DateFilterComponent,\r\n BooleanFilterComponent\r\n ],\r\n \r\n exports: [ \r\n CommonModule, \r\n FormsModule, \r\n HttpClientModule, \r\n Tooltip, \r\n Autofocus, \r\n UserRoleLinkCheck, \r\n SubNavMenuComponent,\r\n UnauthorizedAccessComponent, \r\n BreadCrumbComponent, \r\n ForbiddenComponent, \r\n NotFoundComponent, \r\n HttpCodeExceptionButtonComponent, \r\n NgxPaginationModule, \r\n FixedElementHorizontalScrollDirective,\r\n CalpineAgGridPagerComponent,\r\n DocumentDownloadListComponent,\r\n InvoiceDownloadErrorDialogComponent,\r\n CounterpartyUsersAddEditDialogComponent,\r\n Typeahead,\r\n CounterpartyUsersRemoveDialogComponent,\r\n UsersRemoveDialogComponent,\r\n SendWelcomeEmailDialogComponent,\r\n CounterpartyUsersGroupedRowComponent,\r\n CounterpartyUserEditDeleteButtonComponent,\r\n SendWelcomeEmailHeaderComponent,\r\n CounterpartyUsersRolesComponent,\r\n AddNewUserHeaderComponent,\r\n DatePickerPopUpComponent,\r\n DateFilterComponent,\r\n BooleanFilterComponent\r\n ],\r\n //entryComponents: [\r\n // UserImpersonateViewButtonsComponent,\r\n // UsersEditDeleteButtonComponent,\r\n // SendWelcomeEmailDialogComponent,\r\n // CounterpartyUsersAddEditDialogComponent,\r\n // CounterpartyUsersRemoveDialogComponent,\r\n // InvoiceDownloadErrorDialogComponent,\r\n // DocumentDownloadListComponent,\r\n //]\r\n})\r\n\r\nexport class SharedModule {\r\n static forRoot(): ModuleWithProviders {\r\n return {\r\n ngModule: SharedModule,\r\n providers: [\r\n HttpErrorHandlerService,\r\n { provide: ErrorHandler, useClass: CalpineExceptionHandlerService },\r\n NgbDateCustomParserFormatter,\r\n AuthenticationService,\r\n ApiGatewayService,\r\n Configuration,\r\n AppGlobalsComponent,\r\n CanActivateAuthGuard,\r\n DynamicSchedulingAuthGuard,\r\n CanLoadAuthGuard,\r\n UserRole,\r\n GridService,\r\n UserImpersonateViewButtonsComponent,\r\n UsersEditDeleteButtonComponent,\r\n DownloadFileService,\r\n ]\r\n };\r\n }\r\n}\r\n","import { Component, Input, Output, EventEmitter, ViewChild, OnInit, forwardRef } from '@angular/core';\r\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\r\n\r\nconst noop = () => {\r\n};\r\n\r\nexport const TYPEAHEAD_CONTROL_VALUE_ACCESSOR:any = {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => Typeahead),\r\n multi: true\r\n};\r\n\r\n\r\n@Component({\r\n selector: 'cp-typeahead',\r\n template: `\r\n
\r\n\r\n \r\n\r\n \r\n\r\n
\r\n\r\n
    \r\n\r\n
  • {{ suggestion[displayProperty] }}
  • \r\n\r\n
\r\n\r\n
\r\n\r\n
\r\n `,\r\n styles: [`\r\n .typeahead {\r\n position: relative;\r\n width: 100%;\r\n text-align: left;\r\n vertical-align: top;\r\n padding-bottom: 2.5em;\r\n }\r\n\r\n .typeahead-input {\r\n border-color: transparent;\r\n position: absolute;\r\n z-index: 10;\r\n background-color: transparent;\r\n background-repeat: no-repeat;\r\n background-position: right 10px;\r\n background-size: 28px 18px;\r\n }\r\n\r\n .typeahead-input-has-selection {\r\n background-color: #f5f5f5;\r\n border: 1px solid #4c4845;\r\n color: #008fca;\r\n }\r\n\r\n .typeahead-typeahead {\r\n color: rgb(128, 128, 128);\r\n position: absolute;\r\n z-index: 5;\r\n text-align: start;\r\n background-color: rgb(255, 255, 255);\r\n }\r\n\r\n .typeahead-suggestions {\r\n position: absolute;\r\n top: 42px;\r\n overflow-y: auto;\r\n color: #666666;\r\n border-radius: 3px;\r\n padding: 0;\r\n background-color: #f5f5f5;\r\n width: 100%;\r\n max-height: 18em !important;\r\n border: 1px solid #e0e0e0;\r\n z-index: 100;\r\n }\r\n\r\n .typeahead-suggestions ul {\r\n list-style-type: none;\r\n padding-left: 0;\r\n margin-top: 3px;\r\n }\r\n\r\n .typeahead-suggestions ul li {\r\n padding: 6px !important;\r\n font-size: 0.9em;\r\n border-bottom: 1px solid #e0e0e0;\r\n }\r\n\r\n .typeahead-suggestion-active {\r\n background-color: #008fca;\r\n color: #ffffff;\r\n }\r\n `],\r\n providers: [TYPEAHEAD_CONTROL_VALUE_ACCESSOR]\r\n})\r\nexport class Typeahead implements OnInit, ControlValueAccessor {\r\n /**\r\n * The complete list of items.\r\n */\r\n @Input() list:any[] = [];\r\n\r\n /**\r\n * Input element placeholder text.\r\n */\r\n @Input() placeholder:string = '';\r\n\r\n /**\r\n * The property of a list item that should be used for matching.\r\n */\r\n @Input() searchProperty:string = 'name';\r\n\r\n /**\r\n * The property of a list item that should be displayed.\r\n */\r\n @Input() displayProperty:string = 'name';\r\n\r\n /**\r\n * The maximum number of suggestions to display.\r\n */\r\n @Input() maxSuggestions:number = -1;\r\n\r\n /**\r\n * Event that occurs when a suggestion is selected.\r\n */\r\n @Output() suggestionSelected = new EventEmitter();\r\n\r\n /**\r\n * Handle to the input element.\r\n */\r\n @ViewChild('inputElement') private inputElement:any;\r\n\r\n /**\r\n * The input element's value.\r\n */\r\n private input:string;\r\n\r\n /**\r\n * The typeahead element's value. This element is displayed behind the input element.\r\n */\r\n private typeahead:string;\r\n\r\n /**\r\n * The previously entered input string.\r\n */\r\n private previousInput:string;\r\n\r\n /**\r\n * The filtered list of suggestions.\r\n */\r\n private suggestions:any[] = [];\r\n\r\n /**\r\n * Indicates whether the suggestions are visible.\r\n */\r\n private areSuggestionsVisible:boolean = false;\r\n\r\n /**\r\n * The currently selected suggestion.\r\n */\r\n private selectedSuggestion:any;\r\n\r\n /**\r\n * The active (highlighted) suggestion.\r\n */\r\n private activeSuggestion:any;\r\n\r\n /**\r\n * Indicates whether the control is disabled.\r\n */\r\n private isDisabled:boolean = false;\r\n\r\n /**\r\n * Creates and initializes a new typeahead component.\r\n */\r\n constructor() {\r\n }\r\n\r\n /**\r\n * Implement this interface to execute custom initialization logic after your\r\n * directive's data-bound properties have been initialized.\r\n *\r\n * ngOnInit is called right after the directive's data-bound properties have\r\n * been checked for the first time, and before any of its\r\n * children have been checked. It is invoked only once when the directive is\r\n * instantiated.\r\n */\r\n public ngOnInit() {\r\n }\r\n\r\n /**\r\n * Placeholder for a callback which is later provided by the Control Value Accessor.\r\n */\r\n private onTouchedCallback:() => void = noop;\r\n\r\n /**\r\n * Placeholder for a callback which is later provided by the Control Value Accessor.\r\n */\r\n private onChangeCallback:(_:any) => void = noop;\r\n\r\n /**\r\n * Get accessor.\r\n */\r\n get value():any {\r\n return this.selectedSuggestion;\r\n }\r\n\r\n /**\r\n * Set accessor including call the onchange callback.\r\n */\r\n set value(v:any) {\r\n if (v !== this.selectedSuggestion) {\r\n this.selectSuggestion(v);\r\n this.onChangeCallback(v);\r\n }\r\n }\r\n\r\n /**\r\n * From ControlValueAccessor interface.\r\n */\r\n writeValue(value:any) {\r\n if (value !== this.selectedSuggestion) {\r\n this.selectSuggestion(value);\r\n }\r\n }\r\n\r\n /**\r\n * From ControlValueAccessor interface.\r\n */\r\n registerOnChange(fn:any) {\r\n this.onChangeCallback = fn;\r\n }\r\n\r\n /**\r\n * From ControlValueAccessor interface.\r\n */\r\n registerOnTouched(fn:any) {\r\n this.onTouchedCallback = fn;\r\n }\r\n\r\n /**\r\n * Sets the disabled state of the control.\r\n * @param isDisabled\r\n */\r\n setDisabledState(isDisabled:boolean):void {\r\n this.isDisabled = isDisabled;\r\n }\r\n\r\n /**\r\n * Called when a keydown event is fired on the input element.\r\n */\r\n public inputKeyDown(event:KeyboardEvent) {\r\n if (event.which === 9 || event.keyCode === 9) { // TAB\r\n // Only enter this branch if suggestions are displayed\r\n if (!this.areSuggestionsVisible) {\r\n return;\r\n }\r\n\r\n // Select the first suggestion\r\n this.selectSuggestion(this.activeSuggestion);\r\n\r\n // Remove all but the first suggestion\r\n this.suggestions.splice(1);\r\n\r\n // Hide the suggestions\r\n this.areSuggestionsVisible = false;\r\n\r\n event.preventDefault();\r\n } else if (event.which === 38 || event.keyCode === 38) { // UP\r\n // Find the active suggestion in the list\r\n let activeSuggestionIndex = this.getActiveSuggestionIndex();\r\n\r\n // If not found, then activate the first suggestion\r\n if (activeSuggestionIndex === -1) {\r\n this.setActiveSuggestion(this.suggestions[0]);\r\n return;\r\n }\r\n\r\n if (activeSuggestionIndex === 0) {\r\n // Go to the last suggestion\r\n this.setActiveSuggestion(this.suggestions[this.suggestions.length - 1]);\r\n } else {\r\n // Decrement the suggestion index\r\n this.setActiveSuggestion(this.suggestions[activeSuggestionIndex - 1]);\r\n }\r\n } else if (event.which === 40 || event.keyCode === 40) { // DOWN\r\n // Find the active suggestion in the list\r\n let activeSuggestionIndex = this.getActiveSuggestionIndex();\r\n\r\n // If not found, then activate the first suggestion\r\n if (activeSuggestionIndex === -1) {\r\n this.setActiveSuggestion(this.suggestions[0]);\r\n return;\r\n }\r\n\r\n if (activeSuggestionIndex === (this.suggestions.length - 1)) {\r\n // Go to the first suggestion\r\n this.setActiveSuggestion(this.suggestions[0]);\r\n } else {\r\n // Increment the suggestion index\r\n this.setActiveSuggestion(this.suggestions[activeSuggestionIndex + 1]);\r\n }\r\n } else if ((event.which === 10 || event.which === 13 ||\r\n event.keyCode === 10 || event.keyCode === 13) &&\r\n this.areSuggestionsVisible) { // ENTER\r\n\r\n // Select the active suggestion\r\n this.selectSuggestion(this.activeSuggestion);\r\n\r\n // Hide the suggestions\r\n this.areSuggestionsVisible = false;\r\n\r\n event.preventDefault();\r\n }\r\n }\r\n\r\n /**\r\n * Sets the active (highlighted) suggestion.\r\n */\r\n public setActiveSuggestion(suggestion:any) {\r\n this.activeSuggestion = suggestion;\r\n this.populateTypeahead();\r\n }\r\n\r\n /**\r\n * Gets the index of the active suggestion within the suggestions list.\r\n */\r\n public getActiveSuggestionIndex() {\r\n let activeSuggestionIndex = -1;\r\n if (this.activeSuggestion != null) {\r\n activeSuggestionIndex = this.indexOfObject(this.suggestions, this.searchProperty, this.activeSuggestion[this.searchProperty]);\r\n }\r\n return activeSuggestionIndex;\r\n }\r\n\r\n /**\r\n * Gets the index of an object in a list by matching a property value.\r\n */\r\n public indexOfObject(array:any[], property:string, value:string) {\r\n if (array == null || array.length === 0) return -1;\r\n let index = -1;\r\n for (let i = 0; i < array.length; i++) {\r\n if (array[i][property] != null && array[i][property] === value) {\r\n index = i;\r\n }\r\n }\r\n return index;\r\n }\r\n\r\n /**\r\n * Called when a keyup event is fired on the input element.\r\n */\r\n public inputKeyUp(event:KeyboardEvent) {\r\n // Ignore TAB, UP, and DOWN since they are processed by the keydown handler\r\n if (event.which === 9 || event.keyCode === 9 ||\r\n event.which === 38 || event.keyCode === 38 ||\r\n event.which === 40 || event.keyCode === 40) {\r\n return;\r\n }\r\n\r\n // When the input is cleared\r\n if (this.input == null || this.input.length === 0) {\r\n console.debug(`When the input is cleared`);\r\n this.typeahead = '';\r\n this.populateSuggestions();\r\n return;\r\n }\r\n\r\n // If the suggestion matches the input, then return\r\n if (this.selectedSuggestion != null) {\r\n console.debug(`If the suggestion matches the input, then return`);\r\n if (this.selectedSuggestion[this.displayProperty] === this.input) {\r\n return;\r\n }\r\n }\r\n\r\n // Repopulate the suggestions\r\n this.previousInput = this.input;\r\n this.populateSuggestions();\r\n this.populateTypeahead();\r\n }\r\n\r\n /**\r\n * Called when a focus event is fired on the input element.\r\n */\r\n public inputFocus(event:FocusEvent) {\r\n // If the element is receiving focus and it has a selection, then\r\n // clear the selection. This helps prevent partial editing\r\n if (this.selectedSuggestion != null) {\r\n this.selectSuggestion(null);\r\n this.input = null;\r\n this.populateTypeahead();\r\n }\r\n\r\n // Re-populate the suggestions\r\n this.populateSuggestions();\r\n\r\n // If we have suggestions\r\n if (this.suggestions.length > 0) {\r\n // Set the typeahead to a slice of the first suggestion\r\n this.populateTypeahead();\r\n\r\n // Show/hide the suggestions\r\n this.areSuggestionsVisible = this.suggestions.length > 0;\r\n }\r\n }\r\n\r\n /**\r\n * Called when a blur event is fired on the input element.\r\n */\r\n public inputBlur(event:Event) {\r\n this.typeahead = '';\r\n this.areSuggestionsVisible = false;\r\n this.onTouchedCallback();\r\n }\r\n\r\n /**\r\n * Called when a mouseover event is fired on a suggestion element.\r\n */\r\n public suggestionMouseOver(suggestion:any) {\r\n this.setActiveSuggestion(suggestion);\r\n }\r\n\r\n /**\r\n * Called when a mousedown event is fired on a suggestion element.\r\n */\r\n public suggestionMouseDown(suggestion:any) {\r\n this.selectSuggestion(suggestion);\r\n }\r\n\r\n /**\r\n * Called when a mouseout event is fired on the suggestions element.\r\n */\r\n public suggestionsMouseOut(event:MouseEvent) {\r\n this.setActiveSuggestion(null);\r\n }\r\n\r\n /**\r\n * Fills the suggestions list with items matching the input pattern.\r\n */\r\n public populateSuggestions() {\r\n // Capture variables scoped to the component\r\n let searchProperty = this.searchProperty;\r\n let input = this.input;\r\n\r\n // Confirm that we have a search property\r\n if (searchProperty == null || searchProperty.length === 0) {\r\n console.error('The input attribute `searchProperty` must be provided');\r\n return;\r\n }\r\n\r\n // Handle empty input\r\n if (input == null || input.length === 0) {\r\n // No input yet\r\n this.suggestions = [];\r\n this.areSuggestionsVisible = false;\r\n return;\r\n }\r\n\r\n // Check that we have data\r\n if (this.list == null || this.list.length === 0) return;\r\n\r\n // Filter the suggestions\r\n this.suggestions = this.list.filter(function (item) {\r\n return item[searchProperty].toLowerCase().indexOf(input.toLowerCase()) > -1;\r\n });\r\n\r\n // Limit the suggestions (if applicable)\r\n if (this.maxSuggestions > -1) {\r\n this.suggestions = this.suggestions.slice(0, this.maxSuggestions);\r\n }\r\n\r\n if (this.suggestions.length === 0) {\r\n // No suggestions, so clear the typeahead\r\n this.typeahead = '';\r\n } else {\r\n // Set the typeahead value\r\n this.populateTypeahead();\r\n // Make the first suggestion active\r\n this.activeSuggestion = this.suggestions[0];\r\n }\r\n\r\n // Show/hide the suggestions\r\n this.areSuggestionsVisible = this.suggestions.length > 0;\r\n }\r\n\r\n public populateInput(inputString: string) {\r\n this.inputElement.nativeElement.value = inputString;\r\n }\r\n\r\n /**\r\n * Sets the typeahead input element's value based on the active suggestion.\r\n */\r\n public populateTypeahead() {\r\n // Clear the typeahead when there is no active suggestion\r\n if (this.activeSuggestion == null || !this.areSuggestionsVisible) {\r\n this.typeahead = '';\r\n return;\r\n }\r\n // Set the typeahead value\r\n this.typeahead = this.input + (this.activeSuggestion[this.displayProperty] || '').slice(this.input.length);\r\n }\r\n\r\n /**\r\n * Selects a suggestion.\r\n */\r\n public selectSuggestion(suggestion:any) {\r\n // Set the variable\r\n this.selectedSuggestion = suggestion;\r\n\r\n // Hide the suggestions\r\n this.areSuggestionsVisible = false;\r\n\r\n // Notify the parent component\r\n this.suggestionSelected.emit(suggestion);\r\n\r\n // Other form operations\r\n if (this.selectedSuggestion != null) {\r\n // Set the values of the input elements\r\n this.input = suggestion[this.displayProperty];\r\n this.typeahead = suggestion[this.displayProperty];\r\n\r\n // Blur the input so we can \"lock\" the selected suggestion\r\n this.blurInputElement();\r\n }\r\n }\r\n\r\n /**\r\n * Blurs the input element in order to \"lock\" the value and prevent partial editing.\r\n */\r\n public blurInputElement() {\r\n if (this.inputElement && this.inputElement.nativeElement) {\r\n this.inputElement.nativeElement.blur();\r\n }\r\n }\r\n\r\n /**\r\n * Indicates whether a suggestion has been selected.\r\n */\r\n public hasSelection() {\r\n return this.selectedSuggestion != null;\r\n }\r\n}","import { Component, OnInit } from '@angular/core';\r\nimport { Location } from '@angular/common';\r\n\r\n@Component({\r\n template: ''\r\n})\r\n\r\n// **\r\n// This is a dummy component to handle login where IdentityServer initially redirects the user to a route with \"id_token\" in the url.\r\n// Replace the browser history state with that of the LANDING_PAGE_ROUTE and naivate the user to that page.\r\n// **\r\nexport class IdTokenComponent implements OnInit {\r\n\r\n constructor(private location: Location) { \r\n this.location.replaceState(LANDING_PAGE_ROUTE);\r\n }\r\n\r\n ngOnInit() { }\r\n\r\n} ","import { Routes, RouterModule } from '@angular/router';\r\n\r\nimport { CanActivateAuthGuard, CanLoadAuthGuard } from './authentication/auth-guard.service';\r\nimport { UnauthorizedAccessComponent } from './shared/error/unauthorized-access.component';\r\nimport { ForbiddenComponent } from './shared/error/forbidden.component';\r\nimport { NotFoundComponent } from './shared/error/not-found.component';\r\nimport { IdTokenComponent } from './authentication/id-token.component';\r\nimport { Configuration } from './app.configuration';\r\n\r\n// Lazy loaded modules\r\nconst billingRoutes: Routes = [\r\n { path: Configuration.ROUTE_PATHS.BILLING, loadChildren: ()=> import('./billing/billing.module').then(m=>m.BillingModule), canLoad: [CanLoadAuthGuard] }\r\n]\r\n\r\nconst administrationRoutes: Routes = [\r\n { path: Configuration.ROUTE_PATHS.ADMIN, loadChildren: () => import('./administration/administration.module').then(m => m.AdministrationModule), canLoad: [CanLoadAuthGuard] }\r\n]\r\n\r\nconst reportRoutes: Routes = [\r\n { path: Configuration.ROUTE_PATHS.REPORTS, loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule), canLoad: [CanLoadAuthGuard] }\r\n]\r\n\r\nconst impersonateRoutes: Routes = [\r\n { path: Configuration.ROUTE_PATHS.IMPERSONATE, loadChildren: () => import('./impersonate/impersonate.module').then(m => m.ImpersonateModule), canLoad: [CanLoadAuthGuard] }\r\n]\r\n\r\nconst routes: Routes = [\r\n { path: 'unauthorized-access', component: UnauthorizedAccessComponent },\r\n { path: 'forbidden', component: ForbiddenComponent },\r\n { path: 'not-found', component: NotFoundComponent },\r\n { path: 'id_token', component: IdTokenComponent }, // Dummy route to handle login '/id_token' route.\r\n ...billingRoutes,\r\n ...reportRoutes,\r\n ...administrationRoutes,\r\n ...impersonateRoutes,\r\n { path: '**', component: IdTokenComponent },\r\n];\r\n\r\nexport const APP_ROUTES = RouterModule.forRoot(routes);\r\n","import { Component, ViewEncapsulation } from '@angular/core';\r\nimport { LicenseManager } from 'ag-grid-enterprise';\r\nlet styles = String(require('./app.component.css'));\r\n\r\n@Component({\r\n selector: 'app',\r\n template: `\r\n
\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n `,\r\n styles: [styles]\r\n})\r\n\r\n// Instantiate the HttpErrorHandler and ClientCache when the app starts up\r\nexport class AppComponent {\r\n constructor() { \r\n LicenseManager.setLicenseKey('Using_this_{AG_Grid}_Enterprise_key_{AG-108524}_in_excess_of_the_licence_granted_is_not_permitted___Please_report_misuse_to_legal@ag-grid.com___For_help_with_changing_this_key_please_contact_info@ag-grid.com___{Calpine_Corporation}_is_granted_a_{Multiple_Applications}_Developer_License_for_{3}_Front-End_JavaScript_developers___All_Front-End_JavaScript_developers_need_to_be_licensed_in_addition_to_the_ones_working_with_{AG_Grid}_Enterprise___This_key_has_not_been_granted_a_Deployment_License_Add-on___This_key_works_with_{AG_Grid}_Enterprise_versions_released_before_{22_December_2026}____[v3]_[01]_MTc5Nzg5NzYwMDAwMA==99fb87be28467aa2badf367b00f3f45a');\r\n /** The below line fix the 3sec(hard coded) delay issue for removal of pre-loader from index.html */\r\n $('#mdb-preloader').remove();\r\n }\r\n} \r\n","export class LogoutModel {\r\n constructor(public Message: string, public UserName:string) {\r\n }\r\n}","import { Component, OnInit } from '@angular/core';\r\nimport { Subscription } from 'rxjs';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { AppGlobalsComponent } from '../app-globals.component';\r\nimport { ApiGatewayService } from '../services/api-gateway.service';\r\nimport { LogoutModel } from '../../user-management/shared/logout.model';\r\nimport { LoggedInUserService } from '../services/logged-in-user.service';\r\nimport 'bootstrap/dist/js/bootstrap.bundle';\r\n\r\nlet styles = String(require('./nav-menu.component.css'));\r\n@Component({\r\n selector: 'nav-menu',\r\n template: require('./nav-menu.component.html'),\r\n styles: [styles]\r\n})\r\nexport class NavMenuComponent implements OnInit {\r\n toggleMenu: boolean = false;\r\n toggle: Subscription;\r\n logout: boolean = false;\r\n loggedInUserName: string;\r\n isInternalUser: string;\r\n isReportsUser: boolean;\r\n\r\n constructor(private configuration: Configuration,\r\n private auth: AuthenticationService,\r\n private globals: AppGlobalsComponent,\r\n private apiGateway: ApiGatewayService,\r\n private loggedInUserService: LoggedInUserService) { }\r\n\r\n ngOnInit() {\r\n\r\n if (window.location.hash) {\r\n if (!this.logout && window.location.hash.indexOf('id_token') > 0) {\r\n this.auth.endSigninMainWindow();\r\n }\r\n }\r\n this.auth.userLoadedEvent.subscribe(user => {\r\n this.loggedInUserName = user.profile.name;\r\n })\r\n /**\r\n * Below code is added to handle a scenario\r\n * when user reloaded the browser window after login into the system. \r\n */\r\n if (this.auth.loggedInUser != null) {\r\n this.loggedInUserName = this.auth.loggedInUser.profile.name;\r\n this.toggleMenu = true;\r\n this.globals.ToggleMenuService.next(true);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n }\r\n\r\n /**\r\n * Toggle main navigation component based on different conditions.\r\n */\r\n this.toggle = this.globals.ToggleMenuService.subscribe((data: boolean) => {\r\n this.toggleMenu = data;\r\n });\r\n }\r\n\r\n /**\r\n * Shows Identity server login screen for providing user credentials\r\n */\r\n signIn() {\r\n this.auth.signIn();\r\n }\r\n\r\n /**\r\n * Logout the user and clean unused state.\r\n */\r\n signOut(event) {\r\n event.preventDefault();\r\n /** Fix for bug 1149 */\r\n let isLoggedIn: number = this.auth.getLocalStorageLoggedIn();\r\n if (isLoggedIn !== 1) {\r\n this.auth.signIn();\r\n } else {\r\n let logLogoutInfo: string = PORTAL_IDENTITY_PATH + 'api/userinfo/loglogout';\r\n let logoutData = new LogoutModel('Manual', this.auth.loggedInUser.profile.preferred_username);\r\n this.apiGateway.post(logLogoutInfo, {}, logoutData)\r\n .subscribe((resp) => {\r\n if (this.auth.isAuthorized) {\r\n this.logout = true;\r\n this.auth.signOut();\r\n }\r\n });\r\n }\r\n }\r\n\r\n public UserAdmin() {\r\n window.location.href = this.configuration.UserAdministrationUrl;\r\n }\r\n getReportClass(isUrlActive: boolean): any {\r\n var hasReportsAccess: boolean = this.loggedInUserService.hasReportsRole();\r\n if (!hasReportsAccess) {\r\n return {\r\n 'reports': false,\r\n 'reports-disabled': true,\r\n 'reports-enabled': false,\r\n 'reports-enabled:hover': false,\r\n 'reports-active': false\r\n };\r\n }\r\n else if (isUrlActive) {\r\n return {\r\n 'reports': true,\r\n 'reports-disabled': false,\r\n 'reports-enabled': false,\r\n 'reports-enabled:hover': false,\r\n 'reports-active': true\r\n };\r\n } else {\r\n return {\r\n 'reports': true,\r\n 'reports-disabled': !hasReportsAccess,\r\n 'reports-enabled': hasReportsAccess,\r\n 'reports-enabled:hover': hasReportsAccess,\r\n 'reports-active': false\r\n };\r\n }\r\n }\r\n\r\n getReportsDropdownClass(): any {\r\n var hasReportsAccess: boolean = this.loggedInUserService.hasReportsRole();\r\n if (!hasReportsAccess) {\r\n return {\r\n 'dropdown-nav': true,\r\n 'dropdown-enabled': false,\r\n 'dropdown-disabled': true\r\n }\r\n } else {\r\n if (this.loggedInUserService.enabledReports == null){\r\n this.loggedInUserService.enabledReports = this.getReportsDropdownItems()\r\n }\r\n return {\r\n 'dropdown-nav': true,\r\n 'dropdown-enabled': hasReportsAccess,\r\n 'dropdown-disabled': !hasReportsAccess\r\n }\r\n }\r\n }\r\n\r\n getReportsDropdownItems() {\r\n let value: any;\r\n if (this.loggedInUserService.isImpersonate) {\r\n let users = this.loggedInUserService.getImpersonateAndLoggedInUser();\r\n if (users == null || users.impersonated.roles == null ||\r\n users.loggedInUser.roles == null) {\r\n return []\r\n }\r\n //If LoggedInUser is PortalAdmin, they can see all Impersonated User's Reports\r\n if (users.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.INTERNAL) &&\r\n users.loggedInUser.roles.some(x => x === Configuration.USER_ROLES.PORTAL_ADMIN)) {\r\n let user = this.loggedInUserService.getLoggedInUser();\r\n if (user == null || user.roles == null) return [];\r\n value = ENABLED_REPORTS.filter(r => user.roles.some(x => x === r.Claim) == true);\r\n }\r\n else {\r\n let reports = ENABLED_REPORTS;\r\n\r\n //Check Logged in Impersonate Report Roles\r\n let userImpersonateReports = reports.filter(r => users.loggedInUser.roles.some(x => x === r.ImpersonateClaim) == true);\r\n\r\n //Check Impersonated User's View Report Roles\r\n let impersonatedReports = reports.filter(y => users.impersonated.roles.some(z => z === y.Claim) == true);\r\n\r\n //Filter the Impersonated roles to only have the Reports that the impersonated user has\r\n value = userImpersonateReports.filter(r => impersonatedReports.some(x => x === r) == true);\r\n }\r\n }\r\n else {\r\n let user = this.loggedInUserService.getLoggedInUser();\r\n if (user == null || user.roles == null) return [];\r\n value = ENABLED_REPORTS.filter(r => user.roles.some(x => x === r.Claim) == true);\r\n }\r\n return value.filter(r => !r.IsHidden);\r\n }\r\n\r\n getDynamicSchedulingClass(isUrlActive: boolean): any {\r\n var isDynamicSchedulingActive: boolean = this.loggedInUserService.hasDynamicSchedulingRole();\r\n if (!isDynamicSchedulingActive) {\r\n return {\r\n 'power-manager': false,\r\n 'power-manager-enabled': false,\r\n 'power-manager-enabled:hover': false,\r\n 'power-manager-active': false\r\n };\r\n } else if (isUrlActive) {\r\n return {\r\n 'power-manager': true,\r\n 'power-manager-enabled': false,\r\n 'power-manager-enabled:hover': false,\r\n 'power-manager-active': true\r\n };\r\n } else {\r\n return {\r\n 'power-manager': true,\r\n 'power-manager-enabled': isDynamicSchedulingActive,\r\n 'power-manager-enabled:hover': isDynamicSchedulingActive,\r\n 'power-manager-active': false\r\n };\r\n }\r\n }\r\n getBillingClass(isUrlActive: boolean): any {\r\n var isBillingActive: boolean = this.loggedInUserService.hasBillingRole();\r\n if (!isBillingActive) {\r\n return {\r\n 'billing': false,\r\n 'billing-enabled': false,\r\n 'billing-enabled:hover': false,\r\n 'billing-active': false\r\n };\r\n\r\n } else if (isUrlActive) {\r\n return {\r\n 'billing': true,\r\n 'billing-enabled': false,\r\n 'billing-enabled:hover': false,\r\n 'billing-active': true\r\n };\r\n } else {\r\n return {\r\n 'billing': true,\r\n 'billing-enabled': isBillingActive,\r\n 'billing-enabled:hover': isBillingActive,\r\n 'billing-active': false\r\n };\r\n }\r\n }\r\n getAdminClass(isUrlActive: boolean): any {\r\n var isAdminActive: boolean = this.loggedInUserService.hasAdminRole();\r\n if (!isAdminActive) {\r\n return {\r\n 'administration': false,\r\n 'administration-enabled': false,\r\n 'administration-enabled:hover': false,\r\n 'administration-active': false\r\n };\r\n } else if (isUrlActive) {\r\n return {\r\n 'administration': true,\r\n 'administration-enabled': false,\r\n 'administration-enabled:hover': false,\r\n 'administration-active': true\r\n };\r\n } else {\r\n return {\r\n 'administration': true,\r\n 'administration-enabled': isAdminActive,\r\n 'administration-enabled:hover': isAdminActive,\r\n 'administration-active': false\r\n };\r\n }\r\n }\r\n getImpersonateClass(isUrlActive: boolean): any {\r\n var isUserImpersonateRole: boolean = this.loggedInUserService.hasImpersonateRole() || this.loggedInUserService.isPortalAdmin();\r\n if (!isUserImpersonateRole) {\r\n return {\r\n 'impersonate': false,\r\n 'impersonate-enabled': false,\r\n 'impersonate-enabled:hover': false,\r\n 'impersonate-active': false\r\n };\r\n }\r\n else if (isUrlActive) {\r\n return {\r\n 'impersonate': true,\r\n 'impersonate-enabled': false,\r\n 'impersonate-enabled:hover': false,\r\n 'impersonate-active': true\r\n };\r\n }\r\n else {\r\n return {\r\n 'impersonate': true,\r\n 'impersonate-enabled': isUserImpersonateRole,\r\n 'impersonate-enabled:hover': isUserImpersonateRole,\r\n 'impersonate-active': false\r\n };\r\n }\r\n }\r\n revertImpersonation() {\r\n this.loggedInUserService.isImpersonate = false;\r\n this.loggedInUserService.resetImpersonatedProfile();\r\n window.location.assign(window.location.origin);\r\n }\r\n}","import { Component } from '@angular/core';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { Subscription } from 'rxjs';\r\nimport { AppGlobalsComponent } from '../app-globals.component';\r\n\r\nlet styles = String(require('./footer.component.css'));\r\n\r\n@Component({\r\n selector: 'footer-component',\r\n template: require('./footer.component.html'),\r\n styles: [styles]\r\n})\r\n\r\nexport class FooterComponent {\r\n toggleFooterMenu: boolean = false;\r\n toggle: Subscription;\r\n contactUsLink: string;\r\n currentYear: number;\r\n\r\n constructor(private configuration: Configuration,\r\n private globals: AppGlobalsComponent) {\r\n /**\r\n * Toggle main navigation component based on different conditions.\r\n */\r\n this.toggle = this.globals.ToggleFooterMenuService.subscribe((data: boolean) => {\r\n this.toggleFooterMenu = data;\r\n });\r\n\r\n this.contactUsLink = PORTAL_WEB_PATH + '#/contact-us';\r\n\r\n this.currentYear = (new Date()).getFullYear();\r\n }\r\n /** Open terms & conditions link in new window */\r\n openTermsLink(event) {\r\n event.preventDefault();\r\n this.globals.openLinkInBrowserFullScreen(PORTAL_WEB_PATH + \"#/terms-conditions\");\r\n }\r\n\r\n openContactUsLink(event) {\r\n event.preventDefault();\r\n\r\n window.location.href = this.contactUsLink;\r\n window.location.reload();\r\n }\r\n}","import { Component, ViewChild, Renderer2, Optional, OnInit, Input, OnDestroy } from '@angular/core';\r\nimport { Observable, Subscription, timer, fromEvent } from 'rxjs';\r\nimport { AuthenticationService } from './authentication.service';\r\nimport { ApiGatewayService } from '../shared/services/api-gateway.service';\r\nimport { Configuration } from '../app.configuration';\r\nimport { LogoutModel } from '../user-management/shared/logout.model';\r\nimport { NgbModal, NgbModalRef, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\r\n\r\n@Component({\r\n selector: 'session-timeout',\r\n template: require('./session-timeout.component.html')\r\n})\r\nexport class SessionTimeoutComponent implements OnInit, OnDestroy{\r\n private modalTitle: string;\r\n private modalCancelButtonText: string;\r\n private modalOkButtonText: string;\r\n private ticks: number = 0;\r\n private timerSubscription: Subscription | null;\r\n private lastTimeUserClickedBrowser: number;\r\n private showLogOutSpinner: boolean = false;\r\n private showExtendSpinner: boolean = false;\r\n private isDialogOpen: boolean = false;\r\n private isTokenExpiring: boolean = false;\r\n modalReference: NgbModalRef;\r\n constructor(private auth: AuthenticationService,\r\n private apiGateway: ApiGatewayService,\r\n private renderer: Renderer2,\r\n private modalService: NgbModal,\r\n @Optional() private activeModal: NgbActiveModal) {\r\n\r\n if (this.activeModal) {\r\n this.isDialogOpen = true;\r\n }\r\n else {\r\n this.isDialogOpen = false;\r\n this.auth.getUserManager().events.addAccessTokenExpiring(() => {\r\n this.tokenExpiring()\r\n });\r\n this.auth.getUserManager().events.addAccessTokenExpired(() => {\r\n this.tokenExpired();\r\n });\r\n this.auth.getUserManager().events.addSilentRenewError((error) => {\r\n console.error('error while renewing the access token', error);\r\n });\r\n\r\n this.timerSubscription = null;\r\n\r\n this.checkUserActive();\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n if (this.activeModal) {\r\n let pendingTokenExpirationTime = (this.auth.accessTokenExpiringNotificationTime - 10);\r\n this.timerSubscription = timer(0, 1000).subscribe((t) => {\r\n let timeRemains: number = (pendingTokenExpirationTime - t);\r\n if (timeRemains > 0) {\r\n this.ticks = timeRemains;\r\n } else {\r\n this.signOut('Automatically');\r\n $(window).trigger(Configuration.DestroyunloadhandlersEvent);\r\n }\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.timerSubscription != null) {\r\n this.timerSubscription.unsubscribe();\r\n }\r\n }\r\n\r\n /**\r\n * To check whether user is actively using the portal or not \r\n * we will use window.onfocus event to check when user last used the portal for any operation.\r\n * This event needs to be added at body level so it can be tracked from portal page.\r\n */\r\n checkUserActive() {\r\n this.renderer.listen('document', 'mouseover', (event) => {\r\n this.lastTimeUserClickedBrowser = Date.now();\r\n localStorage.setItem('nes.lastClick', Date.now().toString());\r\n });\r\n\r\n this.renderer.listen('document', 'click', (event) => {\r\n this.lastTimeUserClickedBrowser = Date.now();\r\n localStorage.setItem('nes.lastClick', Date.now().toString());\r\n });\r\n\r\n /**\r\n * Tracks browser storage updates for token expiry\r\n */\r\n let storageUpdated = fromEvent(window, 'storage');\r\n storageUpdated.subscribe((e: StorageEvent) => {\r\n if (e.key === Configuration.LOCAL_STORAGE.RENEW_TOKEN && e.newValue === '0' && this.isTokenExpiring) {\r\n this.extendTokenExpiration();\r\n this.isTokenExpiring = false;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Show session expiration info dialog aksing for user consent to extend the session or not.\r\n */\r\n showTimeOutDialog() {\r\n this.modalReference = this.modalService.open(SessionTimeoutComponent);\r\n };\r\n\r\n /**\r\n * Shows session epiration info to user and ask for user consent whethr want to extent the session\r\n * or close the session and logout.\r\n */\r\n tokenExpiring() {\r\n this.isTokenExpiring = true;\r\n // Check when user last clicked the browser\r\n if (this.lastTimeUserClickedBrowser == undefined) {\r\n this.lastTimeUserClickedBrowser = +localStorage.getItem('nes.lastClick');\r\n }\r\n let lastWindowClicked = (Date.now() - this.lastTimeUserClickedBrowser) / 1000;\r\n if (lastWindowClicked > (this.auth.tokenExpiresIn - this.auth.accessTokenExpiringNotificationTime)) {\r\n this.showTimeOutDialog();\r\n } else {\r\n this.extendTokenExpiration();\r\n }\r\n }\r\n\r\n /**\r\n * Task performed after the access token expired.\r\n */\r\n tokenExpired() {\r\n this.signOut('Session Timeout');\r\n }\r\n\r\n /**\r\n * Request silent token renewation if user request for session extension.\r\n * Configuration.LOCAL_STORAGE.RENEW_TOKEN is used to track token renewal in other browser windows.\r\n * If renewed, other browsers track browser storage property update via 'storageUpdated' Observable\r\n */\r\n extendTokenExpiration() {\r\n\r\n if (this.isDialogOpen) { this.showExtendSpinner = true; }\r\n localStorage.setItem(Configuration.LOCAL_STORAGE.RENEW_TOKEN, '1');\r\n this.auth.getUserManager().signinSilent().then((resp) => {\r\n console.log('signin silently');\r\n \r\n this.auth.setLocalStorageLoggedIn();\r\n localStorage.setItem(Configuration.LOCAL_STORAGE.RENEW_TOKEN, '0');\r\n this.auth.tokenExpiresIn = resp.expires_in;\r\n\r\n if (this.showExtendSpinner) this.showExtendSpinner = false;\r\n if (this.activeModal) {\r\n this.activeModal.close('extend token expiration');\r\n }\r\n\r\n }).catch((err) => {\r\n this.showExtendSpinner = false;\r\n console.log(err);\r\n });\r\n }\r\n\r\n /**\r\n * Logout the user and clean unused state.\r\n */\r\n signOut(logoutMessage: string) {\r\n this.showLogOutSpinner = true;\r\n let logLogoutInfo: string = PORTAL_IDENTITY_PATH + 'api/userinfo/loglogout';\r\n let logoutData = new LogoutModel(logoutMessage, this.auth.loggedInUser.profile.preferred_username);\r\n this.apiGateway.post(logLogoutInfo, {}, logoutData)\r\n .subscribe((resp) => {\r\n this.showLogOutSpinner = false;\r\n if (this.auth.IsAuthorized()) {\r\n this.auth.signOut();\r\n if (this.activeModal) {\r\n this.activeModal.close('sign out');\r\n }\r\n }\r\n });\r\n }\r\n}","import { Component, OnInit, Input, Optional, OnDestroy } from '@angular/core';\r\nimport { AppGlobalsComponent } from '../app-globals.component';\r\nimport type { IPopupMessageOptions } from './popup-message-options.component';\r\nimport { NgbModal, NgbModalRef, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\r\nimport { Subscription } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'popup',\r\n template: require('./popup.component.html')\r\n})\r\nexport class PopupComponent implements OnInit, OnDestroy {\r\n @Input() modalData: IPopupMessageOptions;\r\n modalReference: NgbModalRef;\r\n globalServiceSubscription: Subscription | null;\r\n isHidden: boolean = true;\r\n\r\n constructor(private globals: AppGlobalsComponent, private modalService: NgbModal, @Optional() private activeModal: NgbActiveModal) {\r\n if (this.activeModal) {\r\n this.isHidden = false;\r\n }\r\n this.modalData = {\r\n headerText: '',\r\n bodyText: '',\r\n buttonText: '',\r\n show: false\r\n };\r\n }\r\n\r\n ngOnInit() {\r\n if (this.activeModal == null) {\r\n this.globalServiceSubscription = this.globals.TogglePopupService.subscribe((data: IPopupMessageOptions) => {\r\n if (data.show) {\r\n /**\r\n * Set the icon if it is not set earlier\r\n */\r\n this.modalData = data;\r\n this.modalReference = this.modalService.open(PopupComponent);\r\n this.modalReference.componentInstance.modalData = this.modalData;\r\n }\r\n else {\r\n if (this.activeModal) {\r\n this.activeModal.close();\r\n }\r\n }\r\n });\r\n }\r\n else {\r\n this.globalServiceSubscription = null;\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.globalServiceSubscription) {\r\n this.globalServiceSubscription.unsubscribe();\r\n }\r\n }\r\n /**\r\n * Close the popup.\r\n */\r\n closePopup() {\r\n if (this.activeModal) {\r\n this.activeModal.close();\r\n }\r\n }\r\n}","import { Component, OnInit, Optional, OnDestroy } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { Subscription } from 'rxjs';\r\nimport { NgbModal, NgbModalRef, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';\r\n\r\n@Component({\r\n selector: 'outdated-browser',\r\n template: require('./outdated-browser.component.html')\r\n})\r\nexport class OutdatedBrowserComponent implements OnInit, OnDestroy {\r\n isWarningDisplayed: boolean = false;\r\n toggle: Subscription | null;\r\n modalReference: NgbModalRef;\r\n isHidden: boolean = true;\r\n constructor(private securityService: AuthenticationService, private modalService: NgbModal, @Optional() private activeModal: NgbActiveModal) {\r\n if (this.activeModal) {\r\n this.isHidden = false;\r\n }\r\n }\r\n\r\n isUnsupportedBrowser() {\r\n let ua = navigator.userAgent;\r\n if (ua.indexOf('MSIE') > -1) {\r\n return ua.indexOf('MSIE 10') > -1 || ua.indexOf('MSIE 9') > -1 || ua.indexOf('MSIE 8') > -1\r\n || ua.indexOf('MSIE 7') > -1 || ua.indexOf('MSIE 6') > -1;\r\n }\r\n else {\r\n return false;\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n if (this.activeModal == null) {\r\n\r\n if (!this.isWarningDisplayed && this.isUnsupportedBrowser() && this.securityService.IsAuthorized()) {\r\n this.isWarningDisplayed = true;\r\n this.modalReference = this.modalService.open(OutdatedBrowserComponent);\r\n }\r\n\r\n this.toggle = this.securityService.userLoadedEvent.subscribe(user => {\r\n if (!this.isWarningDisplayed && this.isUnsupportedBrowser() && this.securityService.IsAuthorized()) {\r\n this.isWarningDisplayed = true;\r\n this.modalReference = this.modalService.open(OutdatedBrowserComponent);\r\n }\r\n });\r\n }\r\n else {\r\n this.toggle = null;\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.toggle) {\r\n this.toggle.unsubscribe();\r\n }\r\n }\r\n\r\n closePopup() {\r\n if (this.activeModal) {\r\n this.activeModal.close();\r\n }\r\n }\r\n}","import { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { TitleCasePipe } from '@angular/common';\r\n/*import * as sc from '../shared/index';*/\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'user-profile',\r\n template: require('./user-profile.component.html'),\r\n styles: [styles],\r\n})\r\n\r\nexport class UserProfileComponent implements OnInit { \r\n loadAccountDetailsComponent: boolean = true;\r\n supportEmail: string = SUPPORT_EMAIL;\r\n supportPhone: string = SUPPORT_PHONE;\r\n \r\n constructor(private securityService: AuthenticationService) {\r\n }\r\n\r\n ngOnInit() {\r\n if (!this.securityService.isAuthorized) {\r\n this.securityService.signIn();\r\n }\r\n }\r\n\r\n userProfileComponentLinkClick(): void {\r\n this.loadAccountDetailsComponent = true;\r\n }\r\n\r\n userPasswordComponentLinkClick(): void {\r\n this.loadAccountDetailsComponent = false;\r\n }\r\n\r\n getUserProfileComponentStyle() {\r\n if (this.loadAccountDetailsComponent) {\r\n return '#0094ff';\r\n } else {\r\n return '#808080';\r\n }\r\n }\r\n\r\n getUserPasswordComponentStyle() {\r\n if (!this.loadAccountDetailsComponent) {\r\n return '#0094ff';\r\n } else {\r\n return '#808080';\r\n }\r\n }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { IUserData } from '../../shared/services/logged-in-user.service';\r\nimport * as _ from 'lodash';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'user-profile-details',\r\n template: require('./user-profile-details.component.html'),\r\n styles: [styles],\r\n})\r\n\r\nexport class UserProfileDetailsComponent implements OnInit {\r\n\r\n email: string = '';\r\n salutation: string = '';\r\n firstName: string = '';\r\n lastName: string = '';\r\n phone: string = '';\r\n\r\n constructor(private apiGateway: ApiGatewayService,\r\n private securityService: AuthenticationService) {\r\n }\r\n\r\n ngOnInit() {\r\n let userAccountDetailsUrl: string = PORTAL_IDENTITY_PATH + \"api/UserInfo/Profile\";\r\n this.apiGateway.get(userAccountDetailsUrl, null)\r\n .subscribe(response => {\r\n let data: any = response;\r\n this.email = data.email;\r\n this.salutation = data.salutation;\r\n this.firstName = data.firstName;\r\n this.lastName = data.lastName;\r\n this.phone = data.phone;\r\n });\r\n }\r\n\r\n public Logout() {\r\n this.securityService.signOut();\r\n }\r\n}\r\n","export class ResetPasswordModel {\r\n constructor(public Email: string) {\r\n }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\nimport { ResetPasswordModel } from '../shared/forgot-password.model';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport type { IConfirmationMessageOptions } from '../shared/confirmation-message-options.component';\r\n\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'forgot-password',\r\n template: require('./forgot-password.component.html'),\r\n styles: [styles]\r\n})\r\n/**\r\n * Reset the user password and send email containing reset link\r\n */\r\nexport class ForgotPasswordComponent implements OnInit, OnDestroy {\r\n private apiErrorsSubscription: Subscription;\r\n private routeParamsSubscription: Subscription;\r\n private model: ResetPasswordModel;\r\n private message: string;\r\n private saved: boolean = false;\r\n private showSpinner: boolean = false;\r\n private keyExpired: boolean = false;\r\n private confirmMessageOptions: IConfirmationMessageOptions;\r\n\r\n private businessUnitName: string;\r\n private logoPath: string;\r\n\r\n constructor(private route: ActivatedRoute,\r\n private securityService: AuthenticationService,\r\n private apiGateway: ApiGatewayService,\r\n private globals: AppGlobalsComponent,\r\n private elementRef: ElementRef) { }\r\n\r\n requestPassword() {\r\n this.showSpinner = true;\r\n if (this.model.Email.trim().length > 0) {\r\n let resetPasswordUrl: string = PORTAL_IDENTITY_PATH + 'api/password/reset';\r\n this.apiGateway.post(resetPasswordUrl, {}, this.model)\r\n .subscribe(response => {\r\n this.saved = true;\r\n this.showSpinner = false;\r\n this.confirmMessageOptions = {\r\n headerText: 'To get back into your account,',\r\n footerText: \"Didn't receive the password reset email?\",\r\n };\r\n });\r\n } else {\r\n this.message = 'Please enter valid email.';\r\n }\r\n }\r\n\r\n ngOnInit() {\r\n this.showSpinner = false;\r\n this.model = new ResetPasswordModel('');\r\n this.routeParamsSubscription = this.route.params.subscribe(params => {\r\n let keyState = params['keyState'];\r\n if (keyState == 'true') {\r\n this.keyExpired = true;\r\n }\r\n });\r\n\r\n this.apiErrorsSubscription = this.apiGateway.errors$.subscribe(\r\n (value: any) => {\r\n let exceptionMessage = JSON.parse(value._body).exceptionMessage;\r\n let message = JSON.parse(value._body).message;\r\n this.message = (exceptionMessage ? exceptionMessage : message);\r\n this.showSpinner = false;\r\n });\r\n /**\r\n * Rasing event to disable top navigation\r\n */\r\n this.globals.ToggleMenuService.next(false);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n /**\r\n * Setting the background image of body as per mockup\r\n */\r\n let el: HTMLElement = this.elementRef.nativeElement.ownerDocument.body;\r\n el.className = 'body-background-image';\r\n }\r\n\r\n ngOnDestroy() {\r\n this.apiErrorsSubscription.unsubscribe();\r\n this.routeParamsSubscription.unsubscribe();\r\n }\r\n\r\n login() {\r\n this.showSpinner = false;\r\n event.preventDefault();\r\n this.securityService.signIn();\r\n }\r\n\r\n tryAgain() {\r\n this.saved = false;\r\n this.model = new ResetPasswordModel('');\r\n }\r\n}","/**\r\n * Custom messages to show on screen\r\n */\r\nexport class AccountMessagesService {\r\n public static get Verification_Key_Status_Check():string {return \"Loading...\";}\r\n public static get Confirm_Forgot_Password(): string { return \"Password changed. \" + AccountMessagesService.loginRedirection; }\r\n public static get Password_VerificationKey_Expired(): string { return \"Either password has changed or Key expired. \" + AccountMessagesService.loginRedirection; }\r\n public static get Confirm_Email_With_Password_Change(): string { return \"New portal password set. \" + AccountMessagesService.loginRedirection; }\r\n static loginRedirection: string = \"Please wait while we redirect you to sign in page.\"\r\n}","export class ConfirmPasswordModel {\r\n constructor(public Key: string,\r\n public UserId: string,\r\n public Password: string,\r\n public ConfirmPassword: string,\r\n public PasswordPlaceholder: string,\r\n public ReEnterPasswordPlaceholder: string) { }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { AccountMessagesService } from '../shared/account-messages.service';\r\nimport { ConfirmPasswordModel } from '../shared/confirm-password.model'\r\nimport { map } from 'rxjs/operators';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n\r\n@Component({\r\n selector: 'confirm-password',\r\n template: require('./confirm-password.component.html'),\r\n styles: [styles]\r\n})\r\n\r\n/**\r\n * Confirm and change password from link received in email after resetting the password.\r\n */\r\nexport class ConfirmPasswordComponent implements OnInit, OnDestroy {\r\n\r\n private apiErrorsSubscription: Subscription;\r\n private routeParamsSubscription: Subscription;\r\n private model: ConfirmPasswordModel;\r\n private showSpinner: boolean = false;\r\n private isIE: boolean;\r\n private message: string;\r\n private saved: boolean = false;\r\n private keyExpired: boolean = true;\r\n constructor(private route: ActivatedRoute,\r\n private router: Router,\r\n private securityService: AuthenticationService,\r\n private apiGateway: ApiGatewayService,\r\n private configuration: Configuration,\r\n private globals: AppGlobalsComponent,\r\n private elementRef: ElementRef) {\r\n \r\n }\r\n\r\n ConfirmPassword() {\r\n this.showSpinner = true;\r\n this.message = '';\r\n if (this.model.Password.trim().length > 0) {\r\n let confirmPasswordUrl: string = PORTAL_IDENTITY_PATH + \"api/password/confirm\";\r\n this.apiGateway.post(confirmPasswordUrl, {}, this.model)\r\n .pipe(map((res) => res))\r\n .subscribe(data => {\r\n if (data.toString() == 'true') {\r\n // Show the success message\r\n // You have been sent an email to confirm your request to reset your password. Once you have recieved the email you can follow the instructions to set a new password.\r\n this.message = AccountMessagesService.Confirm_Forgot_Password;\r\n this.saved = true;\r\n this.startTimer();\r\n } else if (data.toString() == 'false') {\r\n this.message = AccountMessagesService.Password_VerificationKey_Expired;\r\n this.startTimer();\r\n } else {\r\n this.message = data.toString();\r\n }\r\n this.showSpinner = false;\r\n });\r\n }\r\n\r\n }\r\n\r\n startTimer() {\r\n let timer = setTimeout(() => {\r\n this.securityService.signIn();\r\n }, 2000);\r\n }\r\n ngOnInit() {\r\n this.showSpinner = false;\r\n this.message = AccountMessagesService.Verification_Key_Status_Check;\r\n this.isIE = this.globals.isInternetExplorer();\r\n /**\r\n * At least 1 lowercase, uppercase, digit, symbole, in any order, for a length >= 10\r\n * \"^.*(?=.{10,})(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[&\"'(\\-_)=~#{[|`\\\\^@\\]}^$*¨£µ%,;:!?./§+]).*$\"\r\n\r\n * \"Password with minimum 8 and maximum 20 characters with minimum 1 Upper Case Alphabet, 1 Digit and 1 Special Character\"\r\n * \"^(?!.*(.)\\1{1})(?=(.*[\\d]){1,})(?=(.*[a-z]){1,})(?=(.*[A-Z]){1,})(?=(.*[@#$%!]){1,})(?:[\\da-zA-Z@#$%!]){8,20}$\"\r\n\r\n * Password with minimum 8 and maximum 20 characters with minimum 1 Upper 1 lower Case Alphabet, 1 Digit or 1 Special Character\r\n * ^(?=.*[a-z])(?=.*[A-Z])((?=.*\\d)|(?=(.*[@#$%!]){1,})).{8,20)$\r\n * var strongRegex = new RegExp(\"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\\$%\\^&\\*])(?=.{8,})\");\r\n * var mediumRegex = new RegExp(\"^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})\");\r\n \r\n ^\t The password string will start this way\r\n (?=.*[a-z])\t The string must contain at least 1 lowercase alphabetical character\r\n (?=.*[A-Z])\t The string must contain at least 1 uppercase alphabetical character\r\n (?=.*[0-9])\t The string must contain at least 1 numeric character\r\n (?=.*[!@#\\$%\\^&\\*])\tThe string must contain at least one special character, but we are escaping reserved RegEx characters to avoid conflict\r\n (?=.{8,})\t The string must be eight characters or longer\r\n */\r\n\r\n this.apiErrorsSubscription = this.apiGateway.errors$.subscribe(\r\n (value: any) => {\r\n let exceptionMessage = JSON.parse(value._body).exceptionMessage;\r\n let message = JSON.parse(value._body).message;\r\n this.message = (exceptionMessage ? exceptionMessage : message);\r\n this.showSpinner = false;\r\n });\r\n /**\r\n * Rasing event to disable top navigation\r\n */\r\n this.globals.ToggleMenuService.next(false);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n /**\r\n * Setting the background image of body as per mockup\r\n */\r\n let el: HTMLElement = this.elementRef.nativeElement.ownerDocument.body;\r\n el.className = 'body-background-image';\r\n\r\n this.routeParamsSubscription = this.route.params.subscribe(params => {\r\n let key = params['key'];\r\n this.model = new ConfirmPasswordModel(key, \"\", \"\", \"\",\"Enter New Password\",\"Re-Enter Password\");\r\n this.checkKeyExpiration(key);\r\n });\r\n\r\n }\r\n\r\n ngOnDestroy() {\r\n this.routeParamsSubscription.unsubscribe();\r\n this.apiErrorsSubscription.unsubscribe();\r\n }\r\n\r\n /**\r\n * Check whether the verification key is expired or not.\r\n */\r\n checkKeyExpiration(key: string) {\r\n if (key != undefined) {\r\n let checkKeyStatusUrl: string = PORTAL_IDENTITY_PATH + \"api/password/IsKeyExpired\";\r\n this.apiGateway.post(checkKeyStatusUrl, {}, key)\r\n .subscribe(data => {\r\n if (data.toString() == 'true') {\r\n this.router.navigateByUrl('/forgotpassword/true')\r\n }\r\n else {\r\n this.keyExpired = false;\r\n this.model.UserId = data.toString();\r\n this.message = '';\r\n }\r\n });\r\n }\r\n }\r\n\r\n public Login() {\r\n this.showSpinner = false;\r\n this.securityService.signIn();\r\n }\r\n}","export class ChangePasswordModel {\r\n constructor(public OldPassword: string, public NewPassword: string, public NewPasswordConfirm: string) { }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { AccountMessagesService } from '../shared/account-messages.service';\r\nimport { ChangePasswordModel } from '../shared/change-password.model'\r\nimport { LogoutModel } from '../shared//logout.model';\r\nimport { map } from 'rxjs/operators';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'change-password',\r\n template: require('./change-password.component.html'),\r\n styles: [styles],\r\n})\r\n/**\r\n * Confirm and change password from link received in email after resetting the password.\r\n */\r\nexport class ChangePasswordComponent implements OnInit, OnDestroy {\r\n\r\n private sub: Subscription;\r\n private model: ChangePasswordModel;\r\n private message: string;\r\n private saved: boolean = false;\r\n private showSpinner: boolean = false;\r\n\r\n constructor(private securityService: AuthenticationService,\r\n private apiGateway: ApiGatewayService) { }\r\n\r\n ChangePassword() {\r\n this.showSpinner = true;\r\n // clear the old message if any\r\n this.message = '';\r\n if (this.model.OldPassword.trim().length > 0) {\r\n let confirmPasswordUrl: string = PORTAL_IDENTITY_PATH + 'api/password/change';\r\n this.apiGateway.post(confirmPasswordUrl, {}, this.model)\r\n .pipe(map((res) => res.toString()))\r\n .subscribe(data => {\r\n if (data == 'true') {\r\n // Show the success message\r\n // You have been sent an email to confirm your request to reset your password. Once you have recieved the email you can follow the instructions to set a new password.\r\n this.message = AccountMessagesService.Confirm_Forgot_Password;\r\n this.saved = true;\r\n this.startTimer();\r\n } else if (data == 'false') {\r\n this.message = AccountMessagesService.Password_VerificationKey_Expired;\r\n this.startTimer();\r\n } else {\r\n this.message = data;\r\n }\r\n this.showSpinner = false;\r\n });\r\n }\r\n }\r\n\r\n startTimer() {\r\n let timer = setTimeout(() => {\r\n // logout the user \r\n let logLogoutInfo: string = PORTAL_IDENTITY_PATH + 'api/userinfo/loglogout';\r\n let logoutData = new LogoutModel('Change Password', this.securityService.loggedInUser.profile.preferred_username);\r\n this.apiGateway.post(logLogoutInfo, {}, logoutData)\r\n .subscribe((resp) => {\r\n if (this.securityService.IsAuthorized()) {\r\n this.securityService.signOut();\r\n }\r\n });\r\n\r\n }, 2000);\r\n }\r\n\r\n ngOnInit() {\r\n this.showSpinner = false;\r\n this.model = new ChangePasswordModel('', '', '');\r\n this.sub = this.apiGateway.errors$.subscribe(\r\n (value: any) => {\r\n let exceptionMessage = JSON.parse(value._body).exceptionMessage;\r\n let message = JSON.parse(value._body).message;\r\n this.message = (exceptionMessage ? exceptionMessage : message);\r\n this.showSpinner = false;\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.sub.unsubscribe();\r\n }\r\n\r\n public Login() {\r\n this.showSpinner = false;\r\n this.securityService.signIn();\r\n }\r\n}","export class ConfirmEmailModel {\r\n constructor(public Key: string,\r\n public NewPassword: string,\r\n public NewPasswordConfirm: string, \r\n public NewPasswordPlaceholder: string,\r\n public NewPasswordConfirmPlaceholder: string) { }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\nimport { ResetPasswordModel } from '../shared/forgot-password.model';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { AccountMessagesService } from '../shared/account-messages.service';\r\nimport type { IConfirmationMessageOptions } from '../shared/confirmation-message-options.component';\r\nimport { ConfirmEmailModel } from '../shared/confirm-email.model'\r\nimport { map } from 'rxjs/operators';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'confirm-email',\r\n template: require('./confirm-email.component.html'),\r\n styles: [styles]\r\n})\r\n/**\r\n * Confirm and change password from link received in email after resetting the password.\r\n */\r\nexport class ConfirmEmailComponent implements OnInit, OnDestroy {\r\n\r\n private apiErrorsSubscription: Subscription;\r\n private checkKeyStatusSubscription: Subscription;\r\n private sendWelcomeEmailSubscription: Subscription;\r\n private routeParamsSubscription: Subscription;\r\n private model: ConfirmEmailModel;\r\n private message: string;\r\n private saved: boolean = false;\r\n private showSpinner: boolean = false;\r\n private isIE: boolean;\r\n private keyExpired: boolean = false;\r\n private modelWelcomeEmail: ResetPasswordModel;\r\n private showConfirmMessage: boolean = false;\r\n private confirmMessageOptions: IConfirmationMessageOptions;\r\n private showLinkExpired: boolean = true;\r\n constructor(private route: ActivatedRoute,\r\n private securityService: AuthenticationService,\r\n private apiGateway: ApiGatewayService,\r\n private globals: AppGlobalsComponent,\r\n private elementRef: ElementRef) { }\r\n\r\n /**\r\n * Peform the following tasks\r\n * 1. Change new password\r\n * 2. Confirm email\r\n * 3. Verify account\r\n * 4. Allow login\r\n */\r\n confirmEmail() {\r\n this.showSpinner = true;\r\n // clear the old message if any\r\n this.message = '';\r\n if (this.model.NewPassword.trim().length > 0) {\r\n let confirmEmailUrl: string = PORTAL_IDENTITY_PATH + 'api/password/verify';\r\n this.apiGateway.post(confirmEmailUrl, {}, this.model)\r\n .pipe(map((res) => res.toString()))\r\n .subscribe(data => {\r\n if (data == 'true') {\r\n // Show the success message\r\n this.message = AccountMessagesService.Confirm_Email_With_Password_Change;\r\n this.saved = true;\r\n this.delayedNavToSignIn();\r\n } else {\r\n this.message = data;\r\n }\r\n this.showSpinner = false;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Send welcome email again after link expired.\r\n * As the user account already created. Membership api will send account confirmation email if you request password reset but \r\n * account is not verified.\r\n */\r\n sendWelcomeEmail() {\r\n this.showSpinner = true;\r\n if (this.modelWelcomeEmail.Email.trim().length > 0) {\r\n let welcomeEmailUrl: string = PORTAL_IDENTITY_PATH + 'api/password/reset';\r\n this.sendWelcomeEmailSubscription = this.apiGateway.post(welcomeEmailUrl, {}, this.modelWelcomeEmail)\r\n .subscribe((response) => {\r\n this.saved = true;\r\n this.showConfirmMessage = true;\r\n this.confirmMessageOptions = {\r\n headerText: 'To complete registration,',\r\n footerText: \"Didn't receive the reset registration email?\",\r\n };\r\n\r\n this.showSpinner = false;\r\n });\r\n } else {\r\n this.message = 'Please enter valid email.';\r\n }\r\n }\r\n\r\n delayedNavToSignIn() {\r\n let timer = setTimeout(() => {\r\n // Redirect user to login screen\r\n this.securityService.signIn();\r\n }, 2000);\r\n }\r\n\r\n ngOnInit() {\r\n this.showSpinner = false;\r\n this.message = AccountMessagesService.Verification_Key_Status_Check;\r\n this.isIE = this.globals.isInternetExplorer();\r\n this.apiErrorsSubscription = this.apiGateway.errors$.subscribe(\r\n (value: any) => {\r\n let exceptionMessage = JSON.parse(value._body).exceptionMessage;\r\n let message = JSON.parse(value._body).message ? JSON.parse(value._body).message : JSON.parse(value._body);\r\n this.message = (exceptionMessage ? exceptionMessage : message);\r\n this.showSpinner = false;\r\n });\r\n /**\r\n * Rasing event to disable top navigation\r\n */\r\n this.globals.ToggleMenuService.next(false);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n /**\r\n * Setting the background image of body as per mockup\r\n */\r\n let el: HTMLElement = this.elementRef.nativeElement.ownerDocument.body;\r\n el.className = 'body-background-image';\r\n\r\n this.routeParamsSubscription = this.route.params.subscribe(params => {\r\n let key = params['key'];\r\n this.model = new ConfirmEmailModel(key, \"\", \"\", \"New Password\", \"Re-enter Password\");\r\n this.checkKeyExpiration(key);\r\n });\r\n\r\n }\r\n\r\n /**\r\n * Check whether the verification key is expired or not.\r\n */\r\n checkKeyExpiration(key: string) {\r\n this.saved = true;\r\n if (key != undefined) {\r\n let checkKeyStatusUrl: string = PORTAL_IDENTITY_PATH + \"api/password/IsKeyExpired\";\r\n this.checkKeyStatusSubscription = this.apiGateway.post(checkKeyStatusUrl, {}, key)\r\n .subscribe(data => {\r\n if (data.toString() == 'true') {\r\n this.keyExpired = true;\r\n this.modelWelcomeEmail = new ResetPasswordModel(\"\");\r\n }\r\n else {\r\n this.keyExpired = false;\r\n this.saved = false;\r\n }\r\n this.message = '';\r\n });\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.routeParamsSubscription.unsubscribe();\r\n this.apiErrorsSubscription.unsubscribe();\r\n this.checkKeyStatusSubscription.unsubscribe();\r\n this.sendWelcomeEmailSubscription.unsubscribe();\r\n }\r\n\r\n tryAgain() {\r\n this.showConfirmMessage = false;\r\n this.keyExpired = true;\r\n this.showLinkExpired = false;\r\n this.modelWelcomeEmail = new ResetPasswordModel(\"\");\r\n }\r\n\r\n login() {\r\n this.showSpinner = false;\r\n this.securityService.signIn();\r\n }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, OnInit, OnDestroy, ElementRef } from '@angular/core';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { TitleCasePipe } from '@angular/common';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'cancel-password-reset-request',\r\n template: require('./cancel-password-reset-request.component.html'),\r\n styles: [styles],\r\n})\r\n/**\r\n * Reset the user password and send email containing reset link\r\n */\r\nexport class CancelPasswordResetRequestComponent implements OnInit, OnDestroy {\r\n private apiErrorsSubscription: Subscription;\r\n private routeParamsSubscription: Subscription;\r\n private message: string;\r\n private verificationKey: string;\r\n private saved: boolean = false;\r\n constructor(private route: ActivatedRoute,\r\n private securityService: AuthenticationService,\r\n private apiGateway: ApiGatewayService,\r\n private globals: AppGlobalsComponent,\r\n private elementRef: ElementRef) { }\r\n\r\n CancelPasswordResetRequest() {\r\n let cancelVerificationUrl: string = PORTAL_IDENTITY_PATH + 'api/password/CancelVerification';\r\n this.apiGateway.post(cancelVerificationUrl, {}, this.verificationKey)\r\n .subscribe(response => {\r\n this.message='';\r\n this.saved = true;\r\n });\r\n\r\n }\r\n\r\n ngOnInit() {\r\n this.message=\"Cancelling request. Please wait!!!!\";\r\n this.apiErrorsSubscription = this.apiGateway.errors$.subscribe(\r\n (value: any) => {\r\n this.message = JSON.parse(value._body).message;\r\n });\r\n\r\n /**\r\n * Rasing event to disable top navigation\r\n */\r\n this.globals.ToggleMenuService.next(false);\r\n this.globals.ToggleFooterMenuService.next(true);\r\n /**\r\n * Setting the background image of body as per mockup\r\n */\r\n let el: HTMLElement = this.elementRef.nativeElement.ownerDocument.body;\r\n el.className = 'body-background-image';\r\n\r\n this.routeParamsSubscription = this.route.params.subscribe((params) => {\r\n this.verificationKey = params['key'];\r\n this.CancelPasswordResetRequest();\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.routeParamsSubscription.unsubscribe();\r\n this.apiErrorsSubscription.unsubscribe();\r\n }\r\n\r\n public Login() {\r\n event.preventDefault();\r\n this.securityService.signIn();\r\n }\r\n}","import { Component } from '@angular/core';\r\nimport { AuthenticationService } from './authentication.service';\r\n\r\n@Component({\r\n selector:'login',\r\n template:``\r\n})\r\n/**\r\n * This component helps to resolve the login url(which contains signin querystring value) issue needs to send from change password.\r\n * When you change your password, IDServer sends and email for login url which is missing the applicationid\r\n * requires by IDServer login page itself. \r\n * */\r\nexport class LoginComponent{\r\n constructor(public securityService: AuthenticationService) {\r\n this.securityService.signIn();\r\n }\r\n}","import { Routes, RouterModule } from '@angular/router';\r\nimport { UserProfileComponent } from './profile/user-profile.component';\r\nimport { UserProfileDetailsComponent } from './profile/user-profile-details.component';\r\nimport { ForgotPasswordComponent } from './password/forgot-password.component';\r\nimport { ConfirmPasswordComponent } from './password/confirm-password.component';\r\nimport { ChangePasswordComponent } from './password/change-password.component';\r\nimport { ConfirmEmailComponent } from './password/confirm-email.component';\r\nimport { CancelPasswordResetRequestComponent } from './password/cancel-password-reset-request.component';\r\nimport { LoginComponent } from '../authentication/login.component';\r\nimport { CanActivateAuthGuard } from '../authentication/auth-guard.service';\r\n\r\nconst userManagementRoutes: Routes = [\r\n { path: 'forgotpassword/:keyState', component: ForgotPasswordComponent },\r\n { path: 'confirmresetpassword/:key', component: ConfirmPasswordComponent },\r\n { path: 'changepassword', component: ChangePasswordComponent, canActivate: [CanActivateAuthGuard] },\r\n { path: 'cancelresetpassword/:key', component: CancelPasswordResetRequestComponent },\r\n { path: 'confirmemail/:key', component: ConfirmEmailComponent },\r\n { path: 'user-profile', component: UserProfileComponent, canActivate: [CanActivateAuthGuard], data: { title: 'My Account' } },\r\n { path: 'user-profile-details', component: UserProfileDetailsComponent, canActivate: [CanActivateAuthGuard] },\r\n { path: 'login', component: LoginComponent },\r\n];\r\n\r\nexport const userManagementRouting = RouterModule.forChild(userManagementRoutes);","import { Directive, forwardRef, Attribute } from '@angular/core';\r\nimport { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';\r\n\r\n@Directive({\r\n selector: '[validateEqual][formControlName],[validateEqual][formControl],[validateEqual][ngModel]',\r\n providers: [\r\n { provide: NG_VALIDATORS, useExisting: forwardRef(() => EqualValidatorDirective), multi: true }\r\n ]\r\n})\r\nexport class EqualValidatorDirective implements Validator {\r\n constructor( @Attribute('validateEqual') public validateEqual: string,\r\n @Attribute('reverse') public reverse: string) {\r\n\r\n }\r\n\r\n private get isReverse() {\r\n if (!this.reverse) return false;\r\n return this.reverse === 'true' ? true: false;\r\n }\r\n\r\n validate(c: AbstractControl): { [key: string]: any } {\r\n // self value\r\n let v = c.value;\r\n\r\n // control vlaue\r\n let e = c.root.get(this.validateEqual);\r\n\r\n // value not equal\r\n if (e && v !== e.value && !this.isReverse) {\r\n return {\r\n validateEqual: false\r\n }\r\n }\r\n\r\n // value equal and reverse\r\n if (e && v === e.value && this.isReverse) {\r\n delete e.errors['validateEqual'];\r\n if (!Object.keys(e.errors).length) e.setErrors(null);\r\n }\r\n\r\n // value not equal and reverse\r\n if (e && v !== e.value && this.isReverse) {\r\n e.setErrors({\r\n validateEqual: false\r\n })\r\n }\r\n\r\n return null;\r\n }\r\n}","//import * as sc from '../shared/index';\r\nimport { Component, Input, Output, EventEmitter} from '@angular/core'\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport type { IConfirmationMessageOptions } from '../shared/confirmation-message-options.component';\r\n\r\nlet styles = String(require('../shared/user-management.component.css'));\r\n\r\n@Component({\r\n selector: 'confirmation-message',\r\n template: require('./confirmation-message.component.html'),\r\n styles: [styles],\r\n})\r\n/**\r\n * Reset the user password and send email containing reset link\r\n */\r\nexport class ConfirmationMessageComponent {\r\n\r\n supportEmail: string = SUPPORT_EMAIL;\r\n\r\n constructor(private securityService: AuthenticationService) { }\r\n\r\n @Input() messageOptions: IConfirmationMessageOptions;\r\n @Output() onTryAgain = new EventEmitter();\r\n\r\n tryAgain() {\r\n this.onTryAgain.emit();\r\n }\r\n\r\n login() {\r\n this.securityService.signIn();\r\n }\r\n}","import { NgModule } from '@angular/core';\r\nimport { SharedModule } from '../shared/shared.module';\r\n\r\nimport { userManagementRouting } from './user-management.routing';\r\n\r\nimport { ChangePasswordComponent } from './password/change-password.component';\r\nimport { ConfirmPasswordComponent } from './password/confirm-password.component';\r\nimport { ForgotPasswordComponent } from './password/forgot-password.component';\r\nimport { CancelPasswordResetRequestComponent } from './password/cancel-password-reset-request.component';\r\nimport { ConfirmEmailComponent } from './password/confirm-email.component';\r\nimport { LoginComponent } from '../authentication/login.component';\r\nimport { UserProfileDetailsComponent } from './profile/user-profile-details.component';\r\nimport { UserProfileComponent } from './profile/user-profile.component';\r\n//import { EqualValidatorDirective } from './shared/index';\r\nimport { EqualValidatorDirective } from '../shared/directives/equal-validator.directive';\r\nimport { ConfirmationMessageComponent } from './password/confirmation-message.component';\r\n\r\n@NgModule({\r\n imports: [\r\n SharedModule,\r\n userManagementRouting\r\n ],\r\n\r\n declarations: [\r\n ChangePasswordComponent, \r\n ConfirmPasswordComponent, \r\n ForgotPasswordComponent,\r\n CancelPasswordResetRequestComponent,\r\n ConfirmEmailComponent,\r\n LoginComponent,\r\n UserProfileComponent, \r\n UserProfileDetailsComponent,\r\n EqualValidatorDirective,\r\n ConfirmationMessageComponent\r\n ],\r\n\r\n exports: [\r\n \r\n ]\r\n}) \r\n\r\nexport class UserManagementModule { } ","import { ChangeDetectionStrategy, Component } from '@angular/core';\r\nimport { SubNavItem } from '../shared/nav-menu/sub-nav-menu/sub-nav.model';\r\n\r\n@Component({\r\n selector: 'dynamic-scheduling',\r\n template: require('./dynamic-scheduling.component.html'),\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n styles: [require('./shared/dynamic-scheduling.component.css').toString()]\r\n})\r\n\r\nexport class DynamicSchedulingComponent {\r\n\r\n dynamicScheduleChildRouteDetails: SubNavItem[] = [];\r\n scheduleUploadNavLabel: string;\r\n\r\n constructor() {\r\n document.getElementById(\"main-body\").className = \"add-scrollbar\";\r\n this.scheduleUploadNavLabel = 'Dynamic Scheduling';\r\n\r\n this.dynamicScheduleChildRouteDetails = [\r\n { 'routerText': this.scheduleUploadNavLabel, 'routerLink': 'schedule-upload' },\r\n { 'routerText': 'Help', 'routerLink': 'help' }\r\n ];\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ScheduleUpload } from '../schedule-upload/schedule-upload.reducer'\r\n\r\n@Injectable()\r\nexport class ScheduleValidationService {\r\n\r\n constructor() {}\r\n\r\n static getFlowDateErrors(newInfo: ScheduleUpload[], limitWarningMode: boolean): number[] {\r\n var flowDateErrors: number[] = [];\r\n\r\n newInfo.forEach((schedule: ScheduleUpload) => {\r\n // in limit-warning-mode, we only care about that error\r\n if (schedule.DynamicSchedule.FlowDateValidation != null && !limitWarningMode) {\r\n schedule.DynamicSchedule.FlowDateValidation.forEach((flowDateError) => {\r\n if (flowDateErrors.indexOf(flowDateError.Message) == -1) { // Message = ErrorID\r\n flowDateErrors.push(flowDateError.Message); \r\n }\r\n });\r\n }\r\n\r\n if (schedule.hasBelowFixed && !limitWarningMode && flowDateErrors.indexOf(1) == -1) { // error [1] = hour-below-fixed\r\n flowDateErrors.push(1);\r\n }\r\n if (schedule.hasLimitWarning && flowDateErrors.indexOf(2) == -1) { // error [2] = hour-limit-warning\r\n flowDateErrors.push(2);\r\n }\r\n\r\n });\r\n\r\n // The errors have a sorting order that is different from the MessageID\r\n return flowDateErrors.sort((flowDateError1, flowDateError2) => {\r\n return ValidationMessages[flowDateError1].Order - ValidationMessages[flowDateError2].Order;\r\n });\r\n }\r\n\r\n}\r\n\r\nexport const ValidationMessages: Object = {\r\n 1: {\r\n Order: 7,\r\n Summary: \"Your Requested Quantities for one or more hours are below your Fixed Price Contract Quantities.\",\r\n Footnote: \"Requested Quantities are below your Fixed Price Contract quantities. For the impacted hours the Fixed Price Contract Quantities will be scheduled.\",\r\n Tooltip: \"Your Requested Quantity is below your Fixed Price Contract Quantity.\",\r\n },\r\n 2: {\r\n Order: 2,\r\n Summary: \"Your Requested Quantities for one or more hours are unusually high.\",\r\n Footnote: \"Your Requested Quantities for one or more hours are unusually high.\",\r\n Tooltip: \"Your Requested Quantity is unusually high.\"\r\n },\r\n 3: {\r\n Order: 1,\r\n Summary: \"Submittal failed due to formatting or file formatting error. No quantities were submitted for impacted schedules.\",\r\n Footnote: \"Submittal failed due to formatting or file formatting error. No quantities were submitted for this schedule.\"\r\n },\r\n 4: {\r\n Order: 5,\r\n Summary: \"Customer submittal deadline has passed for one or more of the requested flow dates.\",\r\n Footnote: \"Customer submittal deadline has passed for the requested flow dates. No quantities were submitted for this schedule.\"\r\n },\r\n 5: {\r\n Order: 3,\r\n Summary: \"One or more of the customer points is not currently registered for Dynamic Scheduling.\",\r\n Footnote: \"This customer point is not currently registered for Dynamic Scheduling. No quantities were submitted for this schedule.\"\r\n },\r\n 6: {\r\n Order: 4,\r\n Summary: \"One or more flow dates is beyond the accepted date range. Requests are currently accepted through the end of next month.\",\r\n Footnote: \"Dynamic schedule requests are currently accepted through the end of next month. No quantities were submitted for this schedule.\"\r\n },\r\n 7: {\r\n Order: 6,\r\n Summary: \"There are one or more duplicate pairs of flow date and delivery point.\",\r\n Footnote: \"Flow date could not be processed because a duplicate submission for the Customer Point and Flow Date was received in the same submission. No quantities were submitted for this schedule.\"\r\n },\r\n 8: {\r\n Order: 8,\r\n Summary: \"This delivery point is not configured correctly.\",\r\n Footnote: \"This point does not have an entry in the ScheduleConfiguration table.\"\r\n },\r\n 9: {\r\n Order: 9,\r\n Summary: \"This delivery point does not have fixed load data to check against for load validation.\",\r\n Footnote: \"ScheduleCache fixed load entries for this point do not exist.\"\r\n },\r\n 10: {\r\n Order: 10,\r\n Summary: \"This delivery point does not have index load data to check against for load validation.\",\r\n Footnote: \"ScheduleCache index load entries for this point do not exist.\"\r\n },\r\n 11: {\r\n Order: 11,\r\n Summary: \"You are not authorized to submit dynamic schedules for this point.\",\r\n Footnote: \"Unauthorized user for this delivery point.\"\r\n },\r\n 12: {\r\n Order: 12,\r\n Summary: \"You are not authorized to submit dynamic schedules.\",\r\n Footnote: \"Unauthorized user for dynamic scheduling.\"\r\n },\r\n 13: {\r\n Order: 13,\r\n Summary: \"One or more of the requested volumes is negative.\",\r\n Footnote: \"Negative volumes are not allowed. No quantities were submitted for this schedule.\"\r\n }\r\n}","import { Action, ActionReducer } from '@ngrx/store';\r\nimport { HE_RANGE } from '../shared/he-range';\r\n\r\n// 1. Import the entire timezone package namespace\r\nimport * as momentTimezoneImport from 'moment-timezone';\r\n\r\n// 2. Resolve the runtime default wrapper mapping\r\nconst moment = (momentTimezoneImport as any).default || momentTimezoneImport;\r\n\r\n\r\nimport * as _ from 'lodash';\r\n\r\nimport type { IScheduleUploadFilter } from '../shared/schedule-upload-filter.model';\r\nimport { ScheduleFilterService } from '../shared/schedule-filter.service';\r\nimport { ScheduleValidationService } from '../shared/schedule-validation.service';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { ScheduleAction } from '../shared/schedule-action';\r\nexport interface IScheduleUploadBundle {\r\n UploadTime: string;\r\n UploadID: number;\r\n isNewUpload: boolean;\r\n Outcome: IUploadHold;\r\n ScheduleUploadInfo: IScheduleUploadInfo[];\r\n}\r\nexport interface IUploadHold {\r\n HasHold: boolean;\r\n Outcome: number; // 0 Accepted, 1 Rejected, 2 Abandoned\r\n}\r\nexport class ScheduleUploadBundle implements IScheduleUploadBundle {\r\n public UploadTime: string;\r\n public UploadDateTime: moment.Moment;\r\n public UploadTimeString: string; \r\n public UploadID: number;\r\n public isNewUpload: boolean;\r\n public Outcome: IUploadHold;\r\n public ScheduleUploadInfo: IScheduleUploadInfo[];\r\n\r\n constructor(data: IScheduleUploadBundle) {\r\n this.UploadTime = data.UploadTime;\r\n this.UploadDateTime = data.UploadTime != null ? moment.utc(data.UploadTime).tz(moment.tz.guess()) : null;\r\n this.UploadTimeString = this.UploadDateTime == null ? null : this.UploadDateTime.format(\"M-D-YYYY | h:mm:ss A z\");\r\n this.UploadID = data.UploadID;\r\n this.isNewUpload = data.isNewUpload;\r\n this.Outcome = data.Outcome;\r\n this.ScheduleUploadInfo = data.ScheduleUploadInfo;\r\n \r\n }\r\n}\r\n\r\n\r\n/* HEValue is for editing uploads. For each HE value, we need a little more info there than just the number */\r\nexport interface IHEValue {\r\n value: number;\r\n originalValue: number;\r\n isDirty: boolean;\r\n isActive: boolean;\r\n}\r\nexport class HEValue implements IHEValue {\r\n value: number;\r\n originalValue: number;\r\n isDirty: boolean;\r\n isActive: boolean;\r\n constructor(value: number) {\r\n this.value = value;\r\n this.originalValue = value;\r\n this.isDirty = false;\r\n this.isActive = false;\r\n }\r\n}\r\nexport interface IScheduleUploadInfo{\r\n DynamicSchedule: any;\r\n FinalSchedule: any;\r\n}\r\nexport class ScheduleUpload implements IScheduleUploadInfo {\r\n public DynamicSchedule: any;\r\n public FinalSchedule: any;\r\n\r\n public hasInvalidFileError: boolean;\r\n public hasFlowDateError: boolean;\r\n public isEditable: boolean;\r\n public warningCount: number;\r\n public errorCount: number;\r\n public successfullySubmitted: boolean;\r\n public submittedWithErrors: boolean;\r\n public notSubmitted: boolean;\r\n public hasLimitWarning: boolean;\r\n public hasBelowFixed: boolean;\r\n\r\n constructor(data: IScheduleUploadInfo, isNewUpload: boolean) {\r\n const rawSchedule = data.DynamicSchedule.getValue\r\n ? data.DynamicSchedule.getValue() // If it's a BehaviorSubject\r\n : data.DynamicSchedule; // If it's a plain object\r\n var ds = Object.assign({}, rawSchedule); // make a copy so we don't modify the original object\r\n\r\n var ds1 = JSON.parse(JSON.stringify(ds));\r\n\r\n this.DynamicSchedule = Object.assign({}, ds1);;\r\n for (var i of HE_RANGE) {\r\n this.DynamicSchedule['HE' + i] = new HEValue(this.DynamicSchedule['HE' + i]);\r\n }\r\n\r\n this.DynamicSchedule.FlowDateMoment = data.DynamicSchedule.FlowDate != null ? moment(data.DynamicSchedule.FlowDate, \"YYYY-MM-DD\") : null;\r\n this.DynamicSchedule.FlowDate = this.DynamicSchedule.FlowDateMoment == null ? null : this.DynamicSchedule.FlowDateMoment.format(\"M/DD/YY\");\r\n this.DynamicSchedule.FlowDateYear = this.DynamicSchedule.FlowDateMoment == null ? null : this.DynamicSchedule.FlowDateMoment.year().toString();\r\n this.DynamicSchedule.FlowDateValue = this.DynamicSchedule.FlowDateMoment.valueOf(); // for date sorting and filtering\r\n\r\n this.FinalSchedule = data.FinalSchedule;\r\n\r\n this.hasInvalidFileError = this.DynamicSchedule.FlowDateValidation != null && this.DynamicSchedule.FlowDateValidation.some((error) => { return error.Message == 3; });\r\n this.hasFlowDateError = this.DynamicSchedule.FlowDateValidation != null && this.DynamicSchedule.FlowDateValidation.length != 0;\r\n this.isEditable = isNewUpload && !this.hasFlowDateError; // no edit for get-previous or schedules with flowdate errors\r\n\r\n var warningCount = 0, errorCount = 0;\r\n for (var i of HE_RANGE) {\r\n if (this.DynamicSchedule['HEValidation' + i] != null && this.DynamicSchedule['HEValidation' + i].length != 0 ){\r\n switch (this.DynamicSchedule['HEValidation' + i][0].Severity) {\r\n case 2:\r\n warningCount++;\r\n break;\r\n case 3:\r\n errorCount++;\r\n break;\r\n }\r\n } \r\n }\r\n\r\n this.warningCount = warningCount;\r\n this.errorCount = errorCount;\r\n this.hasLimitWarning = this.warningCount != 0;\r\n this.hasBelowFixed = this.errorCount != 0;\r\n\r\n if (this.errorCount == 0 && this.warningCount == 0 && (this.DynamicSchedule.FlowDateValidation == null || this.DynamicSchedule.FlowDateValidation.length == 0)){\r\n this.successfullySubmitted = true;\r\n this.submittedWithErrors = false;\r\n this.notSubmitted = false;\r\n } else if ((this.errorCount != 0 || this.warningCount != 0) && (this.DynamicSchedule.FlowDateValidation == null || this.DynamicSchedule.FlowDateValidation.length == 0)) {\r\n this.successfullySubmitted = false;\r\n this.submittedWithErrors = true;\r\n this.notSubmitted = false;\r\n } else {\r\n this.successfullySubmitted = false;\r\n this.submittedWithErrors = false;\r\n this.notSubmitted = true;\r\n }\r\n\r\n }\r\n}\r\n\r\nexport interface IScheduleUploadModel {\r\n scheduleUploadList: ScheduleUpload[];\r\n lastUploadedDate: string;\r\n filteredSchedules: ScheduleUpload[];\r\n dashboardCounts: IDashboardCounts;\r\n flowDateErrors: number[];\r\n showInvalidExtensionMessage: boolean;\r\n scheduleUploadFilter: IScheduleUploadFilter;\r\n scheduleCustomerPoints: string[];\r\n scheduleFlowDates: string[];\r\n isDynamicSchedulingAvailable: boolean;\r\n limitWarningMode: boolean;\r\n uploadID: number;\r\n isDirty: boolean;\r\n isNewUpload: boolean;\r\n showXlsmError: boolean;\r\n isLoading: boolean;\r\n}\r\ninterface IDashboardCounts {\r\n successfullySubmitted: number;\r\n submittedWithErrors: number;\r\n notSubmitted: number;\r\n pointsSubmitted: number;\r\n limitWarning: number;\r\n belowFixed: number;\r\n}\r\n\r\n\r\n\r\nexport const scheduleUploadReducer: ActionReducer = (\r\n /* Default VM */\r\n currentState: IScheduleUploadModel = {\r\n scheduleUploadList: [],\r\n lastUploadedDate: null,\r\n filteredSchedules: [],\r\n dashboardCounts: {\r\n successfullySubmitted: 0,\r\n submittedWithErrors: 0,\r\n notSubmitted: 0,\r\n pointsSubmitted: 0,\r\n limitWarning: 0,\r\n belowFixed: 0\r\n },\r\n flowDateErrors: [],\r\n showInvalidExtensionMessage: false,\r\n isDynamicSchedulingAvailable: true,\r\n limitWarningMode: false,\r\n uploadID: 0,\r\n scheduleUploadFilter: ReducerMethods.getDefaultFilter(),\r\n scheduleCustomerPoints: [],\r\n scheduleFlowDates: [],\r\n isDirty: false,\r\n isNewUpload: false,\r\n showXlsmError: false,\r\n isLoading: false\r\n }, action: ScheduleAction) => {\r\n\r\n var state = JSON.parse(JSON.stringify(currentState));\r\n\r\n switch (action.type) {\r\n case 'SET_DYNAMIC_SCHEDULES':\r\n //do some re-calculations before we update the state\r\n var uploadBundle: ScheduleUploadBundle = new ScheduleUploadBundle(action.payload); // Action.Payload should be IScheduleUploadBundle\r\n var schedulesData: IScheduleUploadInfo[] = uploadBundle.ScheduleUploadInfo;\r\n var schedules = schedulesData.map((schedule) => {\r\n return new ScheduleUpload(schedule, uploadBundle.isNewUpload);\r\n });\r\n\r\n var limitWarningMode: boolean = false;\r\n\r\n // see if high limit warnings and display dialog\r\n if (schedules.some((schedule) => { return schedule.hasLimitWarning; }) && uploadBundle.isNewUpload == true) {\r\n //$(window).trigger(Configuration.ShowHighLimitWarningDialogEvent);\r\n limitWarningMode = true;\r\n }\r\n if (uploadBundle.Outcome && uploadBundle.Outcome.HasHold && uploadBundle.Outcome.Outcome !== 0) {\r\n //they either rejected or abandoned a previous upload that had limit warnings\r\n limitWarningMode = true;\r\n }\r\n\r\n var dashboardCounts = ReducerMethods.getDashboardCounts(schedules, limitWarningMode);\r\n var defaultFilter: IScheduleUploadFilter = ReducerMethods.getDefaultFilter(); // Jeff's sorting doesn't work accross year\r\n ScheduleFilterService.sortSchedules(schedules, defaultFilter);\r\n var uploadID: number = uploadBundle.UploadID;\r\n\r\n // figure out the lists of customer points and flow dates for the header filters\r\n var scheduleCustomerPoints = [];\r\n var scheduleFlowDatesSchedules: ScheduleUpload[] = []; // grab the whole schedule for now so we can sort\r\n schedules.forEach((schedule) => {\r\n if (scheduleCustomerPoints.filter((point) => { return schedule.DynamicSchedule.Point.toLowerCase() == point.toLowerCase(); }).length == 0) {\r\n scheduleCustomerPoints.push(schedule.DynamicSchedule.Point);\r\n }\r\n if (scheduleFlowDatesSchedules.findIndex((flowDateSchedule) => flowDateSchedule.DynamicSchedule.FlowDate == schedule.DynamicSchedule.FlowDate) == -1) {\r\n scheduleFlowDatesSchedules.push(schedule);\r\n }\r\n });\r\n scheduleCustomerPoints = scheduleCustomerPoints.sort((a, b) => {\r\n if (a.toLowerCase() > b.toLowerCase())\r\n return 1;\r\n else return -1;\r\n });\r\n var scheduleFlowDates = scheduleFlowDatesSchedules.sort((scheduleA, scheduleB) => {\r\n return scheduleA.DynamicSchedule.FlowDateValue > scheduleB.DynamicSchedule.FlowDateValue ? 1 : -1;\r\n }).map((schedule) => {\r\n return schedule.DynamicSchedule.FlowDate\r\n });\r\n \r\n var flowDateErrors = ScheduleValidationService.getFlowDateErrors(schedules, limitWarningMode);\r\n //apply the counts and reset the filter + filteredschedules\r\n return Object.assign({}, state, {\r\n scheduleUploadList: schedules,\r\n lastUploadedDate: uploadBundle.UploadTimeString,\r\n filteredSchedules: schedules, \r\n scheduleCustomerPoints,\r\n scheduleFlowDates,\r\n scheduleUploadFilter: defaultFilter,\r\n dashboardCounts,\r\n flowDateErrors,\r\n limitWarningMode,\r\n uploadID,\r\n isDirty: false,\r\n isNewUpload: uploadBundle.isNewUpload,\r\n isLoading: false\r\n });\r\n case 'UPDATE_SCHEDULE_FILTER':\r\n // stuff should come thru like { scheduleStatus: 1 } - just smoosh it into the existing filter\r\n // scheduleStatus and specificError need to work like a toggle though so a little extra logic for that\r\n var updatedFilter = ScheduleFilterService.updateFilter(state.scheduleUploadFilter, action.payload, state.scheduleFlowDates, state.scheduleCustomerPoints);\r\n var filteredSchedules = ScheduleFilterService.filterSchedules(state.scheduleUploadList, updatedFilter, state.limitWarningMode);\r\n updatedFilter.isAnyFilterPresent = ReducerMethods.isAnyFilterPresent(updatedFilter);\r\n ScheduleFilterService.sortSchedules(filteredSchedules, updatedFilter);\r\n return Object.assign({}, state, { scheduleUploadFilter: updatedFilter, filteredSchedules: filteredSchedules });\r\n case 'SET_INVALID_FLOWDATES':\r\n return Object.assign({}, state, { invalidFlowdates: action.payload });\r\n case 'SET_INVALID_EXTENSION_MESSAGE':\r\n return Object.assign({}, state, { showInvalidExtensionMessage: action.payload });\r\n case 'SET_XLSM_EXTENSION_MESSAGE':\r\n return Object.assign({}, state, { showXlsmError: action.payload });\r\n case 'SET_DYNAMIC_SCHEDULING_AVAILABLE':\r\n return Object.assign({}, state, { isDynamicSchedulingAvailable: action.payload });\r\n case 'SET_LIMIT_WARNING_MODE':\r\n // this is called from the limit-warning modal once the user makes a selection.\r\n // need to recalculate the flowdate errors and dashboard counts - they work a little differently \r\n var limitWarningMode: boolean = action.payload;\r\n var flowDateErrors = ScheduleValidationService.getFlowDateErrors(state.scheduleUploadList, limitWarningMode);\r\n var dashboardCounts = ReducerMethods.getDashboardCounts(state.scheduleUploadList, limitWarningMode);\r\n return Object.assign({}, state, { limitWarningMode, flowDateErrors, dashboardCounts });\r\n case 'SUBMIT_HE_CHANGES':\r\n var input: string = action.payload.input;\r\n var parsedInput = parseFloat(input);\r\n var HE_INDEX: number = action.payload.HE_INDEX;\r\n var schedule: ScheduleUpload = action.payload.schedule;\r\n var scheduleFromList = state.scheduleUploadList.find(sched => sched.DynamicSchedule.Point == schedule.DynamicSchedule.Point && sched.DynamicSchedule.FlowDateValue == schedule.DynamicSchedule.FlowDateValue);\r\n var heObject: HEValue = scheduleFromList.DynamicSchedule['HE' + HE_INDEX];\r\n heObject.isActive = false;\r\n //don't update the value if NaN\r\n if (!isNaN(parsedInput)) {\r\n // reset the value and do not mark as dirty\r\n heObject.value = parsedInput;\r\n heObject.isDirty = heObject.value != heObject.originalValue;\r\n }\r\n \r\n //look through our schedules and see if the page as a whole is dirty now too.\r\n var anyDirty: boolean = state.scheduleUploadList.some((sched) => {\r\n return HE_RANGE.some((i) => {\r\n return sched.DynamicSchedule['HE' + i].isDirty;\r\n });\r\n });\r\n\r\n return Object.assign({}, state, { isDirty: anyDirty}); // mark the model as dirty too if any HE is dirty now \r\n case 'ACTIVATE_HE_CELL':\r\n var HE_INDEX: number = action.payload.HE_INDEX;\r\n var schedule: ScheduleUpload = action.payload.schedule;\r\n var scheduleFromList = state.scheduleUploadList.find(sched => sched.DynamicSchedule.Point == schedule.DynamicSchedule.Point && sched.DynamicSchedule.FlowDateValue == schedule.DynamicSchedule.FlowDateValue);\r\n scheduleFromList.DynamicSchedule['HE' + HE_INDEX].isActive = true;\r\n return Object.assign({}, state);\r\n case 'RESET_DYNAMIC_SCHEDULING':\r\n // this is for when someone navigates away from DS and comes back. We want to keep the data but reset the filters and editing\r\n state.scheduleUploadFilter = ReducerMethods.getDefaultFilter();\r\n // loop through all the HE cells of every schedule and reset them all.\r\n state.scheduleUploadList.forEach((sched) => {\r\n for (var i of HE_RANGE) {\r\n var heObject: HEValue = sched.DynamicSchedule['HE' + i];\r\n heObject.isActive = false;\r\n heObject.isDirty = false;\r\n heObject.value = heObject.originalValue;\r\n }\r\n });\r\n return Object.assign({}, state, { filteredSchedules: state.scheduleUploadList, isDirty: false });\r\n case 'SHOW_LOAD_BAR':\r\n return Object.assign({}, state, { isLoading: true });\r\n case 'HIDE_LOAD_BAR':\r\n return Object.assign({}, state, { isLoading: false });\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nclass ReducerMethods {\r\n static getDashboardCounts(schedules: ScheduleUpload[], limitWarningMode: boolean): IDashboardCounts{\r\n var successfullySubmitted = 0,\r\n submittedWithErrors = 0,\r\n notSubmitted = 0,\r\n pointsSubmitted = [],\r\n limitWarning = 0,\r\n belowFixed = 0;\r\n\r\n schedules.forEach((schedule) => {\r\n if (limitWarningMode) {\r\n // limit-warning-mode = nothing gets submitted\r\n notSubmitted++\r\n } else if (schedule.successfullySubmitted) {\r\n successfullySubmitted++;\r\n } else if (schedule.submittedWithErrors) {\r\n submittedWithErrors++;\r\n } else {\r\n notSubmitted++;\r\n }\r\n\r\n\t\t\t// For point to be added, the point needs to not be in the list already, the schedules needs to have no flowdate errors, and we must not be in limit warning mode (nothing submitted)\r\n if (pointsSubmitted.indexOf(schedule.DynamicSchedule.Point) == -1 && !limitWarningMode && (schedule.DynamicSchedule.FlowDateValidation == null || schedule.DynamicSchedule.FlowDateValidation.length == 0)) {\r\n pointsSubmitted.push(schedule.DynamicSchedule.Point);\r\n }\r\n\r\n if (schedule.hasLimitWarning) {\r\n limitWarning++;\r\n }\r\n // don't care about below-fixed errors if we're in limit-warning-mode\r\n if (schedule.hasBelowFixed && !limitWarningMode) {\r\n belowFixed++;\r\n }\r\n });\r\n\r\n return {\r\n successfullySubmitted,\r\n submittedWithErrors,\r\n notSubmitted,\r\n pointsSubmitted: pointsSubmitted.length,\r\n limitWarning,\r\n belowFixed\r\n };\r\n }\r\n\r\n static getDefaultFilter(): IScheduleUploadFilter {\r\n return {\r\n isDefaultSort: true,\r\n isAnyFilterPresent: false,\r\n scheduleStatuses: [],\r\n specificError: null,\r\n customerSearch: '',\r\n customerPoints: [],\r\n flowDates: [],\r\n customerPointSort: 'ASC',\r\n flowDateSort: 'ASC',\r\n flowDateStart: null,\r\n flowDateEnd: null, \r\n submitters: [],\r\n submittersSort: null,\r\n DOWs: [],\r\n DOWSort: null,\r\n uploadTimestamps: [],\r\n uploadTimestampSort: null,\r\n uploadDateStart: null,\r\n uploadDateEnd: null,\r\n finals: []\r\n };\r\n }\r\n\r\n static isAnyFilterPresent(currentFilter: IScheduleUploadFilter): boolean {\r\n let defaultFilters: IScheduleUploadFilter = ReducerMethods.getDefaultFilter();\r\n return (currentFilter.customerSearch !== defaultFilters.customerSearch ||\r\n !(_.isEqual(currentFilter.customerPoints.sort(), defaultFilters.customerPoints.sort())) ||\r\n currentFilter.flowDateStart !== defaultFilters.flowDateStart ||\r\n currentFilter.flowDateEnd !== defaultFilters.flowDateEnd\r\n );\r\n }\r\n\r\n}\r\n","import { ScheduleUpload, IScheduleUploadInfo } from '../schedule-upload/schedule-upload.reducer';\r\n\r\n// 1. Import the entire timezone package namespace\r\nimport * as momentTimezoneImport from 'moment-timezone';\r\n\r\n// 2. Resolve the runtime default wrapper mapping\r\nconst moment = (momentTimezoneImport as any).default || momentTimezoneImport;\r\n\r\nexport const WeekdayStrings = [\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thur\",\"Fri\",\"Sat\"];\r\n\r\nexport interface IScheduleArchiveInfo extends IScheduleUploadInfo{\r\n UploadTime: string;\r\n SubmittedBy: string;\r\n SubmissionRank: number;\r\n ScheduleErrors: Array;\r\n}\r\n\r\nexport class ScheduleArchive extends ScheduleUpload{\r\n public DOW: string;\r\n public isFinal: boolean;\r\n public UploadDateTime: Date;\r\n public UploadDateStamp: string;\r\n public UploadDateStampExcel: string;\r\n public UploadDateTimeValue;\r\n public UploadMoment: moment.Moment;\r\n public UploadTimeString: string; \r\n public SubmittedBy: string;\r\n public SubmissionRank: number;\r\n\r\n constructor(data: IScheduleArchiveInfo){\r\n super(data, false);\r\n var dd = new Date(data.DynamicSchedule.FlowDate);\r\n this.DOW = WeekdayStrings[dd.getDay()]; \r\n this.SubmittedBy = data.SubmittedBy;\r\n this.SubmissionRank = data.SubmissionRank;\r\n this.isFinal = this.SubmissionRank == 1 ? true : false;\r\n\r\n this.UploadDateTime = new Date(data.UploadTime); \r\n this.UploadDateTimeValue = this.UploadDateTime.valueOf();\r\n this.UploadMoment = data.UploadTime != null ? moment.utc(data.UploadTime).tz(moment.tz.guess()) : null;\r\n this.UploadTimeString = this.UploadMoment == null ? null : this.UploadMoment.format(\"h:mm A\");\r\n this.UploadDateStamp = this.UploadMoment == null ? null : moment.utc(this.UploadDateTime).tz(moment.tz.guess()).format(\"M/DD/YY\").toString();\r\n this.UploadDateStampExcel = this.UploadMoment == null ? null : moment.utc(this.UploadDateTime).tz(moment.tz.guess()).format('MM/DD/YYYY').toString();\r\n\r\n data.ScheduleErrors.forEach( e => {\r\n let item = {'Severity': e.Severity, 'Message':e.Message};\r\n switch(e.HourEnding) {\r\n case \"99\":\r\n this.DynamicSchedule.FlowDateValidation = [];\r\n this.DynamicSchedule.FlowDateValidation.push(item);\r\n default:\r\n if (this.DynamicSchedule['HEValidation' + e.HourEnding] == null){\r\n this.DynamicSchedule['HEValidation' + e.HourEnding] = [{'Severity': e.Severity, 'Message':e.Message}];\r\n }\r\n else {\r\n this.DynamicSchedule['HEValidation' + e.HourEnding].push(item);\r\n }\r\n }\r\n });\r\n };\r\n}\r\n\r\nexport interface IScheduleArchiveBundle {\r\n ScheduleArchiveUploadInfo: IScheduleArchiveInfo[];\r\n}\r\n\r\nexport class ScheduleArchiveBundle implements IScheduleArchiveBundle {\r\n public UploadTime: string;\r\n public UploadDateTime: moment.Moment;\r\n public UploadTimeString: string; \r\n public UploadID: number;\r\n public NewUpload: boolean;\r\n public ScheduleArchiveUploadInfo: IScheduleArchiveInfo[];\r\n\r\n constructor(data: IScheduleArchiveBundle) {\r\n this.ScheduleArchiveUploadInfo = data.ScheduleArchiveUploadInfo;\r\n }\r\n}\r\n\r\nexport interface IScheduleArchiveModel {\r\n scheduleList: ScheduleUpload[];\r\n scheduleUploadList: ScheduleArchive[];\r\n lastUploadedDate: string;\r\n filteredSchedules: ScheduleUpload[];\r\n flowDateErrors: number[];\r\n showInvalidExtensionMessage: boolean;\r\n scheduleUploadFilter: any;\r\n scheduleCustomerPoints: string[];\r\n scheduleFlowDates: string[];\r\n scheduleFinals: boolean[],\r\n scheduleSubmitters: string[],\r\n scheduleDOWs: string[];\r\n isDynamicSchedulingAvailable: boolean;\r\n limitWarningMode: boolean;\r\n callHighLimitWarningDialog: boolean;\r\n uploadID: number;\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { ScheduleUpload } from '../schedule-upload/schedule-upload.reducer'\r\nimport { ScheduleArchive, WeekdayStrings } from '../schedule-archive/schedule-archive.model';\r\nimport type { IScheduleUploadFilter } from './schedule-upload-filter.model';\r\n\r\n// faux enum\r\nexport const SCHEDULE_STATUS_FILTERS = {\r\n SUCCESS: 1,\r\n NOT_SUBMITTED: 2,\r\n ERRORS: 3,\r\n LIMIT_WARNING: 4,\r\n BELOW_FIXED: 5\r\n};\r\n\r\n@Injectable()\r\nexport class ScheduleFilterService{\r\n\r\n constructor(){}\r\n\r\n static updateFilter(filter: IScheduleUploadFilter, \r\n currentUpdates: any, \r\n allFlowDates: string[], \r\n allCustomerPoints: string[],\r\n allSubmitters?: string[],\r\n allDOWs?: string[],\r\n allFinals?: boolean[]) \r\n {\r\n // most of them we can just stamp in the updates. Some require a little more attention though\r\n // so create a new object so we don't lost the existing values\r\n var currentFilter: IScheduleUploadFilter = JSON.parse(JSON.stringify(filter));\r\n var updates: any = JSON.parse(JSON.stringify(currentUpdates));\r\n var updatedFilter: IScheduleUploadFilter = Object.assign({}, updates, currentFilter);\r\n\r\n //for these, if the update is the same as the existing value, the user clicked the button again and we want to toggle off.\r\n if (updates.specificError && currentFilter.specificError == updates.specificError) {\r\n updatedFilter.specificError = null;\r\n }\r\n else {\r\n // Otherwise, check if the filter change they made actually involves this filter (!= undefined) before applying it \r\n updatedFilter.specificError = (updates.specificError !== undefined ? updates.specificError : currentFilter.specificError); \r\n if (updates.specificError !== undefined) {\r\n // schedule-status and specific-error should turn each other off\r\n updatedFilter.scheduleStatuses = [];\r\n }\r\n }\r\n\r\n if (updates.scheduleStatus === null) {\r\n updatedFilter.scheduleStatuses = [];\r\n } else if (updates.scheduleStatus) {\r\n // we want to toggle this if it's in there already\r\n if (updatedFilter.scheduleStatuses.indexOf(updates.scheduleStatus) == -1) {\r\n updatedFilter.scheduleStatuses.push(updates.scheduleStatus);\r\n updatedFilter.specificError = null; // schedule-status and specific-error should turn each other off\r\n } else {\r\n updatedFilter.scheduleStatuses.splice(updatedFilter.scheduleStatuses.indexOf(updates.scheduleStatus), 1);\r\n }\r\n }\r\n\r\n // select all\r\n if (updates.addCustomerPoint === null) {\r\n if (updatedFilter.customerPoints.length == allCustomerPoints.length) {\r\n updatedFilter.customerPoints = [];\r\n } else {\r\n // select all - copy the array into the filter\r\n updatedFilter.customerPoints = allCustomerPoints.map((point) => { return point; });\r\n }\r\n }\r\n else if (updates.addCustomerPoint) {\r\n // this should work like a toggle. If it's not there, add it. If it's there, remove it.\r\n if (updatedFilter.customerPoints.indexOf(updates.addCustomerPoint) == -1) {\r\n updatedFilter.customerPoints.push(updates.addCustomerPoint);\r\n } else {\r\n updatedFilter.customerPoints.splice(updatedFilter.customerPoints.indexOf(updates.addCustomerPoint), 1)\r\n }\r\n }\r\n\r\n // Submitted By Filter\r\n if (updates.addSubmitter === null) {\r\n if (updatedFilter.submitters.length == allSubmitters.length) {\r\n updatedFilter.submitters = [];\r\n } else {\r\n updatedFilter.submitters = allSubmitters.map((submitter) => { return submitter });\r\n }\r\n }\r\n else if (updates.addSubmitter) {\r\n if (updatedFilter.submitters.indexOf(updates.addSubmitter) == -1) {\r\n updatedFilter.submitters.push(updates.addSubmitter);\r\n } else {\r\n updatedFilter.submitters.splice(updatedFilter.submitters.indexOf(updates.addSubmitter), 1);\r\n }\r\n }\r\n\r\n // DOW Filter\r\n if(updates.addDOW === null) {\r\n if (updatedFilter.DOWs.length == allDOWs.length) {\r\n updatedFilter.DOWs = [];\r\n } else {\r\n updatedFilter.DOWs = allDOWs.map((dow) => { return dow });\r\n }\r\n }\r\n else if (updates.addDOW) {\r\n if (updatedFilter.DOWs.indexOf(updates.addDOW) == -1 ) {\r\n updatedFilter.DOWs.push(updates.addDOW);\r\n } else {\r\n updatedFilter.DOWs.splice(updatedFilter.DOWs.indexOf(updates.addDOW), 1);\r\n }\r\n }\r\n\r\n // Final Flag Filter\r\n if(updates.addFinal === null) {\r\n if (updatedFilter.finals.length == allFinals.length){\r\n updatedFilter.finals = [];\r\n } else {\r\n updatedFilter.finals = allFinals.map((final) => { return final });\r\n }\r\n }\r\n else if (updates.addFinal != null) {\r\n if (updatedFilter.finals.indexOf(updates.addFinal) == -1) {\r\n updatedFilter.finals.push(updates.addFinal);\r\n } else {\r\n updatedFilter.finals.splice(updatedFilter.finals.indexOf(updates.addFinal), 1);\r\n }\r\n }\r\n\r\n // select all\r\n if (updates.addFlowDate === null) {\r\n if (updatedFilter.flowDates.length == allFlowDates.length) {\r\n // clear all\r\n updatedFilter.flowDates = [];\r\n } else {\r\n // select all - copy the array\r\n updatedFilter.flowDates = allFlowDates.map((flowdate) => { return flowdate; });\r\n }\r\n } else if (updates.addFlowDate) {\r\n // this should work like a toggle. If it's not there, add it. If it's there, remove it.\r\n if (updatedFilter.flowDates.indexOf(updates.addFlowDate) == -1) {\r\n updatedFilter.flowDates.push(updates.addFlowDate);\r\n }\r\n else {\r\n updatedFilter.flowDates.splice(updatedFilter.flowDates.indexOf(updates.addFlowDate), 1)\r\n }\r\n }\r\n\r\n // UPLOAD DATE RANGE FILTER //\r\n // Upload Date Start\r\n if (updates.addUploadStart === \"\") {\r\n updatedFilter.uploadDateStart = null;\r\n } else if (updates.addUploadStart) {\r\n updatedFilter.uploadDateStart = updates.addUploadStart;\r\n }\r\n // Upload Date End\r\n if (updates.addUploadEnd === \"\") {\r\n updatedFilter.uploadDateEnd = null;\r\n } else if (updates.addUploadEnd) {\r\n updatedFilter.uploadDateEnd = updates.addUploadEnd;\r\n }\r\n\r\n // FLOW DATE RANGE FILTER //\r\n // Flow Date Start\r\n if (updates.addFlowStart === \"\") {\r\n updatedFilter.flowDateStart = null;\r\n }\r\n else if (updates.addFlowStart) {\r\n updatedFilter.flowDateStart = updates.addFlowStart;\r\n }\r\n //Flow Date End\r\n if (updates.addFlowEnd === \"\") {\r\n updatedFilter.flowDateEnd = null;\r\n }\r\n if (updates.addFlowEnd) {\r\n updatedFilter.flowDateEnd = updates.addFlowEnd;\r\n }\r\n\r\n if (updates.sortCustomerPoint) {\r\n let previousVal = updatedFilter.customerPointSort;\r\n updatedFilter = this.clearAllSorts(updatedFilter);\r\n if (updatedFilter.isDefaultSort) {\r\n // both filters are on by default but once you click one, it turns the other off and now you can only sort on one column\r\n updatedFilter.customerPointSort = previousVal;\r\n updatedFilter.isDefaultSort = false;\r\n }\r\n else {\r\n updatedFilter.customerPointSort = this.rotateSortDirection(previousVal);\r\n }\r\n }\r\n\r\n if (updates.sortFlowDate) {\r\n let previousVal = updatedFilter.flowDateSort;\r\n updatedFilter = this.clearAllSorts(updatedFilter);\r\n\r\n if (updatedFilter.isDefaultSort) {\r\n updatedFilter.flowDateSort = previousVal;\r\n updatedFilter.isDefaultSort = false;\r\n }\r\n else {\r\n updatedFilter.flowDateSort = this.rotateSortDirection(previousVal);\r\n }\r\n }\r\n\r\n if (updates.sortSubmitter) {\r\n let previousVal = updatedFilter.submittersSort; // remember what the previous sort direction was\r\n updatedFilter = this.clearAllSorts(updatedFilter); // clear all sorts \r\n if (updatedFilter.isDefaultSort){\r\n // certain filters are on by default, but once you click one, it turns the others off and now you can only sort on one column\r\n updatedFilter.submittersSort = previousVal\r\n updatedFilter.isDefaultSort = false;\r\n } \r\n else {\r\n updatedFilter.submittersSort = this.rotateSortDirection(previousVal);\r\n } \r\n }\r\n\r\n if (updates.sortTimestamp) {\r\n let previousVal = updatedFilter.uploadTimestampSort;\r\n updatedFilter = this.clearAllSorts(updatedFilter);\r\n if (updatedFilter.isDefaultSort){\r\n // certain filters are on by default, but once you click one, it turns the others off and now you can only sort on one column\r\n updatedFilter.uploadTimestampSort = previousVal\r\n updatedFilter.isDefaultSort = false;\r\n } \r\n else {\r\n updatedFilter.uploadTimestampSort = this.rotateSortDirection(previousVal);\r\n } \r\n }\r\n\r\n if (updates.sortDOW) {\r\n let previousVal = updatedFilter.DOWSort;\r\n updatedFilter = this.clearAllSorts(updatedFilter);\r\n if (updatedFilter.isDefaultSort) {\r\n updatedFilter.DOWSort = previousVal;\r\n updatedFilter.isDefaultSort = false;\r\n }\r\n else {\r\n updatedFilter.DOWSort = this.rotateSortDirection(previousVal);\r\n }\r\n }\r\n\r\n return updatedFilter;\r\n }\r\n\r\n static clearAllSorts(filter: IScheduleUploadFilter): IScheduleUploadFilter {\r\n filter.customerPointSort = null;\r\n filter.flowDateSort = null;\r\n filter.submittersSort = null;\r\n filter.DOWSort = null;\r\n filter.uploadTimestampSort = null;\r\n return filter;\r\n }\r\n\r\n static rotateSortDirection(previous: string): string {\r\n // Column sorting should rotate through the 3 values ASC DESC NULL\r\n return previous === null ? \"ASC\" : previous == \"ASC\" ? \"DESC\" : null;\r\n }\r\n\r\n\r\n // static filterSchedules(scheduleUploadList: ScheduleUpload[]|ScheduleArchive[], filter: IScheduleUploadFilter|IScheduleArchiveFilter, limitWarningMode: boolean): ScheduleUpload[] {\r\n static filterSchedules(scheduleUploadList: any, filter: IScheduleUploadFilter, limitWarningMode: boolean): ScheduleUpload[] {\r\n var filteredSchedules = [];\r\n\r\n for (var schedule of scheduleUploadList) {\r\n if (this.passesStatusFilter(schedule, filter.scheduleStatuses, limitWarningMode) &&\r\n this.passesSpecificErrorFilter(schedule, filter.specificError) &&\r\n this.passesCustomerSearchFilter(schedule, filter.customerSearch) &&\r\n this.passesCustomerPointFilter(schedule, filter.customerPoints) &&\r\n this.passesFlowDateFilter(schedule, filter.flowDates) &&\r\n this.passesDOWFilter(schedule, filter.DOWs) &&\r\n this.passesSubmitterFilter(schedule, filter.submitters) \r\n && this.passesFinalFlagFilter(schedule, filter.finals)\r\n && this.passesFlowDateStart(schedule, filter.flowDateStart)\r\n && this.passesFlowDateEnd(schedule, filter.flowDateEnd)\r\n && this.passesUploadDateStart(schedule, filter.uploadDateStart)\r\n && this.passesUploadDateEnd(schedule, filter.uploadDateEnd)\r\n ) {\r\n\r\n filteredSchedules.push(schedule);\r\n }\r\n }\r\n return filteredSchedules;\r\n }\r\n\r\n static passesUploadDateStart(schedule: ScheduleArchive, uploadDateStart: string): boolean {\r\n if (uploadDateStart === null) {\r\n return true; // #NoFilter\r\n }\r\n\r\n // Upload Date should be equal to or after selected uploadDateStart, disregard time\r\n if (new Date(schedule.UploadDateTime.setHours(0,0,0,0)) >= new Date(uploadDateStart)) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n static passesUploadDateEnd(schedule: ScheduleArchive, uploadDateEnd: string): boolean {\r\n if (uploadDateEnd === null) {\r\n return true; // #NoFilter\r\n }\r\n\r\n // Upload Date should be before or equal to selected uploadDateEnd, disregard time\r\n if (new Date(schedule.UploadDateTime.setHours(0,0,0,0)) <= new Date(uploadDateEnd)) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n static passesFlowDateStart(schedule: ScheduleUpload, flowDateStart: Date): boolean {\r\n if (flowDateStart === null) {\r\n return true; // #NoFilter\r\n } \r\n\r\n // DynamicSchedule.FlowDate should be equal to or after selected flowDateStart\r\n if ((new Date(schedule.DynamicSchedule.FlowDateValue)) >= new Date(flowDateStart)) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n static passesFlowDateEnd(schedule: ScheduleUpload, flowDateEnd: Date): boolean {\r\n if (flowDateEnd === null) {\r\n return true; // #NoFilter\r\n } \r\n if (new Date(schedule.DynamicSchedule.FlowDateValue) <= new Date(flowDateEnd)) {\r\n return true;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n static passesStatusFilter(schedule: ScheduleUpload, scheduleStatuses: number[], limitWarningMode: boolean): boolean {\r\n if (scheduleStatuses.length == 0) {\r\n return true; // #NoFilter\r\n }\r\n\r\n // see if the schedule passes any of the statuses the user \r\n for (var scheduleStatus of scheduleStatuses){\r\n switch (scheduleStatus) {\r\n case SCHEDULE_STATUS_FILTERS.SUCCESS:\r\n if (schedule.successfullySubmitted && !limitWarningMode)\r\n return true;\r\n else break;\r\n case SCHEDULE_STATUS_FILTERS.ERRORS:\r\n if (schedule.submittedWithErrors && !limitWarningMode)\r\n return true;\r\n else break;\r\n case SCHEDULE_STATUS_FILTERS.NOT_SUBMITTED:\r\n // everything is not submitted with limit-warning-mode\r\n if (schedule.notSubmitted || limitWarningMode)\r\n return true;\r\n else break;\r\n case SCHEDULE_STATUS_FILTERS.LIMIT_WARNING:\r\n if (schedule.hasLimitWarning)\r\n return true;\r\n else break;\r\n case SCHEDULE_STATUS_FILTERS.BELOW_FIXED:\r\n if (schedule.hasBelowFixed && !limitWarningMode)\r\n return true;\r\n else break;\r\n }\r\n }\r\n\r\n // nothing passed\r\n return false;\r\n } \r\n\r\n static passesSpecificErrorFilter(schedule: ScheduleUpload, specificError: number) {\r\n if (specificError == null) { // #NoFilter\r\n return true;\r\n }\r\n if (specificError == 1 && schedule.hasBelowFixed) {\r\n return true;\r\n }\r\n if (specificError == 2 && schedule.hasLimitWarning) {\r\n return true;\r\n }\r\n\r\n //ok we know it's a flowdate error. See if the schedule has it\r\n return schedule.DynamicSchedule.FlowDateValidation != null && schedule.DynamicSchedule.FlowDateValidation.some((error) => {\r\n return error.Message == specificError;\r\n });\r\n }\r\n\r\n static passesCustomerSearchFilter(schedule: ScheduleUpload, searchText: string): boolean {\r\n return searchText == null || searchText == '' || schedule.DynamicSchedule.Point.toLowerCase().indexOf(searchText.toLowerCase()) != -1;\r\n }\r\n\r\n static passesCustomerPointFilter(schedule: ScheduleUpload, customerPoints: string[]) {\r\n return customerPoints.length == 0 || customerPoints.filter((point) => {\r\n return point.toLowerCase() == schedule.DynamicSchedule.Point.toLowerCase();\r\n }).length != 0;\r\n }\r\n\r\n static passesSubmitterFilter(schedule: ScheduleArchive, submitters: string[]) {\r\n return submitters.length == 0 || submitters.filter((submitter) => {\r\n return submitter.toLowerCase() == schedule.SubmittedBy.toLowerCase();\r\n }).length != 0;\r\n }\r\n\r\n static passesDOWFilter(schedule: ScheduleArchive, dows: string[]){\r\n return dows.length == 0 || dows.filter((dow) => {\r\n return dow.toLowerCase() == schedule.DOW.toLowerCase();\r\n }).length != 0;\r\n }\r\n\r\n static passesFinalFlagFilter(schedule: ScheduleArchive, finals: boolean[]) {\r\n return finals.length == 0 || finals.filter((final) => {\r\n return final == schedule.isFinal;\r\n }).length != 0;\r\n }\r\n\r\n static passesFlowDateFilter(schedule: ScheduleUpload, flowDates: string[]) {\r\n return flowDates.length == 0 || flowDates.indexOf(schedule.DynamicSchedule.FlowDate) != -1;\r\n }\r\n\r\n\r\n\r\n static sortSchedules(scheduleUploadList: any, filter: IScheduleUploadFilter) {\r\n var customerPointComparator = (scheduleA: ScheduleUpload, scheduleB: ScheduleUpload) => {\r\n if (filter.customerPointSort == \"ASC\") {\r\n return scheduleA.DynamicSchedule.Point.toLowerCase() > scheduleB.DynamicSchedule.Point.toLowerCase() ? 1 : -1;\r\n }\r\n else if (filter.customerPointSort == \"DESC\") {\r\n return scheduleA.DynamicSchedule.Point.toLowerCase() > scheduleB.DynamicSchedule.Point.toLowerCase() ? -1 : 1;\r\n }\r\n };\r\n var flowDateComparator = (scheduleA: ScheduleUpload, scheduleB: ScheduleUpload) => {\r\n if (filter.flowDateSort == \"ASC\") {\r\n return scheduleA.DynamicSchedule.FlowDateValue > scheduleB.DynamicSchedule.FlowDateValue ? 1 : -1;\r\n }\r\n else if (filter.flowDateSort == \"DESC\") {\r\n return scheduleA.DynamicSchedule.FlowDateValue > scheduleB.DynamicSchedule.FlowDateValue ? -1 : 1;\r\n }\r\n };\r\n var timestampComparator = (scheduleA: ScheduleArchive, scheduleB: ScheduleArchive) => {\r\n if (filter.uploadTimestampSort == \"ASC\") {\r\n return scheduleA.UploadDateTimeValue > scheduleB.UploadDateTimeValue ? 1 : -1;\r\n }\r\n else if (filter.uploadTimestampSort == \"DESC\") {\r\n return scheduleA.UploadDateTimeValue > scheduleB.UploadDateTimeValue ? -1 : 1;\r\n }\r\n };\r\n var dowComparator = (scheduleA: ScheduleArchive, scheduleB: ScheduleArchive) => {\r\n if (filter.DOWSort == \"ASC\") {\r\n return WeekdayStrings.indexOf(scheduleA.DOW) > WeekdayStrings.indexOf(scheduleB.DOW) ? 1 : -1;\r\n }\r\n else if (filter.DOWSort == \"DESC\") {\r\n return WeekdayStrings.indexOf(scheduleA.DOW) > WeekdayStrings.indexOf(scheduleB.DOW) ? -1 : 1; \r\n }\r\n };\r\n var submitterComparator = (scheduleA: ScheduleArchive, scheduleB: ScheduleArchive) => {\r\n if (filter.submittersSort == \"ASC\") {\r\n return scheduleA.SubmittedBy.toLowerCase() > scheduleB.SubmittedBy.toLowerCase() ? 1 : -1;\r\n }\r\n else if (filter.submittersSort == \"DESC\") {\r\n return scheduleA.SubmittedBy.toLowerCase() > scheduleB.SubmittedBy.toLowerCase() ? -1 : 1;\r\n }\r\n };\r\n\r\n \r\n \r\n \r\n if (filter.customerPointSort !== null && filter.flowDateSort !== null && filter.uploadTimestampSort == null) {\r\n // sort point THEN date\r\n scheduleUploadList.sort((scheduleA: ScheduleUpload, scheduleB: ScheduleUpload) => {\r\n if (scheduleA.DynamicSchedule.Point.toLowerCase() == scheduleB.DynamicSchedule.Point.toLowerCase()) {\r\n return flowDateComparator(scheduleA, scheduleB);\r\n } else {\r\n return customerPointComparator(scheduleA, scheduleB);\r\n }\r\n });\r\n } else if (filter.customerPointSort !== null && filter.flowDateSort !== null && filter.uploadTimestampSort !== null) {\r\n }\r\n else if (filter.customerPointSort !== null) {\r\n scheduleUploadList.sort(customerPointComparator);\r\n } else if (filter.flowDateSort !== null) {\r\n scheduleUploadList.sort(flowDateComparator);\r\n } else if (filter.uploadTimestampSort !== null) {\r\n scheduleUploadList.sort(timestampComparator);\r\n } else if (filter.DOWSort !== null) {\r\n scheduleUploadList.sort(dowComparator);\r\n } else if (filter.submittersSort !== null) {\r\n scheduleUploadList.sort(submitterComparator);\r\n } \r\n\r\n }\r\n\r\n\r\n}\r\n","import { Component, Input } from '@angular/core';\r\nimport { ScheduleUploadService } from './schedule-upload.service';\r\nimport { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'\r\n\r\n@Component({\r\n selector: 'schedule-upload-error-dialog',\r\n template: require('./schedule-upload-error-dialog.component.html')\r\n})\r\n\r\nexport class ScheduleUploadErrorDialogComponent {\r\n @Input() userId: string;\r\n @Input() uploadId: number;\r\n showSpinnerProceed: boolean = false;\r\n showSpinnerCancel: boolean = false;\r\n constructor(public scheduleUploadService: ScheduleUploadService, private activeModal: NgbActiveModal) { }\r\n\r\n /**\r\n * Confirm schedule upload and display validation page\r\n */\r\n proceed() {\r\n this.showSpinnerProceed = true;\r\n this.scheduleUploadService.postScheduleWithWarnings(this.userId, this.uploadId, true).subscribe(result => {\r\n this.showSpinnerProceed = false;\r\n console.log('postScheduleWithWarnings: ', result);\r\n this.activeModal.close(false);\r\n }); \r\n }\r\n\r\n /**\r\n * Cancel schedule upload and show UI\r\n */\r\n cancel() {\r\n this.showSpinnerCancel = true;\r\n this.scheduleUploadService.postScheduleWithWarnings(this.userId, this.uploadId, false).subscribe(result => {\r\n this.showSpinnerCancel = false;\r\n console.log('postScheduleWithWarnings: ', result);\r\n this.activeModal.close(true);\r\n });\r\n }\r\n}","import { Observable, Subject } from \"rxjs\";\r\n\r\nexport class EventService {\r\n event: Subject;\r\n event$: Observable;\r\n\r\n constructor() {\r\n this.event = new Subject();\r\n this.event$ = this.event.asObservable();\r\n }\r\n\r\n public subscribeEvent(): Observable {\r\n return this.event$;\r\n }\r\n\r\n public emitEvent(ev: string) {\r\n this.event.next(ev);\r\n }\r\n}","import { Component, OnInit, ViewChild, Renderer2, ElementRef, OnDestroy } from '@angular/core';\r\nimport { Router, ActivatedRoute } from '@angular/router';\r\nimport { Observable, Subscription } from 'rxjs';\r\nimport { Store } from '@ngrx/store';\r\nimport { AppData } from '../../app.data'\r\nimport { IScheduleUploadModel, IScheduleUploadBundle } from './schedule-upload.reducer';\r\nimport { ScheduleUploadService } from './schedule-upload.service';\r\nimport { ValidationMessages } from '../shared/schedule-validation.service';\r\nimport { SCHEDULE_STATUS_FILTERS } from '../shared/schedule-filter.service';\r\nimport { AuthenticationService } from '../../authentication/authentication.service';\r\nimport { ScheduleUploadErrorDialogComponent } from './schedule-upload-error-dialog.component';\r\nimport { Configuration } from '../../app.configuration';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';\r\nimport { EventService } from '../../shared/services/event.service';\r\nimport { Subject } from 'rxjs';\r\nimport { DATEPICKER_FORMAT } from '../../shared/datepicker/datepicker-format.token';\r\n\r\nlet styles = String(require('./schedule-upload.component.css'));\r\n\r\n@Component({\r\n selector: 'schedule-upload',\r\n template: require('./schedule-upload.component.html'),\r\n styles: [styles],\r\n providers: [\r\n // Overwrite the token strictly for this component subtree\r\n { provide: DATEPICKER_FORMAT, useValue: 'YYYY-MM-DD' }\r\n ]\r\n})\r\n\r\nexport class ScheduleUploadComponent implements OnInit, OnDestroy{\r\n SCHEDULE_STATUS_FILTERS: Object; // enum\r\n fileUploadOptions: IgUpload;\r\n scheduleUploadModel: Observable;\r\n validationMessages: Object;\r\n userEmail: string;\r\n uploadID: number; // Optional URL param to load a specific upload\r\n unloadListener: Function;\r\n unsavedChangesExist: boolean = false;\r\n filterByScheduleStatus: (number) => void;\r\n filterByCustomerSearch: (string) => void;\r\n clearCustomerSearch: (any) => void;\r\n filterBySpecificError: (number) => void;\r\n selectedFiles: FileList | null = null;\r\n isDashboardHidden: boolean = false;\r\n schedulelistTableClass: string = 'schedule-upload-list-db-expanded';\r\n modalReference: NgbModalRef;\r\n @ViewChild('fileUpload') fileUploadRef: ElementRef;\r\n scheduleEventSubscription: Subscription;\r\n eventSubscription: Subscription;\r\n isUploading: boolean = false;\r\n newlyUploadID: number = 0;\r\n\r\n constructor(public store: Store,\r\n private scheduleUploadService: ScheduleUploadService,\r\n private auth: AuthenticationService,\r\n private route: ActivatedRoute,\r\n private renderer: Renderer2,\r\n private loggedInService: LoggedInUserService,\r\n private eventService: EventService,\r\n private modalService: NgbModal) {\t\r\n\r\n this.SCHEDULE_STATUS_FILTERS = SCHEDULE_STATUS_FILTERS;\r\n\r\n this.scheduleUploadModel = scheduleUploadService.scheduleUploadModel;\r\n\r\n this.scheduleEventSubscription = this.scheduleUploadModel.subscribe((updated: IScheduleUploadModel) => {\r\n // flag to be used to determine whether we should prompt for any unsaved changes\r\n\r\n if (updated != undefined) {\r\n if (updated.isNewUpload) {\r\n var hasLimitWarning = updated.filteredSchedules.some((s) => { return s.hasLimitWarning; });\r\n if (hasLimitWarning && this.newlyUploadID > 0 && updated.uploadID == this.newlyUploadID) {\r\n this.newlyUploadID = 0;\r\n this.modalReference = this.modalService.open(ScheduleUploadErrorDialogComponent);\r\n this.modalReference.componentInstance.userId = this.userEmail;\r\n this.modalReference.componentInstance.uploadId = updated.uploadID;\r\n this.modalReference.result.then((result) => {\r\n console.log(`Closed with: ${result}`);\r\n this.store.dispatch({ type: 'SET_LIMIT_WARNING_MODE', payload: result });\r\n }, (reason) => {\r\n console.log(`Dismissed ${reason}`);\r\n });\r\n }\r\n }\r\n\r\n this.unsavedChangesExist = updated.isDirty;\r\n\r\n if (updated.isDirty && this.unloadListener == undefined) {\r\n // add the unload event\r\n this.unloadListener = this.renderer.listen('window', 'beforeunload', (event) => {\r\n let msg: string = 'Are you sure you want to leave this page? You have unsubmitted changes to schedule quantities.'\r\n event = event || window.event;\r\n\r\n // For IE and Firefox prior to version 4\r\n if (event) {\r\n event.returnValue = msg;\r\n }\r\n\r\n // For Safari\r\n //return msg;\r\n });\r\n } else if (!updated.isDirty) {\r\n if (this.unloadListener != undefined)\r\n this.unloadListener();\r\n }\r\n }\r\n\r\n });\r\n\r\n this.eventSubscription = this.eventService.subscribeEvent().subscribe((event) => {\r\n switch (event) {\r\n case Configuration.DestroyunloadhandlersEvent:\r\n if (this.unloadListener != undefined)\r\n this.unloadListener();\r\n this.unsavedChangesExist = false;\r\n break;\r\n }\r\n });\r\n \r\n this.validationMessages = ValidationMessages;\r\n\r\n // grab logged in user and fetch previous schedules\r\n if (auth.loggedInUser != null) {\r\n this.userEmail = this.auth.loggedInUser.profile.preferred_username;\r\n } \r\n\r\n this.fileUploadOptions = { \r\n uploadUrl: PORTAL_API_PATH + 'DynamicSchedulingEntries/UploadDynamicSchedule',\r\n autostartupload: true, \r\n allowedExtensions: ['xlsx'],\r\n errorMessageValidatingFileExtension: 'INVALID_EXTENSION',\r\n onError: function (e, args) {\r\n if (args.errorMessage == 'INVALID_EXTENSION') {\r\n store.dispatch({ type: 'SET_INVALID_EXTENSION_MESSAGE', payload: true});\r\n }\r\n store.dispatch({ type: 'HIDE_LOAD_BAR' }); \r\n },\r\n fileSelecting: (e, args) => {\r\n store.dispatch({ type: 'SET_INVALID_EXTENSION_MESSAGE', payload: false });\r\n },\r\n fileExtensionsValidating: function(e, args) {\r\n if (args.fileExtension.toLowerCase().indexOf('xlsm') !== -1)\r\n store.dispatch({ type: 'SET_XLSM_EXTENSION_MESSAGE', payload: true});\r\n else\r\n store.dispatch({ type: 'SET_XLSM_EXTENSION_MESSAGE', payload: false});\r\n },\r\n labelUploadButton: 'Upload Schedule', \r\n labelAddButton: 'Upload Schedule',\r\n labelClearAllButton: 'Cancel',\r\n onFormDataSubmit: ((e, args) => { // fileUploaded does not work\r\n this.newlyUploadID = 0;\r\n store.dispatch({ type: 'SHOW_LOAD_BAR'}); \r\n $('#scheduleUploadWidget').igUpload(\"addDataField\", args.formData, { \"name\": \"userEmail\", \"value\": this.userEmail });\r\n\r\n let authToken = 'Bearer ' + this.auth.GetToken(); \r\n args.xhr.setRequestHeader('Authorization', authToken);\r\n\r\n args.xhr.onreadystatechange = function () {\r\n if (args.xhr.readyState === XMLHttpRequest.DONE) {\r\n let data = args.xhr.responseText;\r\n let schedulesFromServer: any[] = JSON.parse(data);\r\n\r\n let dataBundle: IScheduleUploadBundle = {\r\n ScheduleUploadInfo: schedulesFromServer,\r\n UploadTime: null, // clear out the last-submitted time\r\n UploadID: schedulesFromServer[0].UploadID,\r\n Outcome: null,\r\n isNewUpload: true\r\n };\r\n store.dispatch({ type: 'SET_DYNAMIC_SCHEDULES', payload: dataBundle }); \r\n }\r\n }\r\n })\r\n };\r\n\r\n this.filterByScheduleStatus = (status: number) => {\r\n // purposefully use a different field name scheduleStatuses => scheduleStatus cuz we don't want to overwrite the array\r\n store.dispatch({ type: 'UPDATE_SCHEDULE_FILTER', payload: { scheduleStatus: status } });\r\n };\r\n\r\n this.filterBySpecificError = (error: number) => {\r\n store.dispatch({ type: 'UPDATE_SCHEDULE_FILTER', payload: { specificError: error } });\r\n };\r\n }\r\n\r\n ngOnInit() {\r\n let queryParams: any = this.route.queryParams; // need to cast to 'any' - '.value' isn't in the tsd for rxjs Observable \r\n this.uploadID = +queryParams.value['upload_id'] || null;\r\n\r\n // see if the Noble API is available and grab the previous submission if so\r\n let email: string;\r\n if (this.loggedInService.isImpersonate) {\r\n email = this.loggedInService.impersonateEmail;\r\n }\r\n else {\r\n email = (this.loggedInService.getLoggedInUser()).email\r\n }\r\n\r\n this.scheduleUploadService.initializeDynamicScheduling(this.uploadID, email);\r\n }\r\n\r\n ngOnDestroy() {\r\n if (this.scheduleEventSubscription) {\r\n this.scheduleEventSubscription.unsubscribe();\r\n }\r\n if (this.eventSubscription) {\r\n this.eventSubscription.unsubscribe();\r\n }\r\n }\r\n\r\n // allow unquestioned navigation away from schedule upload screen only if there are no pending changes\r\n canDeactivate() {\r\n return ! this.unsavedChangesExist;\r\n }\r\n\r\n uploadFile(): void {\r\n this.fileUploadRef.nativeElement.click();\r\n }\r\n\r\n onFileSelected(event) {\r\n\r\n if (event.target.files.length > 0) {\r\n if (!this.validatingFileExtension(event.target.files[0].name)) {\r\n return;\r\n }\r\n\r\n this.isUploading = true;\r\n this.store.dispatch({ type: 'SHOW_LOAD_BAR' });\r\n\r\n let formData: FormData = new FormData();\r\n formData.append('userEmail', this.userEmail);\r\n formData.append('file', event.target.files[0], event.target.files[0].name);\r\n\r\n this.scheduleUploadService.uploadDynamicSchedule(formData).subscribe(\r\n (response) => {\r\n this.store.dispatch({ type: 'HIDE_LOAD_BAR' });\r\n let schedules: any = response;\r\n\r\n var dataBundle: IScheduleUploadBundle = {\r\n ScheduleUploadInfo: schedules,\r\n UploadTime: null, // clear out the last-submitted time\r\n UploadID: schedules[0].UploadID,\r\n Outcome: null,\r\n isNewUpload: true\r\n };\r\n this.isUploading = false;\r\n this.newlyUploadID = dataBundle.UploadID;\r\n this.store.dispatch({ type: 'SET_DYNAMIC_SCHEDULES', payload: dataBundle });\r\n },\r\n (error) => {\r\n console.log(error);\r\n this.isUploading = false;\r\n this.store.dispatch({ type: 'HIDE_LOAD_BAR' });\r\n }\r\n )\r\n }\r\n }\r\n\r\n validatingFileExtension(filename: string): boolean {\r\n const parts = filename.split('.');\r\n let extension = '';\r\n\r\n if (parts.length > 1) {\r\n extension = parts.pop();\r\n extension = extension.toLowerCase();\r\n }\r\n\r\n if (extension.indexOf('xlsm') !== -1) {\r\n this.store.dispatch({ type: 'SET_XLSM_EXTENSION_MESSAGE', payload: true });\r\n return false;\r\n }\r\n else {\r\n this.store.dispatch({ type: 'SET_XLSM_EXTENSION_MESSAGE', payload: false });\r\n }\r\n\r\n if (extension == '' || extension.indexOf('xlsx') == -1) {\r\n this.store.dispatch({ type: 'SET_INVALID_EXTENSION_MESSAGE', payload: true });\r\n return false;\r\n }\r\n \r\n return true;\r\n }\r\n\r\n handleFileInput(event: any) {\r\n this.selectedFiles = event.target.files;\r\n }\r\n\r\n toggleDashboard(event: boolean) {\r\n this.isDashboardHidden = event;\r\n this.schedulelistTableClass = this.isDashboardHidden ? 'schedule-upload-list-db-collapsed': 'schedule-upload-list-db-expanded';\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { Configuration } from '../../app.configuration'\r\n\r\n\r\n@Component({\r\n selector: 'help-schedule',\r\n template: require('./help-schedule.component.html'),\r\n styles: [require('./help-schedule.component.css').toString()]\r\n})\r\n\r\nexport class HelpScheduleComponent {\r\n public serverUrl: string;\r\n\r\n constructor(private configuration: Configuration) { \r\n this.serverUrl = this.configuration.JsAppServerUrl;\r\n }\r\n dynSchedEmail: string = DYNAMIC_SCHEDULING_EMAIL;\r\n dynSchedPhone: string = DYNAMIC_SCHEDULING_PHONE;\r\n}","import { Component, ChangeDetectionStrategy, Input, OnInit, ViewChild } from '@angular/core';\r\nimport type { IScheduleUploadFilter } from '../shared/schedule-upload-filter.model';\r\n\r\nimport { Store } from '@ngrx/store';\r\nimport { AppData } from '../../app.data';\r\nimport { DatePickerPopUpComponent } from '../../shared/datepicker/datepicker-popup.component';\r\nimport 'bootstrap/dist/js/bootstrap.bundle';\r\n\r\nlet styles = String(require('../schedule-upload/schedule-upload.component.css'));\r\nexport const HE_RANGE: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\r\n\r\n@Component({\r\n selector: 'schedule-list-header',\r\n template: require('./schedule-list-header.component.html'),\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n styles: [styles]\r\n})\r\n\r\nexport class ScheduleListHeader implements OnInit {\r\n filterAction: string;\r\n HE_RANGE: number[];\r\n datepickerWidth: number = 125;\r\n\r\n @Input() isArchiveView: boolean;\r\n @Input() tableClass: string;\r\n @Input() containerID: string;\r\n @Input() scheduleUploadFilter: IScheduleUploadFilter;\r\n @Input() scheduleCustomerPoints: string[];\r\n @Input() scheduleFlowDates: string[];\r\n @Input() scheduleSubmitters: string[];\r\n @Input() scheduleDOWs: string[];\r\n @Input() scheduleFinals: boolean[];\r\n @ViewChild('flowStartPicker') flowStartPickerRef: DatePickerPopUpComponent;\r\n @ViewChild('flowEndPicker') flowEndPickerRef: DatePickerPopUpComponent;\r\n @ViewChild('uploadStartPicker') uploadStartPickerRef: DatePickerPopUpComponent;\r\n @ViewChild('uploadEndPicker') uploadEndPickerRef: DatePickerPopUpComponent;\r\n\r\n private flowFromDate: string | null;\r\n private flowToDate: string | null;\r\n private uploadFromDate: string | null;\r\n private uploadToDate: string | null;\r\n\r\n constructor(public store: Store) {\r\n this.HE_RANGE = HE_RANGE;\r\n }\r\n\r\n public uploadStartDateOptions: any = {\r\n width: this.datepickerWidth,\r\n valueChanged: (event, control) => {\r\n let uploadStart = new Date(control.newValue.setHours(0,0,0,0)); \r\n this.filterUploadStart(uploadStart);\r\n }\r\n }\r\n public uploadEndDateOptions: any = {\r\n width: this.datepickerWidth,\r\n valueChanged: (event, control) => {\r\n let uploadEnd = new Date(control.newValue.setHours(0,0,0,0)); \r\n this.filterUploadEnd(uploadEnd);\r\n }\r\n }\r\n public flowStartDateOptions: any = {\r\n width: this.datepickerWidth,\r\n valueChanged: (event, control) => {\r\n let flowStart = new Date(control.newValue.setHours(0,0,0,0)); \r\n this.filterFlowStart(flowStart);\r\n }\r\n }\r\n public flowEndDateOptions: any = {\r\n width: this.datepickerWidth,\r\n valueChanged: (event, control) => {\r\n let flowEnd = new Date(control.newValue.setHours(0,0,0,0)); \r\n this.filterFlowEnd(flowEnd);\r\n }\r\n }\r\n\r\n\r\n public stopPropagationFunction(event) {\r\n event.stopPropagation();\r\n }\r\n\r\n public clearUploadRange(){\r\n this.uploadFromDate = \"\";\r\n this.uploadToDate = \"\";\r\n this.filterUploadStart(\"\");\r\n this.filterUploadEnd(\"\");\r\n this.uploadStartPickerRef.reset();\r\n this.uploadEndPickerRef.reset();\r\n }\r\n\r\n public clearFlowRange(){\r\n this.flowFromDate = \"\";\r\n this.flowToDate = \"\";\r\n this.filterFlowStart(\"\");\r\n this.filterFlowEnd(\"\");\r\n this.flowStartPickerRef.reset();\r\n this.flowEndPickerRef.reset();\r\n }\r\n\r\n\r\n public filterUploadStart(uploadStart) {\r\n this.store.dispatch({ type: this.filterAction, payload: { addUploadStart: uploadStart } });\r\n }\r\n public filterUploadEnd(uploadEnd) {\r\n this.store.dispatch({ type: this.filterAction, payload: { addUploadEnd: uploadEnd } });\r\n }\r\n public filterFlowStart(flowStart) {\r\n this.store.dispatch({ type: this.filterAction, payload: { addFlowStart: flowStart } }); \r\n }\r\n public filterFlowEnd(flowEnd) {\r\n this.store.dispatch({ type: this.filterAction, payload: { addFlowEnd: flowEnd } }); \r\n }\r\n\r\n\r\n public filterByFinalFlag = (final:boolean, event:any) => {\r\n this.store.dispatch({ type: this.filterAction, payload: {addFinal: final} });\r\n event.stopPropagation();\r\n }\r\n\r\n public filterByCustomerPoint = (point:string, event:any) => {\r\n this.store.dispatch({type: this.filterAction, payload:{addCustomerPoint: point}});\r\n event.stopPropagation(); // don't close the DDL on click\r\n }\r\n\r\n public filterByFlowDate = (flowDate: string, event: any) => {\r\n this.store.dispatch({type:'UPDATE_SCHEDULE_FILTER', payload: {addFlowDate: flowDate}});\r\n event.stopPropagation(); // don't close the DDL on click\r\n }\r\n\r\n public filterByDOW = (dow:string, event:any) => {\r\n this.store.dispatch({ type: this.filterAction, payload: {addDOW: dow} });\r\n event.stopPropagation();\r\n }\r\n\r\n public filterBySubmitter = (submitter:string, event:any) => {\r\n this.store.dispatch({type: this.filterAction, payload:{addSubmitter: submitter}});\r\n event.stopPropagation(); // don't close the DDL on click\r\n }\r\n\r\n public sortTimestamp = () => {\r\n this.store.dispatch({ type: this.filterAction, payload: { sortTimestamp: true } });\r\n }\r\n public sortCustomerPoint = () => {\r\n this.store.dispatch({ type: this.filterAction, payload: { sortCustomerPoint: true } });\r\n }\r\n\r\n public sortFlowDate = () => {\r\n this.store.dispatch({ type: this.filterAction, payload: { sortFlowDate: true } });\r\n }\r\n public sortDOW = () => {\r\n this.store.dispatch({ type: this.filterAction, payload: { sortDOW: true } });\r\n }\r\n public sortSubmitter = () => {\r\n this.store.dispatch({ type: this.filterAction, payload: { sortSubmitter: true } });\r\n }\r\n\r\n\r\n\r\n\r\n ngOnInit() {\r\n this.filterAction = this.isArchiveView ? \"UPDATE_ARCHIVE_SCHEDULE_FILTER\" : \"UPDATE_SCHEDULE_FILTER\";\r\n }\r\n\r\n ngAfterViewInit() {\r\n }\r\n\r\n public flowFromDateChange(event: string) {\r\n this.flowFromDate = event;\r\n this.filterFlowStart(this.flowFromDate);\r\n }\r\n\r\n public flowToDateChange(event: string) {\r\n this.flowToDate = event;\r\n this.filterFlowEnd(this.flowToDate);\r\n }\r\n\r\n public uploadFromDateChange(event: string) {\r\n this.uploadFromDate = event;\r\n this.filterUploadStart(this.uploadFromDate);\r\n }\r\n\r\n public uploadToDateChange(event: string) {\r\n this.uploadToDate = event;\r\n this.filterUploadEnd(this.uploadToDate);\r\n }\r\n}","import { Injectable } from '@angular/core';\r\nimport { Store } from '@ngrx/store';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { ApiGatewayService } from '../../shared/services/api-gateway.service';\r\nimport { IScheduleArchiveModel, IScheduleArchiveBundle } from './schedule-archive.model';\r\nimport { AppData } from '../../app.data';\r\n\r\n\r\n@Injectable()\r\nexport class ScheduleArchiveService {\r\n scheduleArchiveModel: Observable;\r\n hasGottenUploadHistory: boolean;\r\n\r\n constructor(private store: Store,\r\n private apiGateway: ApiGatewayService) {\r\n \r\n this.hasGottenUploadHistory = false;\r\n this.scheduleArchiveModel = store.select(appData => appData.scheduleArchiveModel);\r\n }\r\n\r\n public initializeDynamicScheduling(email: string) {\r\n this.hasGottenUploadHistory = false;\r\n this.apiGateway.get(PORTAL_API_PATH + 'DynamicSchedulingEntries/IsDynamicSchedulingAvailable', null)\r\n .subscribe(isAvailable => {\r\n this.store.dispatch({ type: 'SET_DYNAMIC_SCHEDULING_AVAILABLE_FOR_ARCHIVE', payload: isAvailable });\r\n\r\n if (isAvailable && email != null) {\r\n this.getUploadHistory(email);\r\n }\r\n });\r\n }\r\n\r\n public getUploadHistory(email: string) {\r\n this.apiGateway.get(PORTAL_API_PATH + 'DynamicSchedulingArchive/GetUploadHistory?userEmail=' + encodeURIComponent(email), null)\r\n .subscribe(data => {\r\n let uploadBundle: any = data;\r\n let fullUploadBundle: IScheduleArchiveBundle = {\r\n ScheduleArchiveUploadInfo: uploadBundle.Schedules\r\n };\r\n this.hasGottenUploadHistory = true;\r\n this.store.dispatch({ type: 'SET_ARCHIVE_SCHEDULES', payload: fullUploadBundle });\r\n });\r\n }\r\n}\r\n","import { Component, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';\r\nimport { Store } from '@ngrx/store';\r\nimport { Observable } from 'rxjs';\r\nimport { AppData } from '../../app.data';\r\nimport { ValidationMessages } from './schedule-validation.service';\r\nimport { AppGlobalsComponent } from '../../shared/app-globals.component';\r\nimport { IScheduleUploadModel } from '../schedule-upload/schedule-upload.reducer';\r\nimport { ScheduleUploadService } from '../schedule-upload/schedule-upload.service';\r\nimport { IScheduleArchiveModel } from '../schedule-archive/schedule-archive.model';\r\nimport { ScheduleArchiveService } from '../schedule-archive/schedule-archive.service';\r\n/*import 'rxjs/Rx';*/\r\nimport * as _ from 'lodash';\r\nimport * as moment from 'moment';\r\nimport { Tooltip } from '../../shared/directives/tooltip.component'\r\nimport 'bootstrap/dist/js/bootstrap.bundle';\r\n\r\n@Component({\r\n selector: 'schedule-list-search-bar',\r\n template: require('./schedule-list-search-bar.component.html')\r\n})\r\nexport class ScheduleListSearchBarComponent {\r\n filterAction: string;\r\n resetAction: string;\r\n isExportingToCSV: boolean = false;\r\n anyFiltersPresent: boolean = false;\r\n scheduleUploadModel: Observable;\r\n scheduleArchiveModel: Observable;\r\n toggled: boolean = false;\r\n\r\n @Input() isArchiveView: boolean;\r\n @Output() toggleEvent = new EventEmitter();\r\n @ViewChild(Tooltip) toggleBtnDirective: Tooltip;\r\n constructor(public store: Store, private globals: AppGlobalsComponent, private scheduleUploadService: ScheduleUploadService, private scheduleArchiveService: ScheduleArchiveService) {\r\n this.scheduleUploadModel = scheduleUploadService.scheduleUploadModel;\r\n this.scheduleArchiveModel = scheduleArchiveService.scheduleArchiveModel;\r\n this.anyFiltersPresent = false;\r\n\r\n this.scheduleArchiveModel.subscribe((updated: IScheduleArchiveModel) => {\r\n this.anyFiltersPresent = updated.scheduleUploadFilter.isAnyFilterPresent;\r\n });\r\n this.scheduleUploadModel.subscribe((updated: IScheduleUploadModel) => {\r\n this.anyFiltersPresent = updated.scheduleUploadFilter.isAnyFilterPresent;\r\n });\r\n }\r\n\r\n public filterByCustomerSearch = (searchText: string) => {\r\n searchText = searchText.trim();\r\n if (searchText.length > 2 || searchText === '') {\r\n this.store.dispatch({ type: this.filterAction, payload: { customerSearch: searchText } });\r\n }\r\n }\r\n\r\n public clearCustomerSearch = (searchElement: any) => {\r\n // clear the search in the gui and in the model. No 2-way binding so we have to do this womop womp\r\n searchElement.value = '';\r\n this.store.dispatch({ type: this.filterAction, payload: { customerSearch: '' } });\r\n }\r\n\r\n public resetFilters() {\r\n this.store.dispatch({ type: this.resetAction});\r\n $('#search').first().val('');\r\n $('#clearFlowDate').first().click();\r\n $('#clearTimestamp').first().click();\r\n }\r\n\r\n ngOnInit() {\r\n this.filterAction = this.isArchiveView ? 'UPDATE_ARCHIVE_SCHEDULE_FILTER' : 'UPDATE_SCHEDULE_FILTER';\r\n this.resetAction = this.isArchiveView ? 'RESET_ARCHIVE_FILTERS' : 'RESET_DYNAMIC_SCHEDULING';\r\n this.anyFiltersPresent = false;\r\n }\r\n\r\n toggleExpandIcon(elem: any): void {\r\n\r\n this.toggleBtnDirective.hide();\r\n this.toggled = !this.toggled;\r\n this.toggleEvent.emit(this.toggled);\r\n\r\n }\r\n\r\n /** Export the submittal history data in CSV format for logged in user */\r\n exportSubmittalHistoryToCSV() {\r\n this.isExportingToCSV = true;\r\n this.store.select(appData => appData.scheduleArchiveModel.scheduleUploadList).subscribe((data) => {\r\n if (this.isExportingToCSV) {\r\n this.downloadSubmittalHistory(data);\r\n this.isExportingToCSV = false;\r\n }\r\n });\r\n }\r\n\r\n exportFilteredSubmittalHistoryToCSV() {\r\n this.isExportingToCSV = true;\r\n this.store.select(appData => appData.scheduleArchiveModel.filteredSchedules.length > 0 ?\r\n appData.scheduleArchiveModel.filteredSchedules : appData.scheduleArchiveModel.scheduleUploadList).subscribe((data) => {\r\n if (this.isExportingToCSV) {\r\n this.downloadSubmittalHistory(data);\r\n this.isExportingToCSV = false;\r\n }\r\n });\r\n }\r\n\r\n /** Download submittal history data for logged in user. Provide save as option for all 4 browsers\r\n * 1. Internet Explorer\r\n * 2. Edge\r\n * 3. Chrome\r\n * 4. Firefox\r\n */\r\n downloadSubmittalHistory(data: any) {\r\n let fileName: string = 'SubmittalHistory.csv';\r\n let csvData = this.convertSubmittalHistoryToCSV(data);\r\n\r\n const nav = window.navigator as any;\r\n if (nav && nav.msSaveBlob) {\r\n let blob = new Blob([csvData]);\r\n nav.msSaveBlob(blob, fileName);\r\n }\r\n else {\r\n let blob = new Blob([csvData], { type: 'text/csv' });\r\n let url = window.URL.createObjectURL(blob);\r\n let a = document.createElement('a');\r\n a.setAttribute('style', 'display:none;');\r\n document.body.appendChild(a);\r\n a.href = url;\r\n a.setAttribute('download', fileName);\r\n a.click();\r\n }\r\n }\r\n\r\n /** Converting submittal history data into csv format. */\r\n convertSubmittalHistoryToCSV(data: any) {\r\n let validationMessages = ValidationMessages;\r\n let str: string = '';\r\n let row: string = '';\r\n let headerRow: string = 'Final,Timestamp,Customer Point,Flow Date,Quantity Type,HE01,HE02,HE03,HE04,HE05,HE06,HE07,HE08,HE09,HE10,HE11,HE12,HE13,HE14,HE15,HE16,HE17,HE18,HE19,HE20,HE21,HE22,HE23,HE24,DOW,Submitted By,Message1';\r\n str += headerRow + '\\r\\n';\r\n\r\n let requestRowMessage: string[];\r\n\r\n _.forEach(data, (v: any) => {\r\n requestRowMessage = [];\r\n row = '';\r\n /** Generating row for requested values */\r\n let timestamp = v.UploadDateStampExcel + ' ' + v.UploadTimeString;\r\n row = v.isFinal + ',' + timestamp + ',' + v.DynamicSchedule.Point + ',' + v.DynamicSchedule.FlowDate + ',Request,';\r\n _.forOwn(v.DynamicSchedule, function (value, key) {\r\n if (key.length <= 4 && key.indexOf('HE', 0) > -1) {\r\n row = row + value.originalValue + ',';\r\n }\r\n /** Error Messages if any */\r\n if (key.indexOf('HEValidation', 0) > -1) {\r\n if (value != null && value.length > 0) {\r\n requestRowMessage.push(validationMessages[value[0].Message].Summary);\r\n }\r\n }\r\n });\r\n row = row + v.DOW + ',' + v.SubmittedBy + ',' + _.join(requestRowMessage, ';');\r\n str += row + '\\r\\n'; /** Request row ends */\r\n /** Final volume row started */\r\n requestRowMessage = [];\r\n row = '';\r\n row = v.isFinal + ',' + timestamp + ',' + v.DynamicSchedule.Point + ',' + v.DynamicSchedule.FlowDate + ',Final Volume,';\r\n _.forOwn(v.FinalSchedule, function (value, key) {\r\n row = row + value + ',';\r\n });\r\n row = row + v.DOW + ',' + v.SubmittedBy + ',' + _.join(requestRowMessage, ';');\r\n str += row + '\\r\\n'; /** Final volume row ends */\r\n });\r\n return str;\r\n }\r\n}\r\n","import { Component, OnInit } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { Store } from '@ngrx/store';\r\n\r\nimport { AppData } from '../../app.data'\r\n\r\nimport { IScheduleArchiveModel } from '../schedule-archive/schedule-archive.model';\r\nimport { ScheduleArchiveService } from '../schedule-archive/schedule-archive.service';\r\nimport { LoggedInUserService } from '../../shared/services/logged-in-user.service';\r\nimport { DATEPICKER_FORMAT } from '../../shared/datepicker/datepicker-format.token';\r\n\r\n@Component({\r\n selector: 'schedule-archive',\r\n template: require('./schedule-archive.component.html'),\r\n styles: [require('./schedule-archive.component.css').toString()],\r\n providers: [\r\n // Overwrite the token strictly for this component subtree\r\n { provide: DATEPICKER_FORMAT, useValue: 'YYYY-MM-DD' }\r\n ]\r\n})\r\n\r\nexport class ScheduleArchiveComponent implements OnInit {\r\n scheduleArchiveModel: Observable;\r\n filterByCustomerSearch: (string) => void;\r\n uploadID: number; // Optional URL param to load a specific upload\r\n\r\n constructor(public store: Store,\r\n private scheduleArchiveService: ScheduleArchiveService,\r\n private loggedInUserService: LoggedInUserService) {\r\n\r\n this.scheduleArchiveModel = scheduleArchiveService.scheduleArchiveModel;\r\n this.scheduleArchiveModel.subscribe((updated: IScheduleArchiveModel) => {\r\n });\r\n }\r\n\r\n ngOnInit() {\r\n // see if the Noble API is available and grab the 2 year sumbission history\r\n let email: string;\r\n if (this.loggedInUserService.isImpersonate) {\r\n email = this.loggedInUserService.impersonateEmail;\r\n }\r\n else {\r\n email = (this.loggedInUserService.getLoggedInUser()).email;\r\n }\r\n this.scheduleArchiveService.initializeDynamicScheduling(email);\r\n }\r\n}","import { Component, ChangeDetectionStrategy, Input, OnChanges, SimpleChanges } from '@angular/core';\r\nimport { IScheduleUploadInfo, ScheduleUpload } from '../schedule-upload/schedule-upload.reducer';\r\nimport type { IScheduleUploadFilter } from '../shared/schedule-upload-filter.model';\r\nimport { ValidationMessages } from '../shared/schedule-validation.service';\r\nimport { HE_RANGE } from './he-range';\r\nimport { ScheduleUploadService } from '../schedule-upload/schedule-upload.service';\r\n\r\nimport { Store } from '@ngrx/store';\r\nimport { AppData } from '../../app.data'\r\n\r\nimport { PaginationInstance } from 'ngx-pagination';\r\n\r\nlet styles = String(require('../schedule-upload/schedule-upload.component.css'));\r\n\r\n@Component({\r\n selector: 'schedule-list-table',\r\n template: require('./schedule-list-table.component.html'),\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n styles: [styles]\r\n})\r\n\r\nexport class ScheduleListTable implements OnChanges {\r\n HE_RANGE: number[];\r\n validationMessages: Object;\r\n\r\n filterByCustomerPoint: (string, boolean) => void;\r\n filterByFlowDate: (string, boolean, any) => void;\r\n\r\n @Input() scheduleUploadList: ScheduleUpload[];\r\n @Input() limitWarningMode: boolean; \r\n @Input() isArchiveView: boolean;\r\n @Input() topPaddingClass: string;\r\n @Input() tableClass: string;\r\n @Input() isDirty: boolean;\r\n @Input() isLoading: boolean;\r\n\r\n public maxSize: number = 10;\r\n public directionLinks: boolean = true;\r\n public pagingConfig: PaginationInstance = {\r\n id: 'archiveSchedules',\r\n itemsPerPage: 5,\r\n currentPage: 1\r\n }\r\n\r\n\r\n constructor(\r\n public store: Store,\r\n public scheduleUploadService: ScheduleUploadService) {\r\n \r\n this.HE_RANGE = HE_RANGE;\r\n this.validationMessages = ValidationMessages;\r\n }\r\n\r\n onPageChange(pageNumber: number){\r\n this.pagingConfig.currentPage = pageNumber;\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n if(this.scheduleUploadList.length <= this.pagingConfig.itemsPerPage) {\r\n this.onPageChange(1); \r\n }\r\n }\r\n\r\n getHEClasses(schedule: ScheduleUpload, he_index: number): Object {\r\n return {\r\n 'clickable': schedule.isEditable,\r\n 'hourly-validation-error':\r\n !this.limitWarningMode && // never show if limitwarningmode\r\n (\r\n (schedule.DynamicSchedule['HEValidation' + he_index] != null && schedule.DynamicSchedule['HEValidation' + he_index].length != 0 && schedule.DynamicSchedule['HEValidation' + he_index][0]['Severity'] == 3)\r\n || schedule.hasFlowDateError //highlight the whole row if there's flowdate validation\r\n ),\r\n 'hourly-validation-warning': schedule.DynamicSchedule['HEValidation' + he_index] != null && schedule.DynamicSchedule['HEValidation' + he_index].length != 0 && schedule.DynamicSchedule['HEValidation' + he_index][0]['Severity'] == 2,\r\n 'vertical-padding-none': schedule.DynamicSchedule['HE' + he_index].isActive,\r\n 'he-highlight-active': schedule.DynamicSchedule['HE' + he_index].isActive,\r\n 'he-highlight-dirty': schedule.DynamicSchedule['HE' + he_index].isDirty && !schedule.DynamicSchedule['HE' + he_index].isActive,\r\n 'he-highlight-error': schedule.DynamicSchedule['HE' + he_index].hasError && !schedule.DynamicSchedule['HE' + he_index].isActive\r\n };\r\n }\r\n\r\n getHEValidationSeverity(schedule: any, he_index: number): number {\r\n var severity = schedule.DynamicSchedule['HEValidation' + he_index] != null && schedule.DynamicSchedule['HEValidation' + he_index].length != 0 ? schedule.DynamicSchedule['HEValidation' + he_index][0]['Severity'] : null;\r\n if (this.limitWarningMode && severity == 3) {\r\n // don't show below-fixed errors if in limit warning mode\r\n severity = null;\r\n }\r\n return severity;\r\n }\r\n\r\n submitHEChanges(event: any, input: string, HE_INDEX: number, schedule: ScheduleUpload) {\r\n this.store.dispatch({\r\n type: 'SUBMIT_HE_CHANGES', payload: { input, HE_INDEX, schedule }\r\n });\r\n }\r\n\r\n inputHandler(event: any, input: string, HE_INDEX: number, schedule: ScheduleUpload) {\r\n //enter key\r\n var key: number = event.keyCode || event.charCode;\r\n if (key == 13) {\r\n this.store.dispatch({\r\n type: 'SUBMIT_HE_CHANGES', payload: { input, HE_INDEX, schedule }\r\n });\r\n }\r\n else {\r\n const acceptableKeys = [\r\n 190,// period\r\n 13, // enter\r\n 8, // backspace\r\n 46, // delete\r\n 37, // left arrow\r\n 38, // up arrow\r\n 39, // right arrow\r\n 40 // down arrow\r\n ];\r\n //reject everything non-numeric except the special characters\r\n return (key >= 48 && key <= 57) || acceptableKeys.indexOf(key) != -1;\r\n }\r\n }\r\n\r\n activateHECell(HE_INDEX: number, schedule: ScheduleUpload, tdElem: any) {\r\n if (!schedule.isEditable) {\r\n return; \r\n }\r\n\r\n this.store.dispatch({\r\n type: 'ACTIVATE_HE_CELL', payload: { HE_INDEX, schedule }\r\n });\r\n\r\n $(tdElem).find('input').focus();\r\n }\r\n\r\n saveScheduleChanges(schedules: ScheduleUpload[]) {\r\n this.scheduleUploadService.saveEditedSchedules(schedules);\r\n }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'schedule-unavailable',\r\n template: require('./schedule-unavailable.component.html')\r\n})\r\nexport class ScheduleUnavailableComponent {\r\n operationsEmail: string;\r\n mailToSubject: string;\r\n\r\n constructor() {\r\n this.operationsEmail = DYNAMIC_SCHEDULING_EMAIL;\r\n this.mailToSubject = 'Support inquiry for dynamic scheduling portal';\r\n }\r\n}\r\n","import { CanDeactivate } from '@angular/router';\r\nimport { ScheduleUploadComponent } from '../dynamic-scheduling/schedule-upload/schedule-upload.component' ;\r\nimport { Observable } from 'rxjs';\r\n\r\n class ScheduleUploadGuard implements CanDeactivate {\r\n\r\n canDeactivate(component: ScheduleUploadComponent) : Observable | boolean {\r\n if (component.canDeactivate()) {\r\n return true;\r\n } else {\r\n return window.confirm('Changes pending submission!\\n\\nAre you sure you want to leave this page? You have unsubmitted changes to schedule quantities.');\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default ScheduleUploadGuard;","import { Routes, RouterModule } from '@angular/router';\r\nimport { ModuleWithProviders } from '@angular/core';\r\n\r\nimport { DynamicSchedulingComponent } from './dynamic-scheduling.component';\r\nimport { ScheduleUploadComponent } from './schedule-upload/schedule-upload.component';\r\nimport { ScheduleArchiveComponent } from './schedule-archive/schedule-archive.component';\r\nimport { HelpScheduleComponent } from './help-schedule/help-schedule.component';\r\nimport { CanActivateAuthGuard } from '../authentication/auth-guard.service';\r\nimport { Configuration } from '../app.configuration';\r\nimport ScheduleUploadGuard from '../authentication/schedule-upload-guard.service';\r\n\r\nconst dynamicSchedulingRoutes: Routes = [\r\n {\r\n path: Configuration.ROUTE_PATHS.DYNAMIC_SCHEDULING,\r\n component: DynamicSchedulingComponent,\r\n data: { title: 'Power Manager', requiredRoles:Configuration.USER_ROLES.SCHEDULER },\r\n canActivate: [CanActivateAuthGuard],\r\n children: [\r\n { path: '', redirectTo: 'schedule-upload', pathMatch: 'full' },\r\n { path: 'help', component: HelpScheduleComponent, data: { title: 'Help' } },\r\n { path: 'schedule-upload', component: ScheduleUploadComponent, data: { title: 'Dynamic Scheduling' }, canDeactivate: [ScheduleUploadGuard] }\r\n ]\r\n }\r\n];\r\n\r\nexport const dynamicSchedulingRouting: ModuleWithProviders = RouterModule.forChild(dynamicSchedulingRoutes);\r\n","import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';\r\nimport { CommonModule } from '@angular/common'; \r\nimport { SharedModule } from '../shared/shared.module';\r\n\r\nimport { DynamicSchedulingComponent } from './dynamic-scheduling.component';\r\nimport { ScheduleUploadComponent } from './schedule-upload/schedule-upload.component';\r\nimport { HelpScheduleComponent } from './help-schedule/help-schedule.component';\r\nimport { ScheduleListHeader } from './shared/schedule-list-header.component';\r\nimport { ScheduleListSearchBarComponent } from './shared/schedule-list-search-bar.component';\r\nimport { ScheduleUploadErrorDialogComponent } from './schedule-upload/schedule-upload-error-dialog.component';\r\nimport { ScheduleArchiveComponent } from './schedule-archive/schedule-archive.component';\r\nimport { ScheduleListTable } from './shared/schedule-list-table.component';\r\nimport { ScheduleUnavailableComponent } from './shared/schedule-unavailable.component';\r\n\r\nimport { dynamicSchedulingRouting } from './dynamic-scheduling.routing';\r\nimport { ScheduleUploadService } from './schedule-upload/schedule-upload.service';\r\nimport { ScheduleArchiveService } from './schedule-archive/schedule-archive.service';\r\n\r\nimport ScheduleUploadGuard from '../authentication/schedule-upload-guard.service';\r\n\r\n@NgModule({\r\n imports: [\r\n SharedModule,\r\n dynamicSchedulingRouting,\r\n ],\r\n\r\n declarations: [\r\n DynamicSchedulingComponent, ScheduleUploadComponent, \r\n ScheduleListHeader, \r\n ScheduleListTable,\r\n ScheduleListSearchBarComponent,\r\n ScheduleArchiveComponent, \r\n HelpScheduleComponent, \r\n ScheduleUploadErrorDialogComponent,\r\n ScheduleUnavailableComponent,\r\n ],\r\n\r\n providers: [\r\n ScheduleUploadService,\r\n ScheduleArchiveService,\r\n ScheduleUploadGuard,\r\n ],\r\n\r\n exports: [\r\n DynamicSchedulingComponent, \r\n ScheduleUploadComponent, \r\n ScheduleArchiveComponent,\r\n ScheduleUploadErrorDialogComponent,\r\n ],\r\n\r\n //entryComponents: [\r\n // ScheduleUploadErrorDialogComponent\r\n //],\r\n\r\n schemas: [NO_ERRORS_SCHEMA],\r\n}) \r\n\r\nexport class DynamicSchedulingModule { } \r\n","import { Component, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'contact-us',\r\n template: require('./contact-us.component.html')\r\n})\r\nexport class ContactUsComponent implements OnInit {\r\n contactUsEmail: string;\r\n contactUsPhone: string;\r\n\r\n constructor() {\r\n this.contactUsEmail = SUPPORT_EMAIL;\r\n this.contactUsPhone = SUPPORT_PHONE;\r\n }\r\n\r\n ngOnInit() { }\r\n}","import { Component, OnInit, OnDestroy } from '@angular/core';\r\nimport { Router } from '@angular/router';\r\n\r\nimport { UserRole } from '../shared/services/user-role.service';\r\nimport { LoggedInUserService } from '../shared/services/logged-in-user.service';\r\nimport { Configuration } from '../app.configuration';\r\n\r\nlet styles = String(require('./home.component.css'));\r\n\r\n@Component({\r\n selector: 'home',\r\n template: require('./home.component.html'),\r\n styles: [styles]\r\n})\r\nexport class HomeComponent implements OnInit, OnDestroy {\r\n\r\n public canAccessInvoiceAndPaymentsLink: boolean;\r\n public canAccessSettlementLink: boolean;\r\n public canAccessInvoiceSummaryReportLink: boolean;\r\n public canAccessDynamicSchedulingLink: boolean;\r\n public canAccessReportLink: boolean;\r\n\r\n constructor(private router: Router,\r\n private loggedInUserService: LoggedInUserService,\r\n private userRole: UserRole) {\r\n\r\n let userProfile = this.loggedInUserService.getLoggedInUser();\r\n let roles = this.userRole.getAllRolesFromUserProfile(userProfile);\r\n\r\n\r\n //PORTAL_ADMIN\r\n //INTERNAL\r\n\r\n let portalAdmin = this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.PORTAL_ADMIN + '&&' + Configuration.USER_ROLES.INTERNAL);\r\n\r\n this.canAccessInvoiceAndPaymentsLink = portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.BILLING_DATA_VIEW);\r\n this.canAccessSettlementLink = portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.BILLING_SETTLEMENTS);\r\n this.canAccessInvoiceSummaryReportLink = portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.INVOICE_SUMMARY_REPORT);\r\n this.canAccessDynamicSchedulingLink = portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.SCHEDULER);\r\n this.canAccessReportLink = portalAdmin || this.userRole.matchRolesAndRolesConditions(roles, Configuration.USER_ROLES.MONTHLY_REPORTS + '||' + Configuration.USER_ROLES.DAILY_REPORTS);\r\n }\r\n\r\n ngOnInit() {\r\n document.getElementById(\"CalpineApp\").className = \"app-container-for-home\";\r\n let windowHeight = $(window).height();\r\n windowHeight = windowHeight < 850 ? 850 : windowHeight;\r\n document.getElementById(\"homeContainer\").style.height = (windowHeight - 165).toString() + \"px\";\r\n document.getElementById(\"main-body\").className = \"hide-scrollbar\";\r\n }\r\n\r\n ngOnDestroy() {\r\n document.getElementById(\"CalpineApp\").className = \"app-container-all-but-home\";\r\n }\r\n\r\n navigateToInvoiceAndPayments() {\r\n this.router.navigate(['/billing/account-summary'])\r\n }\r\n\r\n navigateToSettlements() {\r\n this.router.navigate(['/billing/settlements'])\r\n }\r\n\r\n navigateToInvoiceSummaryReport() {\r\n this.router.navigate(['/billing/invoice-summary-report'])\r\n }\r\n\r\n navigateToDynamicScheduling() {\r\n this.router.navigate(['/dynamic-scheduling/schedule-upload'])\r\n }\r\n}","import { Component, OnInit } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'terms-conditions',\r\n template: require('./terms-conditions.component.html'),\r\n})\r\n\r\nexport class TermsConditionsComponent implements OnInit {\r\n constructor() {}\r\n\r\n /** Remove some class and dom element to meet the acceptance criteria*/\r\n ngOnInit() {\r\n /** Remove the header placeholder height */\r\n $(\"div\").removeClass('app-container');\r\n /** Remove the header menu */\r\n $(\"nav-menu\").remove();\r\n /** Remove the timeout */\r\n $(\"session-timeout\").remove();\r\n /** Remove the exception popup */\r\n $(\"popup\").remove();\r\n /** Remove the outdated browser */\r\n $(\"outdated-browser\").remove();\r\n /** Remove the footer */\r\n $(\"footer-component\").remove();\r\n $(\"script\").remove();\r\n $(\"modal\").remove();\r\n }\r\n}","import { Routes, RouterModule } from '@angular/router';\r\nimport { ModuleWithProviders } from '@angular/core';\r\n\r\nimport { ContactUsComponent } from './contact-us/contact-us.component';\r\nimport { HomeComponent } from './home.component';\r\nimport { TermsConditionsComponent } from './terms-conditions/terms-conditions.component';\r\nimport { CanActivateAuthGuard } from '../authentication/auth-guard.service';\r\n\r\nconst homeRoutes: Routes = [\r\n { path: '', component: HomeComponent, canActivate: [CanActivateAuthGuard], data: { title: 'Home', requiredRoles: '' }, },\r\n { path: 'contact-us', component: ContactUsComponent, data: { title: 'Contact Us' } },\r\n { path: 'contact-us/:keyState', component: ContactUsComponent, data: { title: 'Contact Us' } },\r\n { path: 'terms-conditions', component: TermsConditionsComponent, data: { title: 'Terms & Conditions' } },\r\n];\r\n\r\nexport const homeRouting: ModuleWithProviders = RouterModule.forChild(homeRoutes);","import { NgModule } from '@angular/core';\r\n\r\nimport { homeRouting } from './home.routing';\r\nimport { ContactUsComponent } from './contact-us/contact-us.component';\r\nimport { TermsConditionsComponent } from './terms-conditions/terms-conditions.component';\r\nimport { HomeComponent } from './home.component';\r\n\r\n@NgModule({\r\n imports: [\r\n homeRouting\r\n ],\r\n\r\n declarations: [\r\n HomeComponent,\r\n ContactUsComponent,\r\n TermsConditionsComponent\r\n ],\r\n\r\n providers: [\r\n ],\r\n\r\n exports: [\r\n ]\r\n})\r\n\r\nexport class HomeModule { } \r\n\r\n","import { Injectable } from '@angular/core';\r\nimport { AuthenticationService } from './authentication/authentication.service';\r\nimport { BillingAccountSummaryService } from './billing/billing-account-summary.service';\r\n\r\n@Injectable()\r\nexport class AppService {\r\n constructor(private billingService: BillingAccountSummaryService, private auth: AuthenticationService) { }\r\n\r\n}\r\n","import { Action, ActionReducer } from '@ngrx/store';\r\nimport { IScheduleArchiveModel, ScheduleArchive } from './schedule-archive.model';\r\n\r\nimport { IScheduleArchiveInfo, ScheduleArchiveBundle, WeekdayStrings } from './schedule-archive.model';\r\n\r\nimport type { IScheduleUploadFilter } from '../shared/schedule-upload-filter.model';\r\nimport { ScheduleFilterService } from '../shared/schedule-filter.service';\r\nimport { ScheduleValidationService } from '../shared/schedule-validation.service';\r\nimport { ScheduleAction } from '../shared/schedule-action';\r\n\r\nexport const scheduleArchiveReducer: ActionReducer = (\r\n /* Default VM */\r\n state: IScheduleArchiveModel = {\r\n scheduleList: [],\r\n scheduleUploadList: [],\r\n lastUploadedDate: null,\r\n filteredSchedules: [],\r\n flowDateErrors: [],\r\n showInvalidExtensionMessage: false,\r\n isDynamicSchedulingAvailable: true,\r\n limitWarningMode: false,\r\n callHighLimitWarningDialog: false,\r\n uploadID: 0,\r\n scheduleUploadFilter: ReducerMethods.getDefaultFilter(),\r\n scheduleCustomerPoints: [],\r\n scheduleFlowDates: [],\r\n scheduleFinals: [],\r\n scheduleSubmitters: [],\r\n scheduleDOWs: []\r\n }, action: ScheduleAction) => {\r\n\r\n switch (action.type) {\r\n case 'SET_ARCHIVE_SCHEDULES':\r\n //do some re-calculations before we update the state\r\n var uploadBundle: ScheduleArchiveBundle = new ScheduleArchiveBundle(action.payload); // Action.Payload should be IScheduleUploadBundle\r\n var schedulesData: IScheduleArchiveInfo[] = uploadBundle.ScheduleArchiveUploadInfo;\r\n var schedules = schedulesData.map((schedule) => {\r\n return new ScheduleArchive(schedule);\r\n });\r\n\r\n var limitWarningMode: boolean = false;\r\n\r\n // see if high limit warnings and display dialog\r\n var callHighLimitWarningDialog: boolean = false;\r\n if (schedules.some((schedule) => { return schedule.hasLimitWarning; }) && uploadBundle.NewUpload == true) {\r\n callHighLimitWarningDialog = true;\r\n limitWarningMode = true;\r\n }\r\n\r\n\r\n var defaultFilter: IScheduleUploadFilter = ReducerMethods.getDefaultFilter(); // Jeff's sorting doesn't work accross year\r\n var filteredSchedules = ScheduleFilterService.filterSchedules(schedules, defaultFilter, state.limitWarningMode);\r\n ScheduleFilterService.sortSchedules(filteredSchedules, defaultFilter);\r\n var uploadID: number = uploadBundle.UploadID;\r\n\r\n // figure out the lists of customer points, submitter emails, and flow dates for the header filters\r\n var scheduleCustomerPoints = [];\r\n var scheduleSubmitters = [];\r\n var scheduleDOWs = [];\r\n var scheduleFinals = [];\r\n var scheduleFlowDatesSchedules: ScheduleArchive[] = []; // grab the whole schedule for now so we can sort\r\n schedules.forEach((schedule) => {\r\n if (scheduleCustomerPoints.filter((point) => { return schedule.DynamicSchedule.Point.toLowerCase() == point.toLowerCase(); }).length == 0) {\r\n scheduleCustomerPoints.push(schedule.DynamicSchedule.Point);\r\n }\r\n\r\n if (scheduleSubmitters.filter((submitter) => { return schedule.SubmittedBy.toLowerCase() == submitter.toLowerCase(); }).length == 0) {\r\n scheduleSubmitters.push(schedule.SubmittedBy);\r\n }\r\n\r\n if (scheduleDOWs.filter((DOW) => { return schedule.DOW.toLowerCase() == DOW.toLowerCase(); }).length == 0) {\r\n scheduleDOWs.push(schedule.DOW);\r\n }\r\n\r\n if (scheduleFinals.filter((final) => { return schedule.isFinal == final; }).length == 0) {\r\n scheduleFinals.push(schedule.isFinal);\r\n }\r\n\r\n if (scheduleFlowDatesSchedules.findIndex((flowDateSchedule) => flowDateSchedule.DynamicSchedule.FlowDate == schedule.DynamicSchedule.FlowDate) == -1) {\r\n scheduleFlowDatesSchedules.push(schedule);\r\n }\r\n });\r\n scheduleCustomerPoints = scheduleCustomerPoints.sort((a, b) => {\r\n if (a.toLowerCase() > b.toLowerCase())\r\n return 1;\r\n else return -1;\r\n });\r\n scheduleSubmitters = scheduleSubmitters.sort((a, b) => {\r\n if (a.toLowerCase() > b.toLowerCase())\r\n return 1;\r\n else return -1;\r\n });\r\n scheduleDOWs = scheduleDOWs.sort((a, b) => {\r\n if (WeekdayStrings.indexOf(a) > WeekdayStrings.indexOf(b))\r\n return 1;\r\n else return -1;\r\n });\r\n\r\n var scheduleFlowDates = scheduleFlowDatesSchedules.sort((scheduleA, scheduleB) => {\r\n return scheduleA.DynamicSchedule.FlowDateValue > scheduleB.DynamicSchedule.FlowDateValue ? 1 : -1;\r\n }).map((schedule) => {\r\n return schedule.DynamicSchedule.FlowDate\r\n });\r\n \r\n var flowDateErrors = ScheduleValidationService.getFlowDateErrors(schedules, limitWarningMode);\r\n //apply the counts and reset the filter + filteredschedules\r\n return Object.assign({}, state, {\r\n scheduleUploadList: schedules,\r\n lastUploadedDate: uploadBundle.UploadTimeString,\r\n filteredSchedules: filteredSchedules, \r\n scheduleCustomerPoints,\r\n scheduleFlowDates,\r\n scheduleSubmitters,\r\n scheduleDOWs,\r\n scheduleFinals,\r\n scheduleUploadFilter: defaultFilter,\r\n flowDateErrors,\r\n callHighLimitWarningDialog,\r\n limitWarningMode,\r\n uploadID\r\n });\r\n case 'UPDATE_ARCHIVE_SCHEDULE_FILTER':\r\n // stuff should come thru like { scheduleStatus: 1 } - just smoosh it into the existing filter\r\n // scheduleStatus and specificError need to work like a toggle though so a little extra logic for that\r\n var updatedFilter = ScheduleFilterService.updateFilter(state.scheduleUploadFilter, action.payload, state.scheduleFlowDates, state.scheduleCustomerPoints, state.scheduleSubmitters, state.scheduleDOWs, state.scheduleFinals);\r\n var filteredSchedules = ScheduleFilterService.filterSchedules(state.scheduleUploadList, updatedFilter, state.limitWarningMode);\r\n updatedFilter.isAnyFilterPresent = ReducerMethods.isAnyFilterPresent(updatedFilter);\r\n ScheduleFilterService.sortSchedules(filteredSchedules, updatedFilter);\r\n return Object.assign({}, state, { scheduleUploadFilter: updatedFilter, filteredSchedules: filteredSchedules });\r\n case 'SET_INVALID_FLOWDATES_FOR_ARCHIVE':\r\n return Object.assign({}, state, { invalidFlowdates: action.payload });\r\n case 'SET_INVALID_EXTENSION_MESSAGE_FOR_ARCHIVE':\r\n return Object.assign({}, state, { showInvalidExtensionMessage: action.payload });\r\n case 'SET_DYNAMIC_SCHEDULING_AVAILABLE_FOR_ARCHIVE':\r\n return Object.assign({}, state, { isDynamicSchedulingAvailable: action.payload });\r\n case 'SET_LIMIT_WARNING_MODE_FOR_ARCHIVE':\r\n // this is called from the limit-warning modal once the user makes a selection.\r\n // need to recalculate the flowdate errors and dashboard counts - they work a little differently \r\n var limitWarningMode: boolean = action.payload;\r\n var flowDateErrors = ScheduleValidationService.getFlowDateErrors(state.scheduleUploadList, limitWarningMode);\r\n return Object.assign({}, state, { limitWarningMode, flowDateErrors, callHighLimitWarningDialog: false });\r\n case 'RESET_ARCHIVE_FILTERS':\r\n state.scheduleUploadFilter = ReducerMethods.getDefaultFilter();\r\n state.scheduleUploadFilter.finals = [];\r\n return Object.assign({}, state, { filteredSchedules: state.scheduleUploadList });\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nclass ReducerMethods {\r\n\r\n static getDefaultFilter(): IScheduleUploadFilter {\r\n return {\r\n isDefaultSort: true,\r\n isAnyFilterPresent: false,\r\n scheduleStatuses: [],\r\n specificError: null,\r\n customerSearch: '',\r\n customerPoints: [],\r\n flowDates: [],\r\n customerPointSort: 'ASC',\r\n flowDateSort: 'ASC',\r\n flowDateStart: null,\r\n flowDateEnd: null, \r\n submitters: [],\r\n submittersSort: 'ASC',\r\n DOWs: [],\r\n DOWSort: 'ASC',\r\n uploadTimestamps: [],\r\n uploadTimestampSort: 'DESC',\r\n uploadDateStart: null,\r\n uploadDateEnd: null,\r\n finals: [true]\r\n };\r\n }\r\n\r\n static isAnyFilterPresent(currentFilter: IScheduleUploadFilter): boolean {\r\n let defaultFilters: IScheduleUploadFilter = ReducerMethods.getDefaultFilter();\r\n return (currentFilter.customerSearch !== defaultFilters.customerSearch ||\r\n !(_.isEqual(currentFilter.customerPoints.sort(), defaultFilters.customerPoints.sort())) ||\r\n currentFilter.flowDateStart !== defaultFilters.flowDateStart ||\r\n currentFilter.flowDateEnd !== defaultFilters.flowDateEnd ||\r\n currentFilter.uploadDateStart !== defaultFilters.uploadDateStart ||\r\n currentFilter.uploadDateEnd !== defaultFilters.uploadDateEnd ||\r\n !(_.isEqual(currentFilter.finals, []) || _.isEqual(currentFilter.finals, defaultFilters.finals)) ||\r\n !(_.isEqual(currentFilter.DOWs.sort(), defaultFilters.DOWs.sort())) ||\r\n !(_.isEqual(currentFilter.submitters.sort(), defaultFilters.submitters.sort()))\r\n );\r\n }\r\n \r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { LocationStrategy, HashLocationStrategy } from '@angular/common';\r\nimport { BrowserModule } from '@angular/platform-browser';\r\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations'\r\n\r\nimport { StoreModule } from '@ngrx/store';\r\n\r\nimport { APP_ROUTES } from './app.routes';\r\n\r\nimport { SharedModule } from './shared/shared.module';\r\n\r\nimport { AppComponent } from './app.component';\r\nimport { NavMenuComponent } from './shared/nav-menu/nav-menu.component';\r\nimport { FooterComponent } from './shared/footer/footer.component';\r\nimport { SessionTimeoutComponent } from './authentication/session-timeout.component'\r\nimport { IdTokenComponent } from './authentication/id-token.component';\r\nimport { PopupComponent } from './shared/modal/popup.component';\r\nimport { OutdatedBrowserComponent } from './shared/outdated-browser/outdated-browser.component';\r\n\r\nimport { UserManagementModule } from './user-management/user-management.module';\r\nimport { DynamicSchedulingModule } from './dynamic-scheduling/dynamic-scheduling.module';\r\nimport { HomeModule } from './home/home.module';\r\nimport { LoggedInUserService } from './shared/services/logged-in-user.service';\r\nimport { AppService } from './app.service';\r\nimport { BillingAccountSummaryService } from './billing/billing-account-summary.service';\r\nimport { CheckboxService } from './billing/checkbox.service';\r\n\r\nimport { scheduleUploadReducer } from './dynamic-scheduling/schedule-upload/schedule-upload.reducer';\r\nimport { scheduleArchiveReducer } from './dynamic-scheduling/schedule-archive/schedule-archive.reducer';\r\nimport { UsersService } from './administration/users/users.service';\r\nimport { CounterpartyUsersService } from './administration/counterparty-users/counterparty-users.service';\r\nimport { EventService } from './shared/services/event.service';\r\nimport { NgbModule } from '@ng-bootstrap/ng-bootstrap';\r\nimport { NgxPaginationModule } from 'ngx-pagination';\r\n\r\n@NgModule({\r\n imports: [\r\n BrowserModule,\r\n BrowserAnimationsModule,\r\n HomeModule,\r\n DynamicSchedulingModule,\r\n UserManagementModule,\r\n APP_ROUTES,\r\n SharedModule.forRoot(),\r\n StoreModule.forRoot({\r\n scheduleUploadModel: scheduleUploadReducer,\r\n scheduleArchiveModel: scheduleArchiveReducer\r\n }),\r\n NgbModule,\r\n NgxPaginationModule,\r\n ],\r\n\r\n declarations: [\r\n AppComponent,\r\n NavMenuComponent, \r\n FooterComponent, \r\n SessionTimeoutComponent,\r\n IdTokenComponent,\r\n PopupComponent,\r\n OutdatedBrowserComponent,\r\n ],\r\n\r\n providers: [\r\n CounterpartyUsersService,\r\n UsersService,\r\n LoggedInUserService,\r\n AppService,\r\n BillingAccountSummaryService,\r\n CheckboxService,\r\n EventService,\r\n { provide: LocationStrategy, useClass: HashLocationStrategy },\r\n ],\r\n\r\n //entryComponents: [\r\n // SessionTimeoutComponent,\r\n // PopupComponent,\r\n // OutdatedBrowserComponent\r\n //],\r\n\r\n bootstrap: [\r\n AppComponent\r\n ],\r\n})\r\nexport class AppModule { }\r\n","import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';\r\nimport { enableProdMode } from '@angular/core';\r\nimport { AppModule } from './app/app.module';\r\n\r\nif (ENV === 'production') {\r\n enableProdMode();\r\n}\r\n\r\nplatformBrowserDynamic().bootstrapModule(AppModule)\r\n .then(success => console.log('ngModule Bootstrap success'))","// The module cache\nconst __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tconst cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tconst module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","const deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tlet notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tlet [chunkIds, fn, priority] = deferred[i];\n\t\tlet fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tconst r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tconst getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter/value functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tif(Array.isArray(definition)) {\n\t\tvar i = 0;\n\t\twhile(i < definition.length) {\n\t\t\tvar key = definition[i++];\n\t\t\tvar binding = definition[i++];\n\t\t\tif(!__webpack_require__.o(exports, key)) {\n\t\t\t\tif(binding === 0) {\n\t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, value: definition[i++] });\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: binding });\n\t\t\t\t}\n\t\t\t} else if(binding === 0) { i++; }\n\t\t}\n\t} else {\n\t\tfor(var key in definition) {\n\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t\t}\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = (chunkId) => {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = (chunkId) => {\n\t// return url for filenames based on template\n\treturn \"\" + chunkId + \".\" + {\"14\":\"36ca964efc0c4c281f46\",\"122\":\"b24870151f1ef844ab51\",\"698\":\"e6c950328c4a08bf4a18\",\"974\":\"7e9facd3bb80bbd32a30\"}[chunkId] + \".js\";\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","const inProgress = {};\nconst dataWebpackPrefix = \"calpine-client-portal:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = (url, done, key, chunkId) => {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tlet script, needAttach;\n\tif(key !== undefined) {\n\t\tconst scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tconst s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tconst onScriptComplete = (prev, event) => {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tconst doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode?.removeChild(script);\n\t\tdoneFns?.forEach((fn) => (fn(event)));\n\t\tif(prev) return prev(event);\n\t}\n\tconst timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 792;","let scriptUrl;\nif (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \"\";\nconst document = __webpack_require__.g.document;\nif (!scriptUrl && document) {\n\tif (document.currentScript?.tagName.toUpperCase() === 'SCRIPT')\n\t\tscriptUrl = document.currentScript.src;\n\tif (!scriptUrl) {\n\t\tconst scripts = document.getElementsByTagName(\"script\");\n\t\tif(scripts.length) {\n\t\t\tlet i = scripts.length - 1;\n\t\t\twhile (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;\n\t\t}\n\t}\n}\n// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration\n// or pass an empty string (\"\") and set the __webpack_public_path__ variable from your code to use your own logic.\nif (!scriptUrl) throw new Error(\"Automatic publicPath is not supported in this browser\");\nscriptUrl = scriptUrl.replace(/^blob:/, \"\").replace(/#.*$/, \"\").replace(/\\?.*$/, \"\").replace(/\\/[^\\/]+$/, \"/\");\n__webpack_require__.p = scriptUrl;","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nconst installedChunks = {\n\t792: 0\n};\n\n__webpack_require__.f.j = (chunkId, promises) => {\n\t\t// JSONP chunk loading for javascript\n\t\tlet installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tconst promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tconst url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tconst error = new Error();\n\t\t\t\t\tconst loadingEnded = (event) => {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tconst errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tconst realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nconst webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tlet [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nconst chunkLoadingGlobal = self[\"webpackChunkcalpine_client_portal\"] = self[\"webpackChunkcalpine_client_portal\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nlet __webpack_exports__ = __webpack_require__.O(undefined, [223], () => (__webpack_require__(14543)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":[],"sourceRoot":""}