diff --git a/.browserslistrc b/.browserslistrc deleted file mode 100644 index 214388fe..00000000 --- a/.browserslistrc +++ /dev/null @@ -1,3 +0,0 @@ -> 1% -last 2 versions -not dead diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 569ce539..00000000 --- a/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -**/node_modules -**/dist \ No newline at end of file diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 7053c49a..00000000 --- a/.editorconfig +++ /dev/null @@ -1,5 +0,0 @@ -[*.{js,jsx,ts,tsx,vue}] -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -insert_final_newline = true diff --git a/.env.example b/.env.example deleted file mode 100644 index 5fb09355..00000000 --- a/.env.example +++ /dev/null @@ -1,29 +0,0 @@ -# Base Path -VUE_APP_PATH=/ - -#vaults Shared -VUE_APP_ADDRESS_COMPLETE_KEY= - -#vaults web-url -VUE_APP_AUTH_WEB_URL="https://dev.account.bcregistry.gov.bc.ca/" -VUE_APP_SITEMINDER_LOGOUT_URL="https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi" -VUE_APP_FAS_WEB_URL="https://fas-dev.apps.silver.devops.gov.bc.ca/" - -#vaults API -VUE_APP_AUTH_API_URL="https://auth-api-dev-142173140222.northamerica-northeast1.run.app" -VUE_APP_AUTH_API_VERSION="/api/v1" -VUE_APP_STATUS_API_URL="https://status-api-dev.apps.gold.devops.gov.bc.ca" -VUE_APP_STATUS_API_VERSION="/api/v1" -VUE_APP_PAY_API_URL="https://pay-api-dev-142173140222.northamerica-northeast1.run.app" -VUE_APP_PAY_API_VERSION="/api/v1" - -#vaults keycloak -VUE_APP_KEYCLOAK_AUTH_URL="https://dev.loginproxy.gov.bc.ca/auth" -VUE_APP_KEYCLOAK_REALM="bcregistry" -VUE_APP_KEYCLOAK_CLIENTID="fas-web" - -#vaults launchdarkly -VUE_APP_PAY_LD_CLIENT_ID= - -# Google Analytics -VUE_APP_GTAG_ID= diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 2680010f..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - root: true, - env: { - es2021: true - }, - extends: ['plugin:vue/essential', '@vue/standard', '@vue/typescript'], - parserOptions: { - ecmaVersion: 2020, - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint'] - }, - rules: { - 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', - 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', - 'space-before-function-paren': 1, - 'vue/component-name-in-template-casing': ['error', 'PascalCase'] - }, - overrides: [ - { - files: [ - '**/__tests__/*.{j,t}s?(x)', - '**/tests/unit/**/*.spec.{j,t}s?(x)' - ], - env: { - jest: true - } - } - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0fef6b6..edfc0bac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,8 @@ jobs: pay-ui-ci: uses: bcgov/bcregistry-sre/.github/workflows/frontend-ci.yaml@main with: - node_version: "20.5.1" + node_version: 24 + pnpm_version: 10.0.0 app_name: "pay-ui" - working_directory: "." + working_directory: "./web/pay-ui" codecov_flag: "payweb" diff --git a/.github/workflows/gcp-cd.yml b/.github/workflows/gcp-cd.yml index 85c951aa..d04f1fce 100644 --- a/.github/workflows/gcp-cd.yml +++ b/.github/workflows/gcp-cd.yml @@ -4,8 +4,6 @@ on: push: branches: - main - - feature* - - hotfix* workflow_dispatch: inputs: target: @@ -24,7 +22,7 @@ jobs: with: target: ${{ inputs.target }} app_name: "pay-ui" - working_directory: "." + working_directory: "./web/pay-ui" secrets: WORKLOAD_IDENTIFY_POOLS_PROVIDER: ${{ secrets.WORKLOAD_IDENTIFY_POOLS_PROVIDER }} GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }} diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 00000000..fcd887a2 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,153 @@ +# ============================================================================ +# Playwright Test Automation Workflow +# ============================================================================ +# +# Name: Pay UI Test Automation +# Description: Automated end-to-end regression testing using Playwright +# Created: February 17, 2026 +# Created By: Anish Batra +# +# Purpose: +# - Run automated regression tests on Pay UI application +# - Supports multiple login methods (BCSC and mocked IDIR) +# - Generates Allure and Playwright HTML reports +# - Runs on schedule (Mon-Fri 11 AM EST) and manual trigger +# +# Triggers: +# - Push to main branch +# - Manual workflow dispatch +# - Scheduled: Mon-Fri 11:00 AM EST (16:00 UTC) +# ============================================================================ +name: Pay UI Test Automation +on: + push: + branches: [ feature-nuxt-v3-upgrade ] + pull_request: + branches: [ feature-nuxt-v3-upgrade ] + workflow_dispatch: {} + schedule: + # Runs Mon-Fri at 11:00 AM Eastern Standard Time (fixed UTC-5 -> 16:00 UTC) + - cron: '0 16 * * 1-5' +permissions: + contents: read +jobs: + build-app: + if: github.event_name == 'pull_request' || github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache pay-ui build + id: build-cache + uses: actions/cache@v4 + with: + path: web/pay-ui/.output/public + key: pay-ui-build-${{ hashFiles('web/pay-ui/**', '!web/pay-ui/node_modules/**') }} + - uses: actions/setup-node@v4 + if: steps.build-cache.outputs.cache-hit != 'true' + with: + node-version: lts/* + - uses: pnpm/action-setup@v4 + if: steps.build-cache.outputs.cache-hit != 'true' + with: + version: 10 + - name: Install pay-ui dependencies + if: steps.build-cache.outputs.cache-hit != 'true' + working-directory: web/pay-ui + run: pnpm install --frozen-lockfile + - name: Build pay-ui + if: steps.build-cache.outputs.cache-hit != 'true' + working-directory: web/pay-ui + run: cp .env.example .env && pnpm generate + - uses: actions/upload-artifact@v4 + with: + name: pay-ui-build + path: web/pay-ui/.output/public/ + retention-days: 1 + + setup-playwright: + runs-on: ubuntu-latest + outputs: + pw-version: ${{ steps.pw-version.outputs.version }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install test dependencies + working-directory: test-automation + run: npm ci + - name: Get Playwright version + id: pw-version + working-directory: test-automation + run: echo "version=$(npx playwright --version | sed 's/Version //')" >> "$GITHUB_OUTPUT" + - name: Cache Playwright Browsers + id: pw-cache + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ steps.pw-version.outputs.version }} + - name: Install Playwright Browsers + if: steps.pw-cache.outputs.cache-hit != 'true' + working-directory: test-automation + run: npx playwright install --with-deps + + test: + needs: [build-app, setup-playwright] + if: always() && needs.setup-playwright.result == 'success' && (needs.build-app.result == 'success' || needs.build-app.result == 'skipped') + timeout-minutes: 60 + runs-on: ubuntu-latest + env: + TEST_USERNAME_BCSC: ${{ secrets.TEST_USERNAME_BCSC }} + TEST_PASSWORD_BCSC: ${{ secrets.TEST_PASSWORD_BCSC }} + TEST_USERNAME_BCSC_IDIR: ${{ secrets.TEST_USERNAME_BCSC_IDIR }} + TEST_PASSWORD_BCSC_IDIR: ${{ secrets.TEST_PASSWORD_BCSC_IDIR }} + BASE_URL_DEV: ${{ secrets.BASE_URL_DEV }} + BASE_URL_TEST: ${{ secrets.BASE_URL_TEST }} + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Restore Playwright Browsers + uses: actions/cache/restore@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ needs.setup-playwright.outputs.pw-version }} + - name: Install test dependencies + working-directory: test-automation + run: npm ci && npx playwright install + - name: Start pay-ui + if: needs.build-app.result == 'success' + uses: actions/download-artifact@v4 + with: + name: pay-ui-build + path: pay-ui-build + - if: needs.build-app.result == 'success' + run: npx serve pay-ui-build -l 3000 & + - if: needs.build-app.result == 'success' + run: npx wait-on http://localhost:3000 --timeout 30000 + - name: Run Playwright regression tests + working-directory: test-automation + run: npm run e2e:regression:test + env: + BASE_URL: ${{ needs.build-app.result == 'success' && 'http://localhost:3000' || '' }} + - name: Generate Allure Report + if: ${{ !cancelled() }} + working-directory: test-automation + run: npm run allure:generate + - name: Upload test artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: test-artifacts + path: | + test-automation/allure-report/ + test-automation/playwright-report/ + test-automation/test-results/ + retention-days: 30 + - name: Publish HTML Report + if: ${{ !cancelled() }} + uses: daun/playwright-report-summary@v3 + with: + report-file: test-automation/playwright-report/results.json + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 4c8b4522..2204ad7f 100644 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,7 @@ venv/ ENV/ env.bak/ venv.bak/ +*.env.* # Spyder project settings .spyderproject @@ -126,3 +127,4 @@ lib/lib.umd.js lib/lib.umd.js.map .history + diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index c3481a75..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "singleQuote": true, - "semi": false -} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index f1a3dd71..00000000 --- a/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:20.5.1 as build-stage -WORKDIR /app -COPY ./package*.json ./ -RUN npm install -COPY . . -RUN npm run build - -FROM nginx:1.18.0 as production-stage - -ARG VCS_REF="missing" -ARG BUILD_DATE="missing" - -ENV VCS_REF=${VCS_REF} -ENV BUILD_DATE=${BUILD_DATE} - -LABEL org.label-schema.vcs-ref=${VCS_REF} \ - org.label-schema.build-date=${BUILD_DATE} - -RUN echo "hello1" -COPY nginx.conf /etc/nginx/nginx.conf -RUN echo "hello2" -RUN mkdir /app -COPY --from=build-stage /app/dist /app -EXPOSE 8080:8080 -CMD ["nginx", "-g", "daemon off;"] diff --git a/Jenkinsfiles/build.groovy b/Jenkinsfiles/build.groovy deleted file mode 100644 index 3d0a0880..00000000 --- a/Jenkinsfiles/build.groovy +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env groovy -// Copyright © 2018 Province of British Columbia -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//JENKINS DEPLOY ENVIRONMENT VARIABLES: -// - JENKINS_JAVA_OVERRIDES -Dhudson.model.DirectoryBrowserSupport.CSP= -Duser.timezone=America/Vancouver -// -> user.timezone : set the local timezone so logfiles report correxct time -// -> hudson.model.DirectoryBrowserSupport.CSP : removes restrictions on CSS file load, thus html pages of test reports are displayed pretty -// See: https://docs.openshift.com/container-platform/3.9/using_images/other_images/jenkins.html for a complete list of JENKINS env vars -// define constants -def COMPONENT_NAME = 'bcrs-entities-create-ui' -def TAG_NAME = 'dev' -def NAMESPACE = 'namespace' - -// define groovy functions -import groovy.json.JsonOutput - -// Determine whether there were any changes the files within the project's context directory. -// return a string listing commit msgs occurred since last build -@NonCPS -String triggerBuild(String contextDirectory) { - // Determine if code has changed within the source context directory. - def changeLogSets = currentBuild.changeSets - def filesChangeCnt = 0 - MAX_MSG_LEN = 512 - def changeString = "" - for (int i = 0; i < changeLogSets.size(); i++) { - def entries = changeLogSets[i - ].items - for (int j = 0; j < entries.length; j++) { - def entry = entries[j - ] - //echo "${entry.commitId} by ${entry.author} on ${new Date(entry.timestamp)}: ${entry.msg}" - def files = new ArrayList(entry.affectedFiles) - - for (int k = 0; k < files.size(); k++) { - def file = files[k - ] - def filePath = file.path - //echo ">> ${file.path}" - if (filePath.contains(contextDirectory)) { - - filesChangeCnt = 1 - truncated_msg = entry.msg.take(MAX_MSG_LEN) - changeString += " - ${truncated_msg} [${entry.author}]\n" - k = files.size() - j = entries.length - } - } - } - } - if ( filesChangeCnt < 1 ) { - echo('The changes do not require a build.') - return "" - } - else { - echo('The changes require a build.') - return changeString - } -} -// Get an image's hash tag -String getImageTagHash(String imageName, String tag = "") { - - if(!tag?.trim()) { - tag = "latest" - } - - def istag = openshift.raw("get istag ${imageName}:${tag} -o template --template='{{.image.dockerImageReference}}'") - return istag.out.tokenize('@')[1].trim() -} - -// pipeline -// define job properties - keep 10 builds only -properties([ - [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '10' - ] - ] -]) - -def run_pipeline = true -if( triggerBuild(COMPONENT_NAME) == "" ) { - node { - try { - timeout(time: 1, unit: 'DAYS') { - input message: "Run ${COMPONENT_NAME}-${TAG_NAME}-pipeline?", id: "1234", submitter: 'admin,thorwolpert-admin,rarmitag-admin,kialj876-admin,katiemcgoff-admin,WalterMoar-admin,severinbeauvais-edit' - } - } catch (Exception e) { - run_pipeline = false; - } - } -} -if (!run_pipeline) { - echo('No Build Wanted - End of Build.') - currentBuild.result = 'SUCCESS' - return -} - -node { - stage("Build ${COMPONENT_NAME}") { - script { - openshift.withCluster() { - openshift.withProject() { - - echo "Building ${COMPONENT_NAME} ..." - def build = openshift.selector("bc", "${COMPONENT_NAME}") - build.startBuild("--wait=true").logs("-f") - } - } - } - } - def old_version - stage("Deploy ${COMPONENT_NAME}:${TAG_NAME}") { - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - old_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - } - } - openshift.withCluster() { - openshift.withProject() { - - echo "Tagging ${COMPONENT_NAME} for deployment to ${TAG_NAME} ..." - - // Don't tag with BUILD_ID so the pruner can do it's job; it won't delete tagged images. - // Tag the images for deployment based on the image's hash - def IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${TAG_NAME}") - } - } - } - } - stage("Verify deployment") { - sleep 10 - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - def new_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - if (new_version == old_version) { - echo "New deployment was not triggered." - currentBuild.result = "FAILURE" - } - def pod_selector = openshift.selector('pod', [ app:"${COMPONENT_NAME}-${TAG_NAME}" ]) - pod_selector.untilEach { - deployment = it.objects()[0].metadata.labels.deployment - echo deployment - if (deployment == "${COMPONENT_NAME}-${TAG_NAME}-${new_version}" && it.objects()[0].status.phase == 'Running' && it.objects()[0].status.containerStatuses[0].ready) { - return true - } else { - echo "Pod for new deployment not ready" - sleep 5 - return false - } - } - } - } - } - } - stage("Run tests on ${COMPONENT_NAME}:${TAG_NAME}") { - openshift.withCluster() { - openshift.withProject() { - def test_pipeline = openshift.selector('bc', 'pytest-pipeline') - try { - test_pipeline.startBuild('--wait=true', "-e=component=${COMPONENT_NAME}", "-e=component_tag=${TAG_NAME}", "-e=tag=${TAG_NAME}", "-e=namespace=${NAMESPACE}", "-e=db_type=PG").logs('-F') - echo "All tests passed" - } catch (Exception e) { - echo "Not all tests passed." - currentBuild.result = 'FAILURE' - } - } - } - } -} diff --git a/Jenkinsfiles/deploy-prod.groovy b/Jenkinsfiles/deploy-prod.groovy deleted file mode 100644 index 694befa6..00000000 --- a/Jenkinsfiles/deploy-prod.groovy +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env groovy -// Copyright © 2018 Province of British Columbia -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//JENKINS DEPLOY ENVIRONMENT VARIABLES: -// - JENKINS_JAVA_OVERRIDES -Dhudson.model.DirectoryBrowserSupport.CSP= -Duser.timezone=America/Vancouver -// -> user.timezone : set the local timezone so logfiles report correxct time -// -> hudson.model.DirectoryBrowserSupport.CSP : removes restrictions on CSS file load, thus html pages of test reports are displayed pretty -// See: https://docs.openshift.com/container-platform/3.9/using_images/other_images/jenkins.html for a complete list of JENKINS env vars -// define constants -def NAMESPACE = 'namesapce' -def COMPONENT_NAME = 'bcrs-entities-create-ui' -def TAG_NAME = 'prod' -def SOURCE_TAG = 'test' - -// define groovy functions -import groovy.json.JsonOutput - -// Get an image's hash tag -String getImageTagHash(String imageName, String tag = "") { - - if(!tag?.trim()) { - tag = "latest" - } - - def istag = openshift.raw("get istag ${imageName}:${tag} -o template --template='{{.image.dockerImageReference}}'") - return istag.out.tokenize('@')[1].trim() -} - -// pipeline -// define job properties - keep 10 builds only -properties([ - [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '10' - ] - ] -]) - -node { - def old_version - stage("Tag ${COMPONENT_NAME}:${TAG_NAME}") { - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - old_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - } - } - openshift.withCluster() { - openshift.withProject() { - echo "Tagging ${COMPONENT_NAME}:${TAG_NAME}-previous" - def IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${TAG_NAME}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${TAG_NAME}-previous") - - echo "Tagging ${COMPONENT_NAME} for deployment to ${TAG_NAME} ..." - // Don't tag with BUILD_ID so the pruner can do it's job; it won't delete tagged images. - // Tag the images for deployment based on the image's hash - IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${SOURCE_TAG}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${TAG_NAME}") - } - } - } - } - stage("Verify deployment") { - sleep 10 - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - def new_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - if (new_version == old_version) { - echo "New deployment was not triggered." - currentBuild.result = "FAILURE" - } - def pod_selector = openshift.selector('pod', [ app:"${COMPONENT_NAME}-${TAG_NAME}" ]) - pod_selector.untilEach { - deployment = it.objects()[0].metadata.labels.deployment - echo deployment - if (deployment == "${COMPONENT_NAME}-${TAG_NAME}-${new_version}" && it.objects()[0].status.phase == 'Running' && it.objects()[0].status.containerStatuses[0].ready) { - return true - } else { - echo "Pod for new deployment not ready" - sleep 5 - return false - } - } - } - } - } - } -}//end node diff --git a/Jenkinsfiles/deploy-test.groovy b/Jenkinsfiles/deploy-test.groovy deleted file mode 100644 index e6668b84..00000000 --- a/Jenkinsfiles/deploy-test.groovy +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env groovy -// Copyright © 2018 Province of British Columbia -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//JENKINS DEPLOY ENVIRONMENT VARIABLES: -// - JENKINS_JAVA_OVERRIDES -Dhudson.model.DirectoryBrowserSupport.CSP= -Duser.timezone=America/Vancouver -// -> user.timezone : set the local timezone so logfiles report correxct time -// -> hudson.model.DirectoryBrowserSupport.CSP : removes restrictions on CSS file load, thus html pages of test reports are displayed pretty -// See: https://docs.openshift.com/container-platform/3.9/using_images/other_images/jenkins.html for a complete list of JENKINS env vars -// define constants -def NAMESPACE = 'namespace' -def COMPONENT_NAME = 'bcrs-entities-create-ui' -def TAG_NAME = 'test' -def SOURCE_TAG = 'dev' -def E2E_TAG = 'e2e' -def E2E_NAMESPACE = 'd7eovc' -def E2E_PROJ = 'tools' - -// define groovy functions -import groovy.json.JsonOutput - -// Get an image's hash tag -String getImageTagHash(String imageName, String tag = "") { - - if(!tag?.trim()) { - tag = "latest" - } - - def istag = openshift.raw("get istag ${imageName}:${tag} -o template --template='{{.image.dockerImageReference}}'") - return istag.out.tokenize('@')[1].trim() -} - -// pipeline -// define job properties - keep 10 builds only -properties([ - [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '10' - ] - ] -]) - -node { - stage("Tag image for E2E") { - script { - openshift.withCluster() { - openshift.withProject() { - echo "Tagging ${COMPONENT_NAME}:${E2E_TAG}-prev with ${E2E_TAG}..." - - def IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${E2E_TAG}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${E2E_TAG}-prev") - - echo "Tagging ${COMPONENT_NAME} to ${E2E_TAG} ..." - - IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${SOURCE_TAG}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${E2E_TAG}") - } - } - } - } - def passed = true - stage("Run E2E Tests") { - script { - try { - timeout(time: 1, unit: 'DAYS') { - input message: "Run E2E pipeline?", id: "1234", submitter: 'admin,thorwolpert-admin,rarmitag-admin,kialj876-admin,katiemcgoff-admin,WalterMoar-admin,JohnamLane-edit,severinbeauvais-edit' - } - openshift.withCluster() { - openshift.withProject("${E2E_NAMESPACE}-${E2E_PROJ}") { - def e2e_pipeline = openshift.selector('bc', 'e2e-pipeline') - try { - echo "Running e2e pipeline (check ${E2E_NAMESPACE}-${E2E_PROJ} to view progress)..." - e2e_pipeline.startBuild('--wait=true').logs('-f') - echo "E2E tests passed!" - } catch (Exception e) { - echo "E2E tests failed: ${e.getMessage()}" - passed = false - } - } - } - } catch (Exception e0) { - echo "Did not run E2E pipeline." - passed = false - } - } - } - def end_pipeline = false - stage("Verify E2E Tests") { - script { - if (!passed) { - try { - timeout(time: 1, unit: 'DAYS') { - input message: "E2E failed or were not run. Proceed to test?", id: "1234", submitter: 'admin,thorwolpert-admin,rarmitag-admin,kialj876-admin,katiemcgoff-admin,WalterMoar-admin,JohnamLane-edit,severinbeauvais-edit' - } - } catch (Exception e1) { - try { - timeout(time: 1, unit: 'DAYS') { - input message: "Keep E2E image?", id: "1234", submitter: 'admin,thorwolpert-admin,rarmitag-admin,kialj876-admin,katiemcgoff-admin,WalterMoar-admin,JohnamLane-edit,severinbeauvais-edit' - } - } catch (Exception e2) { - echo "Reverting E2E image back to previous image..." - openshift.withCluster() { - openshift.withProject() { - echo "Tagging ${COMPONENT_NAME}:${E2E_TAG} with ${E2E_TAG}-prev ..." - - def IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${E2E_TAG}-prev") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${E2E_TAG}") - } - } - } finally { - currentBuild.result = 'FAILURE' - end_pipeline = true - return - } - } - } - } - } - if (!end_pipeline) { - def old_version - stage("Deploy ${COMPONENT_NAME}:${TAG_NAME}") { - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - old_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - } - } - openshift.withCluster() { - openshift.withProject() { - - echo "Tagging ${COMPONENT_NAME} for deployment to ${TAG_NAME} ..." - - // Don't tag with BUILD_ID so the pruner can do it's job; it won't delete tagged images. - // Tag the images for deployment based on the image's hash - def IMAGE_HASH = getImageTagHash("${COMPONENT_NAME}", "${SOURCE_TAG}") - echo "IMAGE_HASH: ${IMAGE_HASH}" - openshift.tag("${COMPONENT_NAME}@${IMAGE_HASH}", "${COMPONENT_NAME}:${TAG_NAME}") - } - } - } - } - stage("Verify deployment") { - sleep 10 - script { - openshift.withCluster() { - openshift.withProject("${NAMESPACE}-${TAG_NAME}") { - def new_version = openshift.selector('dc', "${COMPONENT_NAME}-${TAG_NAME}").object().status.latestVersion - if (new_version == old_version) { - echo "New deployment was not triggered." - currentBuild.result = "FAILURE" - return - } - def pod_selector = openshift.selector('pod', [ app:"${COMPONENT_NAME}-${TAG_NAME}" ]) - pod_selector.untilEach { - deployment = it.objects()[0].metadata.labels.deployment - echo deployment - if (deployment == "${COMPONENT_NAME}-${TAG_NAME}-${new_version}" && it.objects()[0].status.phase == 'Running' && it.objects()[0].status.containerStatuses[0].ready) { - return true - } else { - echo "Pod for new deployment not ready" - sleep 5 - return false - } - } - } - } - } - } - stage("Run pytests for ${COMPONENT_NAME}:${TAG_NAME}") { - script { - openshift.withCluster() { - openshift.withProject() { - def test_pipeline = openshift.selector('bc', 'pytest-pipeline') - try { - test_pipeline.startBuild('--wait=true', "-e=component=${COMPONENT_NAME}", "-e=component_tag=${TAG_NAME}", "-e=tag=${TAG_NAME}", "-e=namespace=${NAMESPACE}", "-e=db_type=PG").logs('-f') - echo "All tests passed" - } catch (Exception e) { - echo e.getMessage() - echo "Not all tests passed." - currentBuild.result = 'FAILURE' - } - } - } - } - } - } -}//end node diff --git a/Makefile b/Makefile deleted file mode 100644 index 1ce3f42e..00000000 --- a/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -.PHONY: setup -.PHONY: ci cd - -PROJECT_NAME=fas-ui -DOCKER_NAME=fas-ui - -################################################################################# -# COMMANDS -- Setup -# expects the terminal to be openshift login -# expects export OPENSHIFT_REPOSITORY="" -################################################################################# -setup: ## Clean and Install npm dependencies - npm ci - -################################################################################# -# COMMANDS - CI # -################################################################################# -ci: lint test - -lint: ## Run linting of code. - npm run lint:nofix - -test: ## Unit testing - npm run test:unit - -################################################################################# -# COMMANDS - CD -# expects the terminal to be openshift login -# expects export OPENSHIFT_DOCKER_REGISTRY="" -# expects export OPENSHIFT_SA_NAME="$(oc whoami)" -# expects export OPENSHIFT_SA_TOKEN="$(oc whoami -t)" -# expects export OPENSHIFT_REPOSITORY="" -# expects export TAG_NAME="dev/test" -################################################################################# -cd: ## CD flow -ifeq ($(TAG_NAME), test) -BUILD_TAG_NAME=test-latest -cd: build tag -else ifeq ($(TAG_NAME), prod) -BUILD_TAG_NAME=prod-latest -cd: build tag-production -else -BUILD_TAG_NAME=dev-latest -TAG_NAME=dev -cd: build tag -endif - -build: ## Build the docker container - docker build . -t $(DOCKER_NAME) \ - --build-arg VCS_REF=$(shell git rev-parse --short HEAD) \ - --build-arg BUILD_DATE=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ") \ - -build-nc: ## Build the docker container without caching - docker build --no-cache -t $(DOCKER_NAME) . - -REGISTRY_IMAGE=$(OPENSHIFT_DOCKER_REGISTRY)/$(OPENSHIFT_REPOSITORY)-tools/$(DOCKER_NAME) -push: #build ## Push the docker container to the registry & tag latest - @echo "$(OPENSHIFT_SA_TOKEN)" | docker login $(OPENSHIFT_DOCKER_REGISTRY) -u $(OPENSHIFT_SA_NAME) --password-stdin ;\ - docker tag $(DOCKER_NAME) $(REGISTRY_IMAGE):$(BUILD_TAG_NAME) ;\ - docker push $(REGISTRY_IMAGE):$(BUILD_TAG_NAME) - -tag: push ## tag image - oc -n "$(OPENSHIFT_REPOSITORY)-tools" tag $(DOCKER_NAME):$(BUILD_TAG_NAME) $(DOCKER_NAME):$(TAG_NAME) - -tag-production: push ## tag image - oc -n "$(OPENSHIFT_REPOSITORY)-tools" tag $(DOCKER_NAME):$(TAG_NAME) $(DOCKER_NAME):$(TAG_NAME)-$(shell date +%F) ;\ - oc -n "$(OPENSHIFT_REPOSITORY)-tools" tag $(DOCKER_NAME):$(BUILD_TAG_NAME) $(DOCKER_NAME):$(TAG_NAME) - -################################################################################# -# Self Documenting Commands # -################################################################################# -.PHONY: help - -.DEFAULT_GOAL := help - -help: - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' \ No newline at end of file diff --git a/README.md b/README.md index f5363298..397cc559 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,15 @@ # PAY-UI ## About -TBD. +This UI interfaces with PAY-API and provides functionality including: Fee Account System (FAS), EFT (Electronic Funds Transfer) and Refund UI. ## Usage ### Local Development -1. make sure you have the `.env` file, required contents can be found in `.env.production` +1. make sure you have the `.env` file, required contents can be found in `.env.example` 2. run docker -## Deployment (OpenShift) - -TBD - -## Getting Help or Reporting an Issue - -To report bugs/issues/feature requests, please file an [issue](https://github.com/bcgov/bcrs-entities-create-ui/issues/). - ## How to Contribute If you would like to contribute, please see our [CONTRIBUTING](CONTRIBUTING.md) guidelines. @@ -27,10 +19,6 @@ If you would like to contribute, please see our [CONTRIBUTING](CONTRIBUTING.md) Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. -## Issues/Suggestions -Make Suggestions/Issues [here!](https://github.com/bcgov/bcrs-entities-create-ui/issues/new) -Issues are [markdown supported](https://guides.github.com/features/mastering-markdown/). - ## License Copyright 2019 Province of British Columbia diff --git a/devops/cloudbuild-pr.yaml b/devops/cloudbuild-pr.yaml deleted file mode 100644 index 85d350e2..00000000 --- a/devops/cloudbuild-pr.yaml +++ /dev/null @@ -1,62 +0,0 @@ -steps: - # install / setup ci - - name: node:20.5.1 - entrypoint: npm - dir: "." - args: ['install'] - - # setup .env - - name: 'bash' - dir: "." - script: | - #!/usr/bin/env bash - cp .env.example .env - - # - # Generate the static site - # - - name: node:20.5.1 - dir: "." - entrypoint: npm - env: - - 'VUE_APP_ADDRESS_COMPLETE_KEY=$_VUE_APP_ADDRESS_COMPLETE_KEY' - - 'VUE_APP_PAY_LD_CLIENT_ID=$_VUE_APP_PAY_LD_CLIENT_ID' - - 'VUE_APP_REGISTRIES_SEARCH_API_KEY=$_VUE_APP_REGISTRIES_SEARCH_API_KEY' - args: ['--openssl-legacy-provider', 'run', 'build'] - - # - # Deploy to firebase channel, using the PR # - # store log to /workspace to get the channel URL - # - - name: gcr.io/yfthig-dev/firebase - dir: "." - entrypoint: bash - args: ['-c', 'firebase hosting:channel:deploy --project=yfthig-dev PR-$_PR_NUMBER > /workspace/firebase-deploy.txt'] - - # - # Update the PR with the temporary URL - # - - id: "Update the PR" - name: gcr.io/cloud-builders/curl - dir: "." - entrypoint: bash - args: - - -c - - | - # Read from "/workspace" - cat /workspace/firebase-deploy.txt - url=`cat /workspace/firebase-deploy.txt| grep 'Channel URL' | grep -Eo "https://[a-zA-Z0-9./?=_%:-]*"` - echo "this is the body:" - echo '{"body": "Temporary Url for review:'"$url"'"}' - curl -X POST \ - https://api.github.com/repos/bcgov/fas-ui/issues/$_PR_NUMBER/comments \ - --header "Authorization: Token $$TOKEN" \ - --header "Accept: application/vnd.github.v3+json" \ - --data-binary '{"body": "Temporary Url for review: '"$url"'"}' - secretEnv: ['TOKEN'] -availableSecrets: - secretManager: - - versionName: projects/$PROJECT_ID/secrets/token-pr-review/versions/latest - env: 'TOKEN' -options: - dynamic_substitutions: true diff --git a/devops/vaults.env b/devops/vaults.env deleted file mode 100644 index a176b029..00000000 --- a/devops/vaults.env +++ /dev/null @@ -1,29 +0,0 @@ -# Base Path -VUE_APP_PATH=/ - -#vaults Shared -VUE_APP_ADDRESS_COMPLETE_KEY="op://canadapost/$APP_ENV/address-key/ADDRESS_COMPLETE_KEY" - -#vaults web-url -VUE_APP_AUTH_WEB_URL="op://web-url/$APP_ENV/auth-web/AUTH_WEB_URL" -VUE_APP_SITEMINDER_LOGOUT_URL="op://web-url/$APP_ENV/siteminder/SITEMINDER_LOGOUT_URL" -VUE_APP_FAS_WEB_URL="op://web-url/$APP_ENV/fas-ui/FAS_WEB_URL" - -#vaults API -VUE_APP_AUTH_API_URL="op://API/$APP_ENV/auth-api/AUTH_API_URL" -VUE_APP_AUTH_API_VERSION="op://API/$APP_ENV/auth-api/AUTH_API_VERSION" -VUE_APP_STATUS_API_URL="op://API/$APP_ENV/status-api/STATUS_API_URL" -VUE_APP_STATUS_API_VERSION="op://API/$APP_ENV/status-api/STATUS_API_VERSION" -VUE_APP_PAY_API_URL="op://API/$APP_ENV/pay-api/PAY_API_URL" -VUE_APP_PAY_API_VERSION="op://API/$APP_ENV/pay-api/PAY_API_VERSION" - -#vaults keycloak -VUE_APP_KEYCLOAK_AUTH_URL="op://keycloak/$APP_ENV/base/KEYCLOAK_AUTH_BASE_URL" -VUE_APP_KEYCLOAK_REALM="op://keycloak/$APP_ENV/base/KEYCLOAK_REALMNAME" -VUE_APP_KEYCLOAK_CLIENTID="op://keycloak/$APP_ENV/fas-web/UI_KEYCLOAK_RESOURCE_NAME" - -#vaults launchdarkly -VUE_APP_PAY_LD_CLIENT_ID="op://launchdarkly/$APP_ENV/pay/PAY_LD_CLIENT_ID" - -# Google Analytics -VUE_APP_GTAG_ID="op://google-analytics/$APP_ENV/developer/GTAG" diff --git a/index.html b/index.html deleted file mode 100644 index 1a4dbedb..00000000 --- a/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - -
- - - ->16&255,h[f++]=a>>8&255,h[f++]=255&a
-2===u&&(a=r[e.charCodeAt(s)]<<2|r[e.charCodeAt(s+1)]>>4,h[f++]=255&a)
-1===u&&(a=r[e.charCodeAt(s)]<<10|r[e.charCodeAt(s+1)]<<4|r[e.charCodeAt(s+2)]>>2,h[f++]=a>>8&255,h[f++]=255&a)
-return h},base64Js.fromByteArray=function fromByteArray(r){for(var o,a=r.length,s=a%3,l=[],c=16383,u=0,h=a-s;u None of the routing slips matched this search. Try another search.
- {{ $t('dashboardSubText') }}
- {{ routingSlipAddress.contactName }} Name of Person or Organization & Address Routing slip Payment Information
- {{ $t('linkRoutingSlipSubText') }}
-
-
-
- {{ $t('paymentInformationSubText') }}
- Linked with:
- Try searching with a different routing slip unique ID
- {{ routingSlipContactName }}
- {{ $t('routingSlipTransactionSubText') }}
- Add Manual Transaction
- {{ $t(status) }}
- Transactions {{ `(${invoiceCount})` }}
- {{ description }}
-
-
- {{ confirmDialogText }}
-
- Unsettled Amount: {{ unsettledAmount }}
-
- Caution: Please verify if the unsettled amount of {{ unsettledAmount }} on the short name
- can be refunded or linked to a new account. If it's insufficient to settle an outstanding statement,
- the settlement process will be on hold until full payment is received.
-
- Enter the contact email provided in the client's Direct Deposit Application form
-
- Enter the supplier number created in CAS for this short name
-
- Enter the supplier site created in CAS for this short name
-
- Short Name Type: {{ getShortNameTypeDescription(currentShortName.shortNameType) }}
- After the account has been linked, payment will be applied at 6:00 p.m. Pacific Time.
- Unsettled amount from the short name: {{ formatCurrency(currentShortName.creditsRemaining) }}
-
- Amount owing on the selected account (Statement #{{ statementId }}):
- {{ formatCurrency(selectedAccount.totalDue) }}
-
- Important:
- The unsettled amount from the short name does not match with the amount owing on the account.
- This could result in over or under payment settlement.
- Please make sure you have selected the correct account to link.
-
- Accounts with EFT Payment Method Selected
-
- Amount Owing
-
- No accounts found
-
- {{ confirmDialogText }}
-
- By declining the request, the amount will remain unsettled in the short name.
- None of the routing slips matched this search. Try another search. {{$t('unauthorizedMsg')}}
- {{ $t('reviewRoutingSlipText') }}
- {{ $t('text.linkedRSChildInfoP1') }} {{ $t('text.linkedRSChildInfoP2') }}
+
+ {{ $t('text.cantLinkBecauseVoided') }}
+
+
+ {{ $t('text.cantLinkSinceInvoicesExistP1') }}
+
+
+ {{ $t('text.cantLinkBecauseVoided') }}
+
+
+ {{ $t('text.routingSlipNoLinkedRoutingSlips') }}
+
+
+ {{ $t('text.linkRSSearchInfo') }}
+
+ {{ $t('text.chequeAdviceHelp') }}
+
+
+ {{ status }}
+
+
+ {{ commentItem.submitterDisplayName }}
+ ‐
+ {{ formatTimestamp(commentItem.timestamp) }}
+
+ Transactions
+
+ ({{ invoiceCount }})
+
+ {{ description }}
+
+ {{ state.confirmDialogText }}
+
+ {{ dialogConfig.description }}
+
+ Please enter a valid email address
+
+ Short Name Type: {{ shortNameTypeDescription }}
+
+ After the account has been linked, payment will be applied at 6:00 p.m. Pacific Time.
+
+ Important:
+ The unsettled amount from the short name does not match with the amount owing on the account.
+ This could result in over or under payment settlement.
+ Please make sure you have selected the correct account to link.
+
+ {{ errorDialogText }}
+
+ {{ confirmDialog.message }}
+
+ By declining the request, the amount will remain unsettled in the short name.
+ {for(var s,l=a>1?void 0:a?__getOwnPropDesc$2(r,o):r,c=e.length-1;c>=0;c--)(s=e[c])&&(l=(a?s(r,o,l):s(l))||l)
-return a&&l&&__defProp$2(r,o,l),l}
-let AuthModule=class extends VuexModule{constructor(){super(...arguments),__publicField(this,"token",""),__publicField(this,"idToken",""),__publicField(this,"refreshToken",""),__publicField(this,"kcGuid",""),__publicField(this,"loginSource","")}get isAuthenticated(){return!!this.token}get keycloakGuid(){return this.kcGuid||KeyCloakService$1.getUserInfo().keycloakGuid}get currentLoginSource(){return this.loginSource||KeyCloakService$1.getUserInfo().loginSource}setKCToken(e){this.token=e,ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakToken,e)}setIDToken(e){this.idToken=e,ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakIdToken,e)}setRefreshToken(e){this.refreshToken=e,ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakRefreshToken,e)}setKCGuid(e){this.kcGuid=e}setLoginSource(e){this.loginSource=e}clearSession(){this.context.commit("setKCToken",""),this.context.commit("setIDToken",""),this.context.commit("setRefreshToken",""),this.context.commit("setKCGuid",""),this.context.commit("setLoginSource","")}syncWithSessionStorage(){this.context.commit("setKCToken",ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakToken)||""),this.context.commit("setIDToken",ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakIdToken)||""),this.context.commit("setRefreshToken",ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakRefreshToken)||"")}}
-__decorateClass$2([Mutation],AuthModule.prototype,"setKCToken",1),__decorateClass$2([Mutation],AuthModule.prototype,"setIDToken",1),__decorateClass$2([Mutation],AuthModule.prototype,"setRefreshToken",1),__decorateClass$2([Mutation],AuthModule.prototype,"setKCGuid",1),__decorateClass$2([Mutation],AuthModule.prototype,"setLoginSource",1),__decorateClass$2([Action({rawError:!0})],AuthModule.prototype,"clearSession",1),__decorateClass$2([Action({rawError:!0})],AuthModule.prototype,"syncWithSessionStorage",1),AuthModule=__decorateClass$2([Module({name:"auth",namespaced:!0})],AuthModule)
-const _KeyCloakService=class _KeyCloakService{constructor(){__publicField(this,"kc"),__publicField(this,"parsedToken"),__publicField(this,"store",null),__publicField(this,"counter",0),__publicField(this,"REFRESH_ATTEMPT_INTERVAL",10),__publicField(this,"timerId",0)}static getInstance(){return this.instance?this.instance:new _KeyCloakService}get isInitialized(){return!!this.kc}async setKeycloakConfigUrl(e){ConfigHelper$1.setKeycloakConfigUrl(e)}getKCInstance(){return this.kc}async initializeKeyCloak(e,r){this.store=r,this.clearSession()
-const o=ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakToken)||void 0,a=ConfigHelper$1.getKeycloakConfigUrl()
-this.kc=Keycloak(a)
-const s=this.kc.login
-this.kc.login=r=>(r&&(r.idpHint=e),s(r))
-let l={onLoad:"login-required",checkLoginIframe:!1,timeSkew:0,token:o,refreshToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakRefreshToken)||void 0,idToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakIdToken)||void 0,pkceMethod:"S256"}
-return this.kc.init(l)}async initSession(){var e,r,o
-if(!this.store)return
-const a=getModule(AuthModule,this.store)
-a.setKCToken((null==(e=this.kc)?void 0:e.token)||""),a.setIDToken((null==(r=this.kc)?void 0:r.idToken)||""),a.setRefreshToken((null==(o=this.kc)?void 0:o.refreshToken)||"")
-const s=this.getUserInfo()
-a.setKCGuid((null==s?void 0:s.keycloakGuid)||""),a.setLoginSource((null==s?void 0:s.loginSource)||""),await this.syncSessionAndScheduleTokenRefresh()}getUserInfo(){var e,r,o,a,s,l,c,u,h
-return this.parsedToken&&Object.keys(this.parsedToken).length||(this.parsedToken=decodeKCToken()),{lastName:null==(e=this.parsedToken)?void 0:e.lastname,firstName:null==(r=this.parsedToken)?void 0:r.firstname,email:null==(o=this.parsedToken)?void 0:o.email,roles:null==(s=null==(a=this.parsedToken)?void 0:a.realm_access)?void 0:s.roles,keycloakGuid:null==(l=this.parsedToken)?void 0:l.sub,userName:null==(c=this.parsedToken)?void 0:c.username,fullName:null==(u=this.parsedToken)?void 0:u.name,loginSource:null==(h=this.parsedToken)?void 0:h.loginSource}}async logout(e){let r=ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakToken)||void 0
-if(r){this.kc=Keycloak(ConfigHelper$1.getKeycloakConfigUrl())
-let o={onLoad:"login-required",checkLoginIframe:!1,timeSkew:0,token:r,refreshToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakRefreshToken)||void 0,idToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakIdToken)||void 0,pkceMethod:"S256"}
-const a=ConfigHelper$1.getFromSession(SessionStorageKeys.SiteminderLogoutUrl)||void 0
-return ConfigHelper$1.clearSession(),ConfigHelper$1.addToSession(SessionStorageKeys.PreventStorageSync,!0),new Promise(((r,s)=>{this.kc&&this.kc.init(o).then((o=>{o||r(),e=e||`${window.location.origin}${process.env.VUE_APP_PATH}`,(null==a?void 0:a.includes("http"))&&(e=`${a}?returl=${e.replace(/(https?:\/\/)|(\/)+/g,"$1$2")}&retnow=1`),this.kc&&this.kc.logout({redirectUri:e}).then((()=>{r()})).catch((e=>{s(e)}))})).catch((e=>{s(e)}))}))}}async refreshToken(e){var r,o
-if(!(e||(null==(o=null==(r=this.kc)?void 0:r.tokenParsed)?void 0:o.exp)&&this.kc.timeSkew))return
-let a=e?-1:this.kc.tokenParsed.exp-Math.ceil((new Date).getTime()/1e3)+this.kc.timeSkew+100
-if(!this.kc)return new Error("Could not refresh Token:No Kc Instance")
-this.kc.updateToken(a).then((e=>{e&&this.initSession()})).catch((()=>(this.clearSession(),new Error("Could not refresh Token"))))}verifyRoles(e,r){let o=!1
-if(e||r){let a=this.getUserInfo()
-o=e?e.some((e=>a.roles.includes(e))):!r.some((e=>a.roles.includes(e)))}else o=!0
-return o}async initializeToken(e,r=!0,o=!1){this.store=e
-const a={onLoad:o?"login-required":"check-sso",checkLoginIframe:!1,timeSkew:0,token:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakToken)||void 0,refreshToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakRefreshToken)||void 0,idToken:ConfigHelper$1.getFromSession(SessionStorageKeys.KeyCloakIdToken)||void 0,pkceMethod:"S256"}
-return new Promise(((e,o)=>{this.kc=Keycloak(ConfigHelper$1.getKeycloakConfigUrl()),ConfigHelper$1.addToSession(SessionStorageKeys.SessionSynced,!1),this.kc.init(a).then((o=>{console.info("[TokenServices] is User Authenticated?: Syncing "+o),e(this.syncSessionAndScheduleTokenRefresh(r))})).catch((e=>{o(new Error("Could not Initialize KC"+e))}))}))}async syncSessionAndScheduleTokenRefresh(e=!0){var r
-return(null==(r=this.kc)?void 0:r.authenticated)?(this.syncSessionStorage(),e&&this.scheduleRefreshTimer(),this.kc.token):(this.clearSession(),new Error("NOT_AUTHENTICATED"))}scheduleRefreshTimer(e=0){let r=1e3*Math.max(this.REFRESH_ATTEMPT_INTERVAL,e)
-this.scheduleRefreshToken(r)}scheduleRefreshToken(e){let r=-1
-if(this.kc&&void 0!==this.kc.timeSkew&&this.kc.refreshTokenParsed&&(r=this.kc.refreshTokenParsed.exp-Math.ceil((new Date).getTime()/1e3)+this.kc.timeSkew),r<0)throw new Error("Refresh Token Expired. No more token refreshes")
-let o=-1
-if(this.kc&&this.kc.tokenParsed&&this.kc.tokenParsed.exp&&void 0!==this.kc.timeSkew&&(o=this.kc.tokenParsed.exp-Math.ceil((new Date).getTime()/1e3)+this.kc.timeSkew),o<0)throw new Error("Refresh Token Expired. No more token refreshes")
-let a=1e3*o-e
-console.info("[TokenServices] Token Refresh Scheduled in %s Seconds",a/1e3),this.timerId=setTimeout((()=>{console.log("[TokenServices] Refreshing Token Attempt: %s ",++this.counter),this.kc.updateToken(-1).then((r=>{r&&(console.log("Token successfully refreshed"),this.syncSessionStorage(),this.scheduleRefreshToken(e))})).catch((()=>{clearTimeout(this.timerId)}))}),a)}syncSessionStorage(){this.kc?(this.kc.token&&ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakToken,this.kc.token),this.kc.refreshToken&&ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakRefreshToken,this.kc.refreshToken),this.kc.idToken&&ConfigHelper$1.addToSession(SessionStorageKeys.KeyCloakIdToken,this.kc.idToken),ConfigHelper$1.addToSession(SessionStorageKeys.SessionSynced,!0)):ConfigHelper$1.addToSession(SessionStorageKeys.SessionSynced,!1)}async clearSession(){if(this.store){getModule(AuthModule,this.store).clearSession()}ConfigHelper$1.removeFromSession(SessionStorageKeys.KeyCloakToken),ConfigHelper$1.removeFromSession(SessionStorageKeys.KeyCloakIdToken),ConfigHelper$1.removeFromSession(SessionStorageKeys.KeyCloakRefreshToken)}}
-__publicField(_KeyCloakService,"instance")
-let KeyCloakService=_KeyCloakService
-const KeyCloakService$1=KeyCloakService.getInstance()
-
-;//! moment.js
-//! version : 2.29.4
-//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
-//! license : MIT
-//! momentjs.com
-var hookCallback,some
-function hooks(){return hookCallback.apply(null,arguments)}function setHookCallback(e){hookCallback=e}function isArray$2(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function isObject$2(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function hasOwnProp(e,r){return Object.prototype.hasOwnProperty.call(e,r)}function isObjectEmpty(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length
-var r
-for(r in e)if(hasOwnProp(e,r))return!1
-return!0}function isUndefined$1(e){return void 0===e}function isNumber$1(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function isDate$1(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function map(e,r){var o,a=[],s=e.length
-for(o=0;o>>0
-for(r=0;r0)for(o=0;o68?1900:2e3)}
-var getSetYear=makeGetSet("FullYear",!0)
-function getIsLeapYear(){return isLeapYear(this.year())}function createDate(e,r,o,a,s,l,c){var u
-return e<100&&e>=0?(u=new Date(e+400,r,o,a,s,l,c),isFinite(u.getFullYear())&&u.setFullYear(e)):u=new Date(e,r,o,a,s,l,c),u}function createUTCDate(e){var r,o
-return e<100&&e>=0?((o=Array.prototype.slice.call(arguments))[0]=e+400,r=new Date(Date.UTC.apply(null,o)),isFinite(r.getUTCFullYear())&&r.setUTCFullYear(e)):r=new Date(Date.UTC.apply(null,arguments)),r}function firstWeekOffset(e,r,o){var a=7+r-o
-return-((7+createUTCDate(e,0,a).getUTCDay()-r)%7)+a-1}function dayOfYearFromWeeks(e,r,o,a,s){var l,c,u=1+7*(r-1)+(7+o-a)%7+firstWeekOffset(e,a,s)
-return u<=0?c=daysInYear(l=e-1)+u:u>daysInYear(e)?(l=e+1,c=u-daysInYear(e)):(l=e,c=u),{year:l,dayOfYear:c}}function weekOfYear(e,r,o){var a,s,l=firstWeekOffset(e.year(),r,o),c=Math.floor((e.dayOfYear()-l-1)/7)+1
-return c<1?a=c+weeksInYear(s=e.year()-1,r,o):c>weeksInYear(e.year(),r,o)?(a=c-weeksInYear(e.year(),r,o),s=e.year()+1):(s=e.year(),a=c),{week:a,year:s}}function weeksInYear(e,r,o){var a=firstWeekOffset(e,r,o),s=firstWeekOffset(e+1,r,o)
-return(daysInYear(e)-a+s)/7}function localeWeek(e){return weekOfYear(e,this._week.dow,this._week.doy).week}addFormatToken("w",["ww",2],"wo","week"),addFormatToken("W",["WW",2],"Wo","isoWeek"),addUnitAlias("week","w"),addUnitAlias("isoWeek","W"),addUnitPriority("week",5),addUnitPriority("isoWeek",5),addRegexToken("w",match1to2),addRegexToken("ww",match1to2,match2),addRegexToken("W",match1to2),addRegexToken("WW",match1to2,match2),addWeekParseToken(["w","ww","W","WW"],(function(e,r,o,a){r[a.substr(0,1)]=toInt(e)}))
-var defaultLocaleWeek={dow:0,doy:6}
-function localeFirstDayOfWeek(){return this._week.dow}function localeFirstDayOfYear(){return this._week.doy}function getSetWeek(e){var r=this.localeData().week(this)
-return null==e?r:this.add(7*(e-r),"d")}function getSetISOWeek(e){var r=weekOfYear(this,1,4).week
-return null==e?r:this.add(7*(e-r),"d")}function parseWeekday(e,r){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=r.weekdaysParse(e))?e:null:parseInt(e,10)}function parseIsoWeekday(e,r){return"string"==typeof e?r.weekdaysParse(e)%7||7:isNaN(e)?null:e}function shiftWeekdays(e,r){return e.slice(r,7).concat(e.slice(0,r))}addFormatToken("d",0,"do","day"),addFormatToken("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),addFormatToken("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),addFormatToken("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),addFormatToken("e",0,0,"weekday"),addFormatToken("E",0,0,"isoWeekday"),addUnitAlias("day","d"),addUnitAlias("weekday","e"),addUnitAlias("isoWeekday","E"),addUnitPriority("day",11),addUnitPriority("weekday",11),addUnitPriority("isoWeekday",11),addRegexToken("d",match1to2),addRegexToken("e",match1to2),addRegexToken("E",match1to2),addRegexToken("dd",(function(e,r){return r.weekdaysMinRegex(e)})),addRegexToken("ddd",(function(e,r){return r.weekdaysShortRegex(e)})),addRegexToken("dddd",(function(e,r){return r.weekdaysRegex(e)})),addWeekParseToken(["dd","ddd","dddd"],(function(e,r,o,a){var s=o._locale.weekdaysParse(e,a,o._strict)
-null!=s?r.d=s:getParsingFlags(o).invalidWeekday=e})),addWeekParseToken(["d","e","E"],(function(e,r,o,a){r[a]=toInt(e)}))
-var defaultLocaleWeekdays="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),defaultLocaleWeekdaysShort="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),defaultLocaleWeekdaysMin="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),defaultWeekdaysRegex=matchWord,defaultWeekdaysShortRegex=matchWord,defaultWeekdaysMinRegex=matchWord
-function localeWeekdays(e,r){var o=isArray$2(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(r)?"format":"standalone"]
-return!0===e?shiftWeekdays(o,this._week.dow):e?o[e.day()]:o}function localeWeekdaysShort(e){return!0===e?shiftWeekdays(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function localeWeekdaysMin(e){return!0===e?shiftWeekdays(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function handleStrictParse$1(e,r,o){var a,s,l,c=e.toLocaleLowerCase()
-if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],a=0;a<7;++a)l=createUTC([2e3,1]).day(a),this._minWeekdaysParse[a]=this.weekdaysMin(l,"").toLocaleLowerCase(),this._shortWeekdaysParse[a]=this.weekdaysShort(l,"").toLocaleLowerCase(),this._weekdaysParse[a]=this.weekdays(l,"").toLocaleLowerCase()
-return o?"dddd"===r?-1!==(s=indexOf.call(this._weekdaysParse,c))?s:null:"ddd"===r?-1!==(s=indexOf.call(this._shortWeekdaysParse,c))?s:null:-1!==(s=indexOf.call(this._minWeekdaysParse,c))?s:null:"dddd"===r?-1!==(s=indexOf.call(this._weekdaysParse,c))||-1!==(s=indexOf.call(this._shortWeekdaysParse,c))||-1!==(s=indexOf.call(this._minWeekdaysParse,c))?s:null:"ddd"===r?-1!==(s=indexOf.call(this._shortWeekdaysParse,c))||-1!==(s=indexOf.call(this._weekdaysParse,c))||-1!==(s=indexOf.call(this._minWeekdaysParse,c))?s:null:-1!==(s=indexOf.call(this._minWeekdaysParse,c))||-1!==(s=indexOf.call(this._weekdaysParse,c))||-1!==(s=indexOf.call(this._shortWeekdaysParse,c))?s:null}function localeWeekdaysParse(e,r,o){var a,s,l
-if(this._weekdaysParseExact)return handleStrictParse$1.call(this,e,r,o)
-for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),a=0;a<7;a++){if(s=createUTC([2e3,1]).day(a),o&&!this._fullWeekdaysParse[a]&&(this._fullWeekdaysParse[a]=new RegExp("^"+this.weekdays(s,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[a]=new RegExp("^"+this.weekdaysShort(s,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[a]=new RegExp("^"+this.weekdaysMin(s,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[a]||(l="^"+this.weekdays(s,"")+"|^"+this.weekdaysShort(s,"")+"|^"+this.weekdaysMin(s,""),this._weekdaysParse[a]=new RegExp(l.replace(".",""),"i")),o&&"dddd"===r&&this._fullWeekdaysParse[a].test(e))return a
-if(o&&"ddd"===r&&this._shortWeekdaysParse[a].test(e))return a
-if(o&&"dd"===r&&this._minWeekdaysParse[a].test(e))return a
-if(!o&&this._weekdaysParse[a].test(e))return a}}function getSetDayOfWeek(e){if(!this.isValid())return null!=e?this:NaN
-var r=this._isUTC?this._d.getUTCDay():this._d.getDay()
-return null!=e?(e=parseWeekday(e,this.localeData()),this.add(e-r,"d")):r}function getSetLocaleDayOfWeek(e){if(!this.isValid())return null!=e?this:NaN
-var r=(this.day()+7-this.localeData()._week.dow)%7
-return null==e?r:this.add(e-r,"d")}function getSetISODayOfWeek(e){if(!this.isValid())return null!=e?this:NaN
-if(null!=e){var r=parseIsoWeekday(e,this.localeData())
-return this.day(this.day()%7?r:r-7)}return this.day()||7}function weekdaysRegex(e){return this._weekdaysParseExact?(hasOwnProp(this,"_weekdaysRegex")||computeWeekdaysParse.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(hasOwnProp(this,"_weekdaysRegex")||(this._weekdaysRegex=defaultWeekdaysRegex),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function weekdaysShortRegex(e){return this._weekdaysParseExact?(hasOwnProp(this,"_weekdaysRegex")||computeWeekdaysParse.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(hasOwnProp(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=defaultWeekdaysShortRegex),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function weekdaysMinRegex(e){return this._weekdaysParseExact?(hasOwnProp(this,"_weekdaysRegex")||computeWeekdaysParse.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(hasOwnProp(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=defaultWeekdaysMinRegex),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function computeWeekdaysParse(){function cmpLenRev(e,r){return r.length-e.length}var e,r,o,a,s,l=[],c=[],u=[],h=[]
-for(e=0;e<7;e++)r=createUTC([2e3,1]).day(e),o=regexEscape(this.weekdaysMin(r,"")),a=regexEscape(this.weekdaysShort(r,"")),s=regexEscape(this.weekdays(r,"")),l.push(o),c.push(a),u.push(s),h.push(o),h.push(a),h.push(s)
-l.sort(cmpLenRev),c.sort(cmpLenRev),u.sort(cmpLenRev),h.sort(cmpLenRev),this._weekdaysRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+c.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+l.join("|")+")","i")}function hFormat(){return this.hours()%12||12}function kFormat(){return this.hours()||24}function meridiem(e,r){addFormatToken(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),r)}))}function matchMeridiem(e,r){return r._meridiemParse}function localeIsPM(e){return"p"===(e+"").toLowerCase().charAt(0)}addFormatToken("H",["HH",2],0,"hour"),addFormatToken("h",["hh",2],0,hFormat),addFormatToken("k",["kk",2],0,kFormat),addFormatToken("hmm",0,0,(function(){return""+hFormat.apply(this)+zeroFill(this.minutes(),2)})),addFormatToken("hmmss",0,0,(function(){return""+hFormat.apply(this)+zeroFill(this.minutes(),2)+zeroFill(this.seconds(),2)})),addFormatToken("Hmm",0,0,(function(){return""+this.hours()+zeroFill(this.minutes(),2)})),addFormatToken("Hmmss",0,0,(function(){return""+this.hours()+zeroFill(this.minutes(),2)+zeroFill(this.seconds(),2)})),meridiem("a",!0),meridiem("A",!1),addUnitAlias("hour","h"),addUnitPriority("hour",13),addRegexToken("a",matchMeridiem),addRegexToken("A",matchMeridiem),addRegexToken("H",match1to2),addRegexToken("h",match1to2),addRegexToken("k",match1to2),addRegexToken("HH",match1to2,match2),addRegexToken("hh",match1to2,match2),addRegexToken("kk",match1to2,match2),addRegexToken("hmm",match3to4),addRegexToken("hmmss",match5to6),addRegexToken("Hmm",match3to4),addRegexToken("Hmmss",match5to6),addParseToken(["H","HH"],HOUR),addParseToken(["k","kk"],(function(e,r,o){var a=toInt(e)
-r[HOUR]=24===a?0:a})),addParseToken(["a","A"],(function(e,r,o){o._isPm=o._locale.isPM(e),o._meridiem=e})),addParseToken(["h","hh"],(function(e,r,o){r[HOUR]=toInt(e),getParsingFlags(o).bigHour=!0})),addParseToken("hmm",(function(e,r,o){var a=e.length-2
-r[HOUR]=toInt(e.substr(0,a)),r[MINUTE]=toInt(e.substr(a)),getParsingFlags(o).bigHour=!0})),addParseToken("hmmss",(function(e,r,o){var a=e.length-4,s=e.length-2
-r[HOUR]=toInt(e.substr(0,a)),r[MINUTE]=toInt(e.substr(a,2)),r[SECOND]=toInt(e.substr(s)),getParsingFlags(o).bigHour=!0})),addParseToken("Hmm",(function(e,r,o){var a=e.length-2
-r[HOUR]=toInt(e.substr(0,a)),r[MINUTE]=toInt(e.substr(a))})),addParseToken("Hmmss",(function(e,r,o){var a=e.length-4,s=e.length-2
-r[HOUR]=toInt(e.substr(0,a)),r[MINUTE]=toInt(e.substr(a,2)),r[SECOND]=toInt(e.substr(s))}))
-var defaultLocaleMeridiemParse=/[ap]\.?m?\.?/i,getSetHour=makeGetSet("Hours",!0)
-function localeMeridiem(e,r,o){return e>11?o?"pm":"PM":o?"am":"AM"}var baseConfig={calendar:defaultCalendar,longDateFormat:defaultLongDateFormat,invalidDate:defaultInvalidDate,ordinal:defaultOrdinal,dayOfMonthOrdinalParse:defaultDayOfMonthOrdinalParse,relativeTime:defaultRelativeTime,months:defaultLocaleMonths,monthsShort:defaultLocaleMonthsShort,week:defaultLocaleWeek,weekdays:defaultLocaleWeekdays,weekdaysMin:defaultLocaleWeekdaysMin,weekdaysShort:defaultLocaleWeekdaysShort,meridiemParse:defaultLocaleMeridiemParse},locales={},localeFamilies={},globalLocale
-function commonPrefix(e,r){var o,a=Math.min(e.length,r.length)
-for(o=0;o0;){if(a=loadLocale(s.slice(0,r).join("-")))return a
-if(o&&o.length>=r&&commonPrefix(s,o)>=r-1)break
-r--}l++}return globalLocale}function isLocaleNameSane(e){return null!=e.match("^[^/\\\\]*$")}function loadLocale(e){var r=null
-if(void 0===locales[e]&&"undefined"!=typeof module&&module&&module.exports&&isLocaleNameSane(e))try{r=globalLocale._abbr,require("./locale/"+e),getSetGlobalLocale(r)}catch(o){locales[e]=null}return locales[e]}function getSetGlobalLocale(e,r){var o
-return e&&((o=isUndefined$1(r)?getLocale(e):defineLocale(e,r))?globalLocale=o:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),globalLocale._abbr}function defineLocale(e,r){if(null!==r){var o,a=baseConfig
-if(r.abbr=e,null!=locales[e])deprecateSimple("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),a=locales[e]._config
-else if(null!=r.parentLocale)if(null!=locales[r.parentLocale])a=locales[r.parentLocale]._config
-else{if(null==(o=loadLocale(r.parentLocale)))return localeFamilies[r.parentLocale]||(localeFamilies[r.parentLocale]=[]),localeFamilies[r.parentLocale].push({name:e,config:r}),null
-a=o._config}return locales[e]=new Locale(mergeConfigs(a,r)),localeFamilies[e]&&localeFamilies[e].forEach((function(e){defineLocale(e.name,e.config)})),getSetGlobalLocale(e),locales[e]}return delete locales[e],null}function updateLocale(e,r){if(null!=r){var o,a,s=baseConfig
-null!=locales[e]&&null!=locales[e].parentLocale?locales[e].set(mergeConfigs(locales[e]._config,r)):(null!=(a=loadLocale(e))&&(s=a._config),r=mergeConfigs(s,r),null==a&&(r.abbr=e),(o=new Locale(r)).parentLocale=locales[e],locales[e]=o),getSetGlobalLocale(e)}else null!=locales[e]&&(null!=locales[e].parentLocale?(locales[e]=locales[e].parentLocale,e===getSetGlobalLocale()&&getSetGlobalLocale(e)):null!=locales[e]&&delete locales[e])
-return locales[e]}function getLocale(e){var r
-if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return globalLocale
-if(!isArray$2(e)){if(r=loadLocale(e))return r
-e=[e]}return chooseLocale(e)}function listLocales(){return keys(locales)}function checkOverflow(e){var r,o=e._a
-return o&&-2===getParsingFlags(e).overflow&&(r=o[MONTH]<0||o[MONTH]>11?MONTH:o[DATE]<1||o[DATE]>daysInMonth(o[YEAR],o[MONTH])?DATE:o[HOUR]<0||o[HOUR]>24||24===o[HOUR]&&(0!==o[MINUTE]||0!==o[SECOND]||0!==o[MILLISECOND])?HOUR:o[MINUTE]<0||o[MINUTE]>59?MINUTE:o[SECOND]<0||o[SECOND]>59?SECOND:o[MILLISECOND]<0||o[MILLISECOND]>999?MILLISECOND:-1,getParsingFlags(e)._overflowDayOfYear&&(rNo Results
Click on the routing slip number above to access to the linked routing slip.",linkRSSearchInfo="When you link to another routing slip, this routing slip’s total balance will transfer to the linked routing slip. After linking to another routing slip this routing slip will be inactive.",linkRoutingSlipSearchTitleParent="This routing slip is linked with:",linkRoutingSlipSearchTitleChild="This routing slip has been linked to:",addManualTransactionQuantityInfoText="The priority or future effective fee will only be applied once. Input transactions separately to add additional fee",cantLinkSinceInvoicesExistMsg="This routing slip cannot link to another routing slip since transactions were made.
Other routing slips can link to this routing slip",cantLinkBecauseVoidedMsg="This routing slip cannot link to another routing slip since it is voided.",cantAddTransactions="Transaction can't be added, since the filling type total amount exceeds the routing slip's current balance",reviewRoutingSlipText="Manage, and review details for this routing slip",NSFWarningText="By placing status to NSF, this routing slip will not be usable, and current transactions will change to pending until it has been repaid by having another slip linked to it.",NSFWarningTitle="Place Routing Slip to NSF?",WriteOffWarningTitle="Authorize Write-off?",WriteOffWarningText="By approving write-off, the routing slip balance will close, and no further transactions may be made using this routing slip.",VoidWarningTitle="Void Routing Slip?",VoidWarningText="By placing status to void, this routing slip will not be usable, and this action cannot be undone.",enLocals={message:message,homeBtnLabel:homeBtnLabel,pageNotFoundTitle:pageNotFoundTitle,pageNotFoundMsg:pageNotFoundMsg,createRoutingSlipSuccessTitle:createRoutingSlipSuccessTitle,createRoutingSlipSuccessText:createRoutingSlipSuccessText,createRoutingSlipCancelTitle:createRoutingSlipCancelTitle,createRoutingSlipCancelText:createRoutingSlipCancelText,unauthorizedTitle:unauthorizedTitle,unauthorizedMsg:unauthorizedMsg,errorAlertMessage:errorAlertMessage,searchStartMessage:searchStartMessage,dashboardSubText:dashboardSubText,routingSlipTransactionSubText:routingSlipTransactionSubText,paymentInformationSubText:paymentInformationSubText,searchNoResult:searchNoResult,linkRoutingSlipSubText:linkRoutingSlipSubText,linkedRSChildInfo:linkedRSChildInfo,linkRSSearchInfo:linkRSSearchInfo,linkRoutingSlipSearchTitleParent:linkRoutingSlipSearchTitleParent,linkRoutingSlipSearchTitleChild:linkRoutingSlipSearchTitleChild,addManualTransactionQuantityInfoText:addManualTransactionQuantityInfoText,cantLinkSinceInvoicesExistMsg:cantLinkSinceInvoicesExistMsg,cantLinkBecauseVoidedMsg:cantLinkBecauseVoidedMsg,cantAddTransactions:cantAddTransactions,reviewRoutingSlipText:reviewRoutingSlipText,NSFWarningText:NSFWarningText,NSFWarningTitle:NSFWarningTitle,WriteOffWarningTitle:WriteOffWarningTitle,WriteOffWarningText:WriteOffWarningText,VoidWarningTitle:VoidWarningTitle,VoidWarningText:VoidWarningText}
-function initialize(e){e.use(VueI18n$1)
-return createI18n({locale:{}.VUE_APP_I18N_LOCALE||"en",fallbackLocale:{}.VUE_APP_I18N_FALLBACK_LOCALE||"en",messages:function loadLocaleMessages(){const e={en:{}}
-return Object.keys(enLocals).forEach((r=>{e.en[r]=enLocals[r]})),e}()})}function install(e,r){if(Vue$1!==e&&console.error("Multiple instances of Vue detected "),install.installed)return
-install.installed=!0,Object.hasOwnProperty.call(e.config.optionMergeStrategies,"setup")?console.info("[FAS-Plugin] VueCompositionAPI already installed"):(e.use(VueCompositionAPI),console.info("[FAS-Plugin] VueCompositionAPI is not available in parent so pushing from plugin"))
-const o=initialize(e)
-r.i18n&&o&&o.messages?r.i18n.mergeLocaleMessage(r.i18n.locale,o.messages[o.locale]):console.error("[FAS-Plugin] please provide i18n to use lang"),r.store?window.fasStore=r.store:console.error("[FAS-Plugin] please provide store"),e.component("fas-search-component",Search)}const plugin={install:install}
-let GlobalVue=null
-return"undefined"!=typeof window?GlobalVue=window.Vue:"undefined"!=typeof global&&(GlobalVue=global.vue),GlobalVue&&GlobalVue.use(plugin),Search.install=install,Search}))
-//# sourceMappingURL=lib.umd.min.js.map
diff --git a/lib/lib.umd.min.js.map b/lib/lib.umd.min.js.map
deleted file mode 100644
index 6d75b0a7..00000000
--- a/lib/lib.umd.min.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"file":"lib.umd.min.js","sources":["../src/shims-vue-composition-api.ts","../src/util/constants.ts","../node_modules/js-sha256/src/sha256.js","../node_modules/keycloak-js/node_modules/base64-js/index.js","../node_modules/keycloak-js/dist/keycloak.js","../node_modules/sbc-common-components/src/util/constants.ts","../node_modules/sbc-common-components/src/util/common-util.ts","../node_modules/sbc-common-components/src/util/config-helper.ts","../node_modules/vuex-module-decorators/dist/esm/index.js","../node_modules/sbc-common-components/src/store/modules/auth.ts","../node_modules/sbc-common-components/src/services/keycloak.services.ts","../node_modules/moment/dist/moment.js","../src/util/common-util.ts","../src/util/config-helper.ts","../src/util/debounce.ts","../src/composables/useIndicators.ts","../src/composables/common/useLoader.ts","../node_modules/axios/lib/helpers/bind.js","../node_modules/axios/lib/utils.js","../node_modules/axios/lib/helpers/buildURL.js","../node_modules/axios/lib/core/InterceptorManager.js","../node_modules/axios/lib/helpers/normalizeHeaderName.js","../node_modules/axios/lib/core/enhanceError.js","../node_modules/axios/lib/core/createError.js","../node_modules/axios/lib/core/settle.js","../node_modules/axios/lib/helpers/cookies.js","../node_modules/axios/lib/helpers/isAbsoluteURL.js","../node_modules/axios/lib/helpers/combineURLs.js","../node_modules/axios/lib/core/buildFullPath.js","../node_modules/axios/lib/helpers/parseHeaders.js","../node_modules/axios/lib/helpers/isURLSameOrigin.js","../node_modules/axios/lib/adapters/xhr.js","../node_modules/axios/lib/defaults.js","../node_modules/axios/lib/core/transformData.js","../node_modules/axios/lib/cancel/isCancel.js","../node_modules/axios/lib/core/dispatchRequest.js","../node_modules/axios/lib/core/mergeConfig.js","../node_modules/axios/lib/helpers/validator.js","../node_modules/axios/lib/core/Axios.js","../node_modules/axios/lib/cancel/Cancel.js","../node_modules/axios/lib/cancel/CancelToken.js","../node_modules/axios/lib/helpers/spread.js","../node_modules/axios/lib/helpers/isAxiosError.js","../node_modules/axios/lib/axios.js","../node_modules/axios/index.js","../src/util/http-util.ts","../src/services/codes.service.ts","../src/composables/useCodes.ts","../src/composables/common/useStatusList.ts","../src/services/routingSlip.services.ts","../src/composables/useRoutingSlip.ts","../src/composables/Dashboard/useSearch.ts","../node_modules/vue-class-component/dist/vue-class-component.esm.js","../node_modules/vue-property-decorator/lib/decorators/Emit.js","../node_modules/vue-property-decorator/lib/helpers/metadata.js","../node_modules/vue-property-decorator/lib/decorators/Prop.js","../src/composables/common/useDateRange.ts","../src/composables/common/useSearchColumnFilterComponent.ts","../src/components/common/DateRangeFilter.vue","../src/components/common/DateRangeFilter.vue?vue&type=template&lang.js","../src/components/common/SearchColumnFilterComponent.vue","../src/components/common/SearchColumnFilterComponent.vue?vue&type=template&lang.js","../src/components/common/StatusList.vue","../src/components/common/StatusList.vue?vue&type=template&lang.js","../src/components/common/TableObserver.vue?vue&type=template&lang.js","../src/components/common/TableObserver.vue","../src/composables/Dashboard/useDashboard.ts","../src/directives/can.ts","../src/components/Dashboard/Search.vue","../src/components/Dashboard/Search.vue?vue&type=template&lang.js","../node_modules/vue-i18n/dist/vue-i18n.esm.js","../node_modules/vue-i18n-composable/dist/index.mjs","../src/plugins/i18n.ts","../src/lib-setup.js"],"sourcesContent":["// This needs to be done, otherwise these App.vue gets hoisted above the statements below:\r\nimport VueCompositionAPI from '@vue/composition-api'\r\nimport Vue from 'vue'\r\nVue.use(VueCompositionAPI)\r\n","export enum SessionStorageKeys {\r\n KeyCloakToken = 'KEYCLOAK_TOKEN',\r\n ApiConfigKey = 'AUTH_API_CONFIG',\r\n LaunchDarklyFlags = 'LD_FLAGS',\r\n ExtraProvincialUser = 'EXTRAPROVINCIAL_USER',\r\n SessionSynced = 'SESSION_SYNCED',\r\n AuthApiUrl = 'AUTH_API_URL',\r\n AuthWebUrl = 'AUTH_WEB_URL',\r\n PayApiUrl = 'PAY_API_URL',\r\n StatusApiUrl = 'STATUS_API_URL',\r\n FasWebUrl = 'FAS_WEB_URL',\r\n SiteminderLogoutUrl = 'SITEMINDER_LOGOUT_URL'\r\n}\r\n\r\nexport enum DateFilterCodes {\r\n TODAY = 'TODAY',\r\n YESTERDAY = 'YESTERDAY',\r\n LASTWEEK = 'LASTWEEK',\r\n LASTMONTH = 'LASTMONTH',\r\n CUSTOMRANGE = 'CUSTOMRANGE',\r\n}\r\n\r\nexport enum PaymentMethods {\r\n CASH = 'CASH',\r\n CHEQUE = 'CHEQUE',\r\n}\r\n\r\nexport enum SlipStatus {\r\n ACTIVE = 'ACTIVE',\r\n COMPLETE = 'COMPLETE',\r\n BOUNCED = 'BOUNCED',\r\n NSF = 'NSF',\r\n REFUND = 'REFUND',\r\n LAST = 'LAST',\r\n HOLD = 'HOLD',\r\n LINKED = 'LINKED',\r\n REFUNDREQUEST = 'REFUND_REQUESTED',\r\n REFUNDAUTHORIZED = 'REFUND_AUTHORIZED',\r\n REFUNDPROCESSED = 'REFUND_PROCESSED',\r\n REFUNDUPLOADED = 'REFUND_UPLOADED',\r\n REFUNDREJECTED = 'REFUND_REJECTED',\r\n CANCEL_REFUND_REQUEST = 'CANCEL_REFUND_REQUEST',\r\n CANCELWRITEOFFREQUEST='CANCEL_WRITE_OFF_REQUEST',\r\n WRITEOFFAUTHORIZED='WRITE_OFF_AUTHORIZED',\r\n WRITEOFFREQUESTED='WRITE_OFF_REQUESTED',\r\n WRITEOFFCOMPLETED='WRITE_OFF_COMPLETED',\r\n VOID='VOID',\r\n CORRECTION='CORRECTION'\r\n}\r\n\r\nexport enum SlipStatusLabel {\r\n ACTIVE = 'Place routing slip to active',\r\n NSF = 'Place routing slip to NSF',\r\n HOLD = 'Place routing slip on hold',\r\n LINKED = 'LINKED',\r\n REFUND_REQUESTED = 'Refund request',\r\n WRITE_OFF_REQUESTED = 'Write off request',\r\n CANCEL_REFUND_REQUEST = 'Cancel refund request',\r\n REFUND_AUTHORIZED='Review refund request',\r\n WRITE_OFF_AUTHORIZED='Authorize Write off request',\r\n CANCEL_WRITE_OFF_REQUEST='Cancel Write off request',\r\n VOID='Void Routing Slip',\r\n // CORRECTION='Correct Routing Slip' - Future\r\n}\r\n\r\nexport enum Role {\r\n FAS_USER = 'fas_user',\r\n FAS_EDIT = 'fas_edit',\r\n FAS_REPORTS = 'fas_reports',\r\n FAS_SEARCH = 'fas_search',\r\n FAS_VIEW = 'fas_view',\r\n FAS_CREATE = 'fas_create',\r\n FAS_LNK = 'fas_link',\r\n FAS_TRANSACTION = 'fas_transaction',\r\n FAS_REFUND_APPROVER = 'fas_refund_approver',\r\n FAS_REFUND = 'fas_refund',\r\n FAS_VOID = 'fas_void',\r\n FAS_CORRECTION = 'fas_correction'\r\n}\r\n\r\nexport enum InvoiceStatus {\r\n COMPLETED = 'COMPLETED',\r\n REFUNDED = 'REFUNDED',\r\n DELETE_ACCEPTED = 'DELETE_ACCEPTED',\r\n REFUNDREQUEST = 'REFUND_REQUESTED',\r\n}\r\n\r\nexport enum ApiErrors {\r\n FAS_INVALID_ROUTING_SLIP_DIGITS = 'FAS_INVALID_ROUTING_SLIP_DIGITS'\r\n}\r\n\r\nexport enum CreateRoutingSlipStatus {\r\n VALID = 'VALID',\r\n EXISTS = 'EXISTS',\r\n INVALID_DIGITS = 'INVALID_DIGITS',\r\n}\r\n\r\nexport enum PatchActions {\r\n UPDATE_STATUS = 'updateStatus'\r\n}\r\n\r\nexport const AXIOS_ERROR_ALERT_TIME_OUT = 5000\r\n\r\nexport const headerSearchTitle =\r\n[\r\n {\r\n text: 'Routing Slip Number',\r\n align: 'start',\r\n value: 'routingSlipNumber',\r\n display: true,\r\n className: 'routing-slip'\r\n },\r\n {\r\n text: 'Receipt Number',\r\n align: 'start',\r\n sortable: false,\r\n value: 'receiptNumber',\r\n display: true,\r\n className: 'receiptNumber'\r\n },\r\n {\r\n text: 'Entity Number',\r\n align: 'start',\r\n value: 'accountName',\r\n sortable: false,\r\n display: false,\r\n className: 'accountName'\r\n },\r\n {\r\n text: 'Created By',\r\n align: 'start',\r\n value: 'createdName',\r\n sortable: false,\r\n display: false,\r\n className: 'createdName'\r\n },\r\n {\r\n text: 'Date',\r\n align: 'start',\r\n sortable: false,\r\n value: 'date',\r\n display: true,\r\n className: 'date'\r\n },\r\n {\r\n text: 'Status',\r\n align: 'start',\r\n sortable: false,\r\n value: 'status',\r\n display: true,\r\n className: 'status'\r\n },\r\n {\r\n text: 'Refund Status',\r\n align: 'start',\r\n sortable: false,\r\n value: 'refundStatus',\r\n display: true,\r\n className: 'refundStatus'\r\n },\r\n {\r\n text: 'Reference Number',\r\n align: 'start',\r\n value: 'businessIdentifier',\r\n sortable: false,\r\n display: true,\r\n className: 'businessIdentifier'\r\n },\r\n {\r\n text: 'Cheque Number',\r\n align: 'start',\r\n value: 'chequeReceiptNumber',\r\n sortable: false,\r\n display: false,\r\n className: 'cheque-receipt-number'\r\n },\r\n {\r\n text: 'Balance',\r\n align: 'right',\r\n value: 'remainingAmount',\r\n sortable: false,\r\n display: true,\r\n className: 'remainingAmount'\r\n },\r\n {\r\n text: 'Actions',\r\n align: 'start',\r\n value: '',\r\n sortable: false,\r\n display: true,\r\n hideInSearchColumnFilter: true,\r\n className: 'action'\r\n }\r\n]\r\n\r\nexport const RoutingSlipRefundStatus = [\r\n {\r\n code: 'PROCESSING',\r\n text: 'PROCESSING',\r\n display: false\r\n },\r\n {\r\n code: 'PROCESSED',\r\n text: 'PROCESSED',\r\n display: true\r\n },\r\n {\r\n code: 'CHEQUE_UNDELIVERABLE',\r\n text: 'CHEQUE UNDELIVERABLE',\r\n display: true\r\n }\r\n]\r\n\r\nexport const RoutingSlipRefundCodes = RoutingSlipRefundStatus.reduce((acc, status) => {\r\n acc[status.code] = status.code\r\n return acc\r\n}, {} as { [key: string]: string })\r\n","/**\n * [js-sha256]{@link https://github.com/emn178/js-sha256}\n *\n * @version 0.9.0\n * @author Chen, Yi-Cyuan [emn178@gmail.com]\n * @copyright Chen, Yi-Cyuan 2014-2017\n * @license MIT\n */\n/*jslint bitwise: true */\n(function () {\n 'use strict';\n\n var ERROR = 'input is invalid type';\n var WINDOW = typeof window === 'object';\n var root = WINDOW ? window : {};\n if (root.JS_SHA256_NO_WINDOW) {\n WINDOW = false;\n }\n var WEB_WORKER = !WINDOW && typeof self === 'object';\n var NODE_JS = !root.JS_SHA256_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;\n if (NODE_JS) {\n root = global;\n } else if (WEB_WORKER) {\n root = self;\n }\n var COMMON_JS = !root.JS_SHA256_NO_COMMON_JS && typeof module === 'object' && module.exports;\n var AMD = typeof define === 'function' && define.amd;\n var ARRAY_BUFFER = !root.JS_SHA256_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';\n var HEX_CHARS = '0123456789abcdef'.split('');\n var EXTRA = [-2147483648, 8388608, 32768, 128];\n var SHIFT = [24, 16, 8, 0];\n var K = [\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n ];\n var OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];\n\n var blocks = [];\n\n if (root.JS_SHA256_NO_NODE_JS || !Array.isArray) {\n Array.isArray = function (obj) {\n return Object.prototype.toString.call(obj) === '[object Array]';\n };\n }\n\n if (ARRAY_BUFFER && (root.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {\n ArrayBuffer.isView = function (obj) {\n return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;\n };\n }\n\n var createOutputMethod = function (outputType, is224) {\n return function (message) {\n return new Sha256(is224, true).update(message)[outputType]();\n };\n };\n\n var createMethod = function (is224) {\n var method = createOutputMethod('hex', is224);\n if (NODE_JS) {\n method = nodeWrap(method, is224);\n }\n method.create = function () {\n return new Sha256(is224);\n };\n method.update = function (message) {\n return method.create().update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createOutputMethod(type, is224);\n }\n return method;\n };\n\n var nodeWrap = function (method, is224) {\n var crypto = eval(\"require('crypto')\");\n var Buffer = eval(\"require('buffer').Buffer\");\n var algorithm = is224 ? 'sha224' : 'sha256';\n var nodeMethod = function (message) {\n if (typeof message === 'string') {\n return crypto.createHash(algorithm).update(message, 'utf8').digest('hex');\n } else {\n if (message === null || message === undefined) {\n throw new Error(ERROR);\n } else if (message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n }\n }\n if (Array.isArray(message) || ArrayBuffer.isView(message) ||\n message.constructor === Buffer) {\n return crypto.createHash(algorithm).update(new Buffer(message)).digest('hex');\n } else {\n return method(message);\n }\n };\n return nodeMethod;\n };\n\n var createHmacOutputMethod = function (outputType, is224) {\n return function (key, message) {\n return new HmacSha256(key, is224, true).update(message)[outputType]();\n };\n };\n\n var createHmacMethod = function (is224) {\n var method = createHmacOutputMethod('hex', is224);\n method.create = function (key) {\n return new HmacSha256(key, is224);\n };\n method.update = function (key, message) {\n return method.create(key).update(message);\n };\n for (var i = 0; i < OUTPUT_TYPES.length; ++i) {\n var type = OUTPUT_TYPES[i];\n method[type] = createHmacOutputMethod(type, is224);\n }\n return method;\n };\n\n function Sha256(is224, sharedMemory) {\n if (sharedMemory) {\n blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n this.blocks = blocks;\n } else {\n this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n }\n\n if (is224) {\n this.h0 = 0xc1059ed8;\n this.h1 = 0x367cd507;\n this.h2 = 0x3070dd17;\n this.h3 = 0xf70e5939;\n this.h4 = 0xffc00b31;\n this.h5 = 0x68581511;\n this.h6 = 0x64f98fa7;\n this.h7 = 0xbefa4fa4;\n } else { // 256\n this.h0 = 0x6a09e667;\n this.h1 = 0xbb67ae85;\n this.h2 = 0x3c6ef372;\n this.h3 = 0xa54ff53a;\n this.h4 = 0x510e527f;\n this.h5 = 0x9b05688c;\n this.h6 = 0x1f83d9ab;\n this.h7 = 0x5be0cd19;\n }\n\n this.block = this.start = this.bytes = this.hBytes = 0;\n this.finalized = this.hashed = false;\n this.first = true;\n this.is224 = is224;\n }\n\n Sha256.prototype.update = function (message) {\n if (this.finalized) {\n return;\n }\n var notString, type = typeof message;\n if (type !== 'string') {\n if (type === 'object') {\n if (message === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {\n message = new Uint8Array(message);\n } else if (!Array.isArray(message)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n notString = true;\n }\n var code, index = 0, i, length = message.length, blocks = this.blocks;\n\n while (index < length) {\n if (this.hashed) {\n this.hashed = false;\n blocks[0] = this.block;\n blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n }\n\n if (notString) {\n for (i = this.start; index < length && i < 64; ++index) {\n blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];\n }\n } else {\n for (i = this.start; index < length && i < 64; ++index) {\n code = message.charCodeAt(index);\n if (code < 0x80) {\n blocks[i >> 2] |= code << SHIFT[i++ & 3];\n } else if (code < 0x800) {\n blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n } else if (code < 0xd800 || code >= 0xe000) {\n blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n } else {\n code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n }\n }\n }\n\n this.lastByteIndex = i;\n this.bytes += i - this.start;\n if (i >= 64) {\n this.block = blocks[16];\n this.start = i - 64;\n this.hash();\n this.hashed = true;\n } else {\n this.start = i;\n }\n }\n if (this.bytes > 4294967295) {\n this.hBytes += this.bytes / 4294967296 << 0;\n this.bytes = this.bytes % 4294967296;\n }\n return this;\n };\n\n Sha256.prototype.finalize = function () {\n if (this.finalized) {\n return;\n }\n this.finalized = true;\n var blocks = this.blocks, i = this.lastByteIndex;\n blocks[16] = this.block;\n blocks[i >> 2] |= EXTRA[i & 3];\n this.block = blocks[16];\n if (i >= 56) {\n if (!this.hashed) {\n this.hash();\n }\n blocks[0] = this.block;\n blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n }\n blocks[14] = this.hBytes << 3 | this.bytes >>> 29;\n blocks[15] = this.bytes << 3;\n this.hash();\n };\n\n Sha256.prototype.hash = function () {\n var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4, f = this.h5, g = this.h6,\n h = this.h7, blocks = this.blocks, j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\n\n for (j = 16; j < 64; ++j) {\n // rightrotate\n t1 = blocks[j - 15];\n s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);\n t1 = blocks[j - 2];\n s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);\n blocks[j] = blocks[j - 16] + s0 + blocks[j - 7] + s1 << 0;\n }\n\n bc = b & c;\n for (j = 0; j < 64; j += 4) {\n if (this.first) {\n if (this.is224) {\n ab = 300032;\n t1 = blocks[0] - 1413257819;\n h = t1 - 150054599 << 0;\n d = t1 + 24177077 << 0;\n } else {\n ab = 704751109;\n t1 = blocks[0] - 210244248;\n h = t1 - 1521486534 << 0;\n d = t1 + 143694565 << 0;\n }\n this.first = false;\n } else {\n s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\n s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\n ab = a & b;\n maj = ab ^ (a & c) ^ bc;\n ch = (e & f) ^ (~e & g);\n t1 = h + s1 + ch + K[j] + blocks[j];\n t2 = s0 + maj;\n h = d + t1 << 0;\n d = t1 + t2 << 0;\n }\n s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));\n s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));\n da = d & a;\n maj = da ^ (d & b) ^ ab;\n ch = (h & e) ^ (~h & f);\n t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];\n t2 = s0 + maj;\n g = c + t1 << 0;\n c = t1 + t2 << 0;\n s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));\n s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));\n cd = c & d;\n maj = cd ^ (c & a) ^ da;\n ch = (g & h) ^ (~g & e);\n t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];\n t2 = s0 + maj;\n f = b + t1 << 0;\n b = t1 + t2 << 0;\n s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));\n s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));\n bc = b & c;\n maj = bc ^ (b & d) ^ cd;\n ch = (f & g) ^ (~f & h);\n t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];\n t2 = s0 + maj;\n e = a + t1 << 0;\n a = t1 + t2 << 0;\n }\n\n this.h0 = this.h0 + a << 0;\n this.h1 = this.h1 + b << 0;\n this.h2 = this.h2 + c << 0;\n this.h3 = this.h3 + d << 0;\n this.h4 = this.h4 + e << 0;\n this.h5 = this.h5 + f << 0;\n this.h6 = this.h6 + g << 0;\n this.h7 = this.h7 + h << 0;\n };\n\n Sha256.prototype.hex = function () {\n this.finalize();\n\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,\n h6 = this.h6, h7 = this.h7;\n\n var hex = HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +\n HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +\n HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +\n HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +\n HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +\n HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +\n HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +\n HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +\n HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +\n HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +\n HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +\n HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +\n HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +\n HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +\n HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +\n HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +\n HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +\n HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +\n HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +\n HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F] +\n HEX_CHARS[(h5 >> 28) & 0x0F] + HEX_CHARS[(h5 >> 24) & 0x0F] +\n HEX_CHARS[(h5 >> 20) & 0x0F] + HEX_CHARS[(h5 >> 16) & 0x0F] +\n HEX_CHARS[(h5 >> 12) & 0x0F] + HEX_CHARS[(h5 >> 8) & 0x0F] +\n HEX_CHARS[(h5 >> 4) & 0x0F] + HEX_CHARS[h5 & 0x0F] +\n HEX_CHARS[(h6 >> 28) & 0x0F] + HEX_CHARS[(h6 >> 24) & 0x0F] +\n HEX_CHARS[(h6 >> 20) & 0x0F] + HEX_CHARS[(h6 >> 16) & 0x0F] +\n HEX_CHARS[(h6 >> 12) & 0x0F] + HEX_CHARS[(h6 >> 8) & 0x0F] +\n HEX_CHARS[(h6 >> 4) & 0x0F] + HEX_CHARS[h6 & 0x0F];\n if (!this.is224) {\n hex += HEX_CHARS[(h7 >> 28) & 0x0F] + HEX_CHARS[(h7 >> 24) & 0x0F] +\n HEX_CHARS[(h7 >> 20) & 0x0F] + HEX_CHARS[(h7 >> 16) & 0x0F] +\n HEX_CHARS[(h7 >> 12) & 0x0F] + HEX_CHARS[(h7 >> 8) & 0x0F] +\n HEX_CHARS[(h7 >> 4) & 0x0F] + HEX_CHARS[h7 & 0x0F];\n }\n return hex;\n };\n\n Sha256.prototype.toString = Sha256.prototype.hex;\n\n Sha256.prototype.digest = function () {\n this.finalize();\n\n var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4, h5 = this.h5,\n h6 = this.h6, h7 = this.h7;\n\n var arr = [\n (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,\n (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,\n (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,\n (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,\n (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF,\n (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, h5 & 0xFF,\n (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, h6 & 0xFF\n ];\n if (!this.is224) {\n arr.push((h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, h7 & 0xFF);\n }\n return arr;\n };\n\n Sha256.prototype.array = Sha256.prototype.digest;\n\n Sha256.prototype.arrayBuffer = function () {\n this.finalize();\n\n var buffer = new ArrayBuffer(this.is224 ? 28 : 32);\n var dataView = new DataView(buffer);\n dataView.setUint32(0, this.h0);\n dataView.setUint32(4, this.h1);\n dataView.setUint32(8, this.h2);\n dataView.setUint32(12, this.h3);\n dataView.setUint32(16, this.h4);\n dataView.setUint32(20, this.h5);\n dataView.setUint32(24, this.h6);\n if (!this.is224) {\n dataView.setUint32(28, this.h7);\n }\n return buffer;\n };\n\n function HmacSha256(key, is224, sharedMemory) {\n var i, type = typeof key;\n if (type === 'string') {\n var bytes = [], length = key.length, index = 0, code;\n for (i = 0; i < length; ++i) {\n code = key.charCodeAt(i);\n if (code < 0x80) {\n bytes[index++] = code;\n } else if (code < 0x800) {\n bytes[index++] = (0xc0 | (code >> 6));\n bytes[index++] = (0x80 | (code & 0x3f));\n } else if (code < 0xd800 || code >= 0xe000) {\n bytes[index++] = (0xe0 | (code >> 12));\n bytes[index++] = (0x80 | ((code >> 6) & 0x3f));\n bytes[index++] = (0x80 | (code & 0x3f));\n } else {\n code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));\n bytes[index++] = (0xf0 | (code >> 18));\n bytes[index++] = (0x80 | ((code >> 12) & 0x3f));\n bytes[index++] = (0x80 | ((code >> 6) & 0x3f));\n bytes[index++] = (0x80 | (code & 0x3f));\n }\n }\n key = bytes;\n } else {\n if (type === 'object') {\n if (key === null) {\n throw new Error(ERROR);\n } else if (ARRAY_BUFFER && key.constructor === ArrayBuffer) {\n key = new Uint8Array(key);\n } else if (!Array.isArray(key)) {\n if (!ARRAY_BUFFER || !ArrayBuffer.isView(key)) {\n throw new Error(ERROR);\n }\n }\n } else {\n throw new Error(ERROR);\n }\n }\n\n if (key.length > 64) {\n key = (new Sha256(is224, true)).update(key).array();\n }\n\n var oKeyPad = [], iKeyPad = [];\n for (i = 0; i < 64; ++i) {\n var b = key[i] || 0;\n oKeyPad[i] = 0x5c ^ b;\n iKeyPad[i] = 0x36 ^ b;\n }\n\n Sha256.call(this, is224, sharedMemory);\n\n this.update(iKeyPad);\n this.oKeyPad = oKeyPad;\n this.inner = true;\n this.sharedMemory = sharedMemory;\n }\n HmacSha256.prototype = new Sha256();\n\n HmacSha256.prototype.finalize = function () {\n Sha256.prototype.finalize.call(this);\n if (this.inner) {\n this.inner = false;\n var innerHash = this.array();\n Sha256.call(this, this.is224, this.sharedMemory);\n this.update(this.oKeyPad);\n this.update(innerHash);\n Sha256.prototype.finalize.call(this);\n }\n };\n\n var exports = createMethod();\n exports.sha256 = exports;\n exports.sha224 = createMethod(true);\n exports.sha256.hmac = createHmacMethod();\n exports.sha224.hmac = createHmacMethod(true);\n\n if (COMMON_JS) {\n module.exports = exports;\n } else {\n root.sha256 = exports.sha256;\n root.sha224 = exports.sha224;\n if (AMD) {\n define(function () {\n return exports;\n });\n }\n }\n})();\n","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n var i\n for (i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(\n uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)\n ))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n","/*\n * Copyright 2016 Red Hat, Inc. and/or its affiliates\n * and other contributors as indicated by the @author tags.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n(function(root, factory) {\n if ( typeof exports === 'object' ) {\n if ( typeof module === 'object' ) {\n module.exports = factory( require(\"js-sha256\"), require(\"base64-js\") ); \n } else {\n exports[\"keycloak\"] = factory( require(\"js-sha256\"), require(\"base64-js\") ); \n }\n } else {\n /**\n * [js-sha256]{@link https://github.com/emn178/js-sha256}\n *\n * @version 0.9.0\n * @author Chen, Yi-Cyuan [emn178@gmail.com]\n * @copyright Chen, Yi-Cyuan 2014-2017\n * @license MIT\n */\n !function () { \"use strict\"; function t(t, i) { i ? (d[0] = d[16] = d[1] = d[2] = d[3] = d[4] = d[5] = d[6] = d[7] = d[8] = d[9] = d[10] = d[11] = d[12] = d[13] = d[14] = d[15] = 0, this.blocks = d) : this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], t ? (this.h0 = 3238371032, this.h1 = 914150663, this.h2 = 812702999, this.h3 = 4144912697, this.h4 = 4290775857, this.h5 = 1750603025, this.h6 = 1694076839, this.h7 = 3204075428) : (this.h0 = 1779033703, this.h1 = 3144134277, this.h2 = 1013904242, this.h3 = 2773480762, this.h4 = 1359893119, this.h5 = 2600822924, this.h6 = 528734635, this.h7 = 1541459225), this.block = this.start = this.bytes = this.hBytes = 0, this.finalized = this.hashed = !1, this.first = !0, this.is224 = t } function i(i, r, s) { var e, n = typeof i; if (\"string\" === n) { var o, a = [], u = i.length, c = 0; for (e = 0; e < u; ++e)(o = i.charCodeAt(e)) < 128 ? a[c++] = o : o < 2048 ? (a[c++] = 192 | o >> 6, a[c++] = 128 | 63 & o) : o < 55296 || o >= 57344 ? (a[c++] = 224 | o >> 12, a[c++] = 128 | o >> 6 & 63, a[c++] = 128 | 63 & o) : (o = 65536 + ((1023 & o) << 10 | 1023 & i.charCodeAt(++e)), a[c++] = 240 | o >> 18, a[c++] = 128 | o >> 12 & 63, a[c++] = 128 | o >> 6 & 63, a[c++] = 128 | 63 & o); i = a } else { if (\"object\" !== n) throw new Error(h); if (null === i) throw new Error(h); if (f && i.constructor === ArrayBuffer) i = new Uint8Array(i); else if (!(Array.isArray(i) || f && ArrayBuffer.isView(i))) throw new Error(h) } i.length > 64 && (i = new t(r, !0).update(i).array()); var y = [], p = []; for (e = 0; e < 64; ++e) { var l = i[e] || 0; y[e] = 92 ^ l, p[e] = 54 ^ l } t.call(this, r, s), this.update(p), this.oKeyPad = y, this.inner = !0, this.sharedMemory = s } var h = \"input is invalid type\", r = \"object\" == typeof window, s = r ? window : {}; s.JS_SHA256_NO_WINDOW && (r = !1); var e = !r && \"object\" == typeof self, n = !s.JS_SHA256_NO_NODE_JS && \"object\" == typeof process && process.versions && process.versions.node; n ? s = global : e && (s = self); var o = !s.JS_SHA256_NO_COMMON_JS && \"object\" == typeof module && module.exports, a = \"function\" == typeof define && define.amd, f = !s.JS_SHA256_NO_ARRAY_BUFFER && \"undefined\" != typeof ArrayBuffer, u = \"0123456789abcdef\".split(\"\"), c = [-2147483648, 8388608, 32768, 128], y = [24, 16, 8, 0], p = [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298], l = [\"hex\", \"array\", \"digest\", \"arrayBuffer\"], d = []; !s.JS_SHA256_NO_NODE_JS && Array.isArray || (Array.isArray = function (t) { return \"[object Array]\" === Object.prototype.toString.call(t) }), !f || !s.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW && ArrayBuffer.isView || (ArrayBuffer.isView = function (t) { return \"object\" == typeof t && t.buffer && t.buffer.constructor === ArrayBuffer }); var A = function (i, h) { return function (r) { return new t(h, !0).update(r)[i]() } }, w = function (i) { var h = A(\"hex\", i); n && (h = b(h, i)), h.create = function () { return new t(i) }, h.update = function (t) { return h.create().update(t) }; for (var r = 0; r < l.length; ++r) { var s = l[r]; h[s] = A(s, i) } return h }, b = function (t, i) { var r = eval(\"require('crypto')\"), s = eval(\"require('buffer').Buffer\"), e = i ? \"sha224\" : \"sha256\", n = function (i) { if (\"string\" == typeof i) return r.createHash(e).update(i, \"utf8\").digest(\"hex\"); if (null === i || void 0 === i) throw new Error(h); return i.constructor === ArrayBuffer && (i = new Uint8Array(i)), Array.isArray(i) || ArrayBuffer.isView(i) || i.constructor === s ? r.createHash(e).update(new s(i)).digest(\"hex\") : t(i) }; return n }, v = function (t, h) { return function (r, s) { return new i(r, h, !0).update(s)[t]() } }, _ = function (t) { var h = v(\"hex\", t); h.create = function (h) { return new i(h, t) }, h.update = function (t, i) { return h.create(t).update(i) }; for (var r = 0; r < l.length; ++r) { var s = l[r]; h[s] = v(s, t) } return h }; t.prototype.update = function (t) { if (!this.finalized) { var i, r = typeof t; if (\"string\" !== r) { if (\"object\" !== r) throw new Error(h); if (null === t) throw new Error(h); if (f && t.constructor === ArrayBuffer) t = new Uint8Array(t); else if (!(Array.isArray(t) || f && ArrayBuffer.isView(t))) throw new Error(h); i = !0 } for (var s, e, n = 0, o = t.length, a = this.blocks; n < o;) { if (this.hashed && (this.hashed = !1, a[0] = this.block, a[16] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = a[9] = a[10] = a[11] = a[12] = a[13] = a[14] = a[15] = 0), i) for (e = this.start; n < o && e < 64; ++n)a[e >> 2] |= t[n] << y[3 & e++]; else for (e = this.start; n < o && e < 64; ++n)(s = t.charCodeAt(n)) < 128 ? a[e >> 2] |= s << y[3 & e++] : s < 2048 ? (a[e >> 2] |= (192 | s >> 6) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]) : s < 55296 || s >= 57344 ? (a[e >> 2] |= (224 | s >> 12) << y[3 & e++], a[e >> 2] |= (128 | s >> 6 & 63) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++n)), a[e >> 2] |= (240 | s >> 18) << y[3 & e++], a[e >> 2] |= (128 | s >> 12 & 63) << y[3 & e++], a[e >> 2] |= (128 | s >> 6 & 63) << y[3 & e++], a[e >> 2] |= (128 | 63 & s) << y[3 & e++]); this.lastByteIndex = e, this.bytes += e - this.start, e >= 64 ? (this.block = a[16], this.start = e - 64, this.hash(), this.hashed = !0) : this.start = e } return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0, this.bytes = this.bytes % 4294967296), this } }, t.prototype.finalize = function () { if (!this.finalized) { this.finalized = !0; var t = this.blocks, i = this.lastByteIndex; t[16] = this.block, t[i >> 2] |= c[3 & i], this.block = t[16], i >= 56 && (this.hashed || this.hash(), t[0] = this.block, t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0), t[14] = this.hBytes << 3 | this.bytes >>> 29, t[15] = this.bytes << 3, this.hash() } }, t.prototype.hash = function () { var t, i, h, r, s, e, n, o, a, f = this.h0, u = this.h1, c = this.h2, y = this.h3, l = this.h4, d = this.h5, A = this.h6, w = this.h7, b = this.blocks; for (t = 16; t < 64; ++t)i = ((s = b[t - 15]) >>> 7 | s << 25) ^ (s >>> 18 | s << 14) ^ s >>> 3, h = ((s = b[t - 2]) >>> 17 | s << 15) ^ (s >>> 19 | s << 13) ^ s >>> 10, b[t] = b[t - 16] + i + b[t - 7] + h << 0; for (a = u & c, t = 0; t < 64; t += 4)this.first ? (this.is224 ? (e = 300032, w = (s = b[0] - 1413257819) - 150054599 << 0, y = s + 24177077 << 0) : (e = 704751109, w = (s = b[0] - 210244248) - 1521486534 << 0, y = s + 143694565 << 0), this.first = !1) : (i = (f >>> 2 | f << 30) ^ (f >>> 13 | f << 19) ^ (f >>> 22 | f << 10), r = (e = f & u) ^ f & c ^ a, w = y + (s = w + (h = (l >>> 6 | l << 26) ^ (l >>> 11 | l << 21) ^ (l >>> 25 | l << 7)) + (l & d ^ ~l & A) + p[t] + b[t]) << 0, y = s + (i + r) << 0), i = (y >>> 2 | y << 30) ^ (y >>> 13 | y << 19) ^ (y >>> 22 | y << 10), r = (n = y & f) ^ y & u ^ e, A = c + (s = A + (h = (w >>> 6 | w << 26) ^ (w >>> 11 | w << 21) ^ (w >>> 25 | w << 7)) + (w & l ^ ~w & d) + p[t + 1] + b[t + 1]) << 0, i = ((c = s + (i + r) << 0) >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10), r = (o = c & y) ^ c & f ^ n, d = u + (s = d + (h = (A >>> 6 | A << 26) ^ (A >>> 11 | A << 21) ^ (A >>> 25 | A << 7)) + (A & w ^ ~A & l) + p[t + 2] + b[t + 2]) << 0, i = ((u = s + (i + r) << 0) >>> 2 | u << 30) ^ (u >>> 13 | u << 19) ^ (u >>> 22 | u << 10), r = (a = u & c) ^ u & y ^ o, l = f + (s = l + (h = (d >>> 6 | d << 26) ^ (d >>> 11 | d << 21) ^ (d >>> 25 | d << 7)) + (d & A ^ ~d & w) + p[t + 3] + b[t + 3]) << 0, f = s + (i + r) << 0; this.h0 = this.h0 + f << 0, this.h1 = this.h1 + u << 0, this.h2 = this.h2 + c << 0, this.h3 = this.h3 + y << 0, this.h4 = this.h4 + l << 0, this.h5 = this.h5 + d << 0, this.h6 = this.h6 + A << 0, this.h7 = this.h7 + w << 0 }, t.prototype.hex = function () { this.finalize(); var t = this.h0, i = this.h1, h = this.h2, r = this.h3, s = this.h4, e = this.h5, n = this.h6, o = this.h7, a = u[t >> 28 & 15] + u[t >> 24 & 15] + u[t >> 20 & 15] + u[t >> 16 & 15] + u[t >> 12 & 15] + u[t >> 8 & 15] + u[t >> 4 & 15] + u[15 & t] + u[i >> 28 & 15] + u[i >> 24 & 15] + u[i >> 20 & 15] + u[i >> 16 & 15] + u[i >> 12 & 15] + u[i >> 8 & 15] + u[i >> 4 & 15] + u[15 & i] + u[h >> 28 & 15] + u[h >> 24 & 15] + u[h >> 20 & 15] + u[h >> 16 & 15] + u[h >> 12 & 15] + u[h >> 8 & 15] + u[h >> 4 & 15] + u[15 & h] + u[r >> 28 & 15] + u[r >> 24 & 15] + u[r >> 20 & 15] + u[r >> 16 & 15] + u[r >> 12 & 15] + u[r >> 8 & 15] + u[r >> 4 & 15] + u[15 & r] + u[s >> 28 & 15] + u[s >> 24 & 15] + u[s >> 20 & 15] + u[s >> 16 & 15] + u[s >> 12 & 15] + u[s >> 8 & 15] + u[s >> 4 & 15] + u[15 & s] + u[e >> 28 & 15] + u[e >> 24 & 15] + u[e >> 20 & 15] + u[e >> 16 & 15] + u[e >> 12 & 15] + u[e >> 8 & 15] + u[e >> 4 & 15] + u[15 & e] + u[n >> 28 & 15] + u[n >> 24 & 15] + u[n >> 20 & 15] + u[n >> 16 & 15] + u[n >> 12 & 15] + u[n >> 8 & 15] + u[n >> 4 & 15] + u[15 & n]; return this.is224 || (a += u[o >> 28 & 15] + u[o >> 24 & 15] + u[o >> 20 & 15] + u[o >> 16 & 15] + u[o >> 12 & 15] + u[o >> 8 & 15] + u[o >> 4 & 15] + u[15 & o]), a }, t.prototype.toString = t.prototype.hex, t.prototype.digest = function () { this.finalize(); var t = this.h0, i = this.h1, h = this.h2, r = this.h3, s = this.h4, e = this.h5, n = this.h6, o = this.h7, a = [t >> 24 & 255, t >> 16 & 255, t >> 8 & 255, 255 & t, i >> 24 & 255, i >> 16 & 255, i >> 8 & 255, 255 & i, h >> 24 & 255, h >> 16 & 255, h >> 8 & 255, 255 & h, r >> 24 & 255, r >> 16 & 255, r >> 8 & 255, 255 & r, s >> 24 & 255, s >> 16 & 255, s >> 8 & 255, 255 & s, e >> 24 & 255, e >> 16 & 255, e >> 8 & 255, 255 & e, n >> 24 & 255, n >> 16 & 255, n >> 8 & 255, 255 & n]; return this.is224 || a.push(o >> 24 & 255, o >> 16 & 255, o >> 8 & 255, 255 & o), a }, t.prototype.array = t.prototype.digest, t.prototype.arrayBuffer = function () { this.finalize(); var t = new ArrayBuffer(this.is224 ? 28 : 32), i = new DataView(t); return i.setUint32(0, this.h0), i.setUint32(4, this.h1), i.setUint32(8, this.h2), i.setUint32(12, this.h3), i.setUint32(16, this.h4), i.setUint32(20, this.h5), i.setUint32(24, this.h6), this.is224 || i.setUint32(28, this.h7), t }, i.prototype = new t, i.prototype.finalize = function () { if (t.prototype.finalize.call(this), this.inner) { this.inner = !1; var i = this.array(); t.call(this, this.is224, this.sharedMemory), this.update(this.oKeyPad), this.update(i), t.prototype.finalize.call(this) } }; var B = w(); B.sha256 = B, B.sha224 = w(!0), B.sha256.hmac = _(), B.sha224.hmac = _(!0), o ? module.exports = B : (s.sha256 = B.sha256, s.sha224 = B.sha224, a && define(function () { return B })) }();\n\n /**\n * [base64-js]{@link https://github.com/beatgammit/base64-js}\n *\n * @version v1.3.0 \n * @author Kirill, Fomichev\n * @copyright Kirill, Fomichev 2014\n * @license MIT\n */\n (function (r) { if (typeof exports === \"object\" && typeof module !== \"undefined\") { module.exports = r() } else if (typeof define === \"function\" && define.amd) { define([], r) } else { var e; if (typeof window !== \"undefined\") { e = window } else if (typeof global !== \"undefined\") { e = global } else if (typeof self !== \"undefined\") { e = self } else { e = this } e.base64js = r() } })(function () { var r, e, n; return function () { function r(e, n, t) { function o(f, i) { if (!n[f]) { if (!e[f]) { var u = \"function\" == typeof require && require; if (!i && u) return u(f, !0); if (a) return a(f, !0); var v = new Error(\"Cannot find module '\" + f + \"'\"); throw v.code = \"MODULE_NOT_FOUND\", v } var d = n[f] = { exports: {} }; e[f][0].call(d.exports, function (r) { var n = e[f][1][r]; return o(n || r) }, d, d.exports, r, e, n, t) } return n[f].exports } for (var a = \"function\" == typeof require && require, f = 0; f < t.length; f++)o(t[f]); return o } return r }()({ \"/\": [function (r, e, n) { \"use strict\"; n.byteLength = d; n.toByteArray = h; n.fromByteArray = p; var t = []; var o = []; var a = typeof Uint8Array !== \"undefined\" ? Uint8Array : Array; var f = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"; for (var i = 0, u = f.length; i < u; ++i) { t[i] = f[i]; o[f.charCodeAt(i)] = i } o[\"-\".charCodeAt(0)] = 62; o[\"_\".charCodeAt(0)] = 63; function v(r) { var e = r.length; if (e % 4 > 0) { throw new Error(\"Invalid string. Length must be a multiple of 4\") } var n = r.indexOf(\"=\"); if (n === -1) n = e; var t = n === e ? 0 : 4 - n % 4; return [n, t] } function d(r) { var e = v(r); var n = e[0]; var t = e[1]; return (n + t) * 3 / 4 - t } function c(r, e, n) { return (e + n) * 3 / 4 - n } function h(r) { var e; var n = v(r); var t = n[0]; var f = n[1]; var i = new a(c(r, t, f)); var u = 0; var d = f > 0 ? t - 4 : t; for (var h = 0; h < d; h += 4) { e = o[r.charCodeAt(h)] << 18 | o[r.charCodeAt(h + 1)] << 12 | o[r.charCodeAt(h + 2)] << 6 | o[r.charCodeAt(h + 3)]; i[u++] = e >> 16 & 255; i[u++] = e >> 8 & 255; i[u++] = e & 255 } if (f === 2) { e = o[r.charCodeAt(h)] << 2 | o[r.charCodeAt(h + 1)] >> 4; i[u++] = e & 255 } if (f === 1) { e = o[r.charCodeAt(h)] << 10 | o[r.charCodeAt(h + 1)] << 4 | o[r.charCodeAt(h + 2)] >> 2; i[u++] = e >> 8 & 255; i[u++] = e & 255 } return i } function s(r) { return t[r >> 18 & 63] + t[r >> 12 & 63] + t[r >> 6 & 63] + t[r & 63] } function l(r, e, n) { var t; var o = []; for (var a = e; a < n; a += 3) { t = (r[a] << 16 & 16711680) + (r[a + 1] << 8 & 65280) + (r[a + 2] & 255); o.push(s(t)) } return o.join(\"\") } function p(r) { var e; var n = r.length; var o = n % 3; var a = []; var f = 16383; for (var i = 0, u = n - o; i < u; i += f) { a.push(l(r, i, i + f > u ? u : i + f)) } if (o === 1) { e = r[n - 1]; a.push(t[e >> 2] + t[e << 4 & 63] + \"==\") } else if (o === 2) { e = (r[n - 2] << 8) + r[n - 1]; a.push(t[e >> 10] + t[e >> 4 & 63] + t[e << 2 & 63] + \"=\") } return a.join(\"\") } }, {}] }, {}, [])(\"/\") });\n\n /**\n * [promise-polyfill]{@link https://github.com/taylorhakes/promise-polyfill}\n *\n * @version v8.1.3 \n * @author Hakes, Taylor\n * @copyright Hakes, Taylor 2014\n * @license MIT\n */\n !function(e,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?n():\"function\"==typeof define&&define.amd?define(n):n()}(0,function(){\"use strict\";function e(e){var n=this.constructor;return this.then(function(t){return n.resolve(e()).then(function(){return t})},function(t){return n.resolve(e()).then(function(){return n.reject(t)})})}function n(e){return!(!e||\"undefined\"==typeof e.length)}function t(){}function o(e){if(!(this instanceof o))throw new TypeError(\"Promises must be constructed via new\");if(\"function\"!=typeof e)throw new TypeError(\"not a function\");this._state=0,this._handled=!1,this._value=undefined,this._deferreds=[],c(e,this)}function r(e,n){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn(function(){var t=1===e._state?n.onFulfilled:n.onRejected;if(null!==t){var o;try{o=t(e._value)}catch(r){return void f(n.promise,r)}i(n.promise,o)}else(1===e._state?i:f)(n.promise,e._value)})):e._deferreds.push(n)}function i(e,n){try{if(n===e)throw new TypeError(\"A promise cannot be resolved with itself.\");if(n&&(\"object\"==typeof n||\"function\"==typeof n)){var t=n.then;if(n instanceof o)return e._state=3,e._value=n,void u(e);if(\"function\"==typeof t)return void c(function(e,n){return function(){e.apply(n,arguments)}}(t,n),e)}e._state=1,e._value=n,u(e)}catch(r){f(e,r)}}function f(e,n){e._state=2,e._value=n,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&o._immediateFn(function(){e._handled||o._unhandledRejectionFn(e._value)});for(var n=0,t=e._deferreds.length;t>n;n++)r(e,e._deferreds[n]);e._deferreds=null}function c(e,n){var t=!1;try{e(function(e){t||(t=!0,i(n,e))},function(e){t||(t=!0,f(n,e))})}catch(o){if(t)return;t=!0,f(n,o)}}var a=setTimeout;o.prototype[\"catch\"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var o=new this.constructor(t);return r(this,new function(e,n,t){this.onFulfilled=\"function\"==typeof e?e:null,this.onRejected=\"function\"==typeof n?n:null,this.promise=t}(e,n,o)),o},o.prototype[\"finally\"]=e,o.all=function(e){return new o(function(t,o){function r(e,n){try{if(n&&(\"object\"==typeof n||\"function\"==typeof n)){var u=n.then;if(\"function\"==typeof u)return void u.call(n,function(n){r(e,n)},o)}i[e]=n,0==--f&&t(i)}catch(c){o(c)}}if(!n(e))return o(new TypeError(\"Promise.all accepts an array\"));var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var f=i.length,u=0;i.length>u;u++)r(u,i[u])})},o.resolve=function(e){return e&&\"object\"==typeof e&&e.constructor===o?e:new o(function(n){n(e)})},o.reject=function(e){return new o(function(n,t){t(e)})},o.race=function(e){return new o(function(t,r){if(!n(e))return r(new TypeError(\"Promise.race accepts an array\"));for(var i=0,f=e.length;f>i;i++)o.resolve(e[i]).then(t,r)})},o._immediateFn=\"function\"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){a(e,0)},o._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn(\"Possible Unhandled Promise Rejection:\",e)};var l=function(){if(\"undefined\"!=typeof self)return self;if(\"undefined\"!=typeof window)return window;if(\"undefined\"!=typeof global)return global;throw Error(\"unable to locate global object\")}();\"Promise\"in l?l.Promise.prototype[\"finally\"]||(l.Promise.prototype[\"finally\"]=e):l.Promise=o});\n\n var Keycloak = factory( root[\"sha256\"], root[\"base64js\"] );\n root[\"Keycloak\"] = Keycloak;\n\n if ( typeof define === \"function\" && define.amd ) { \n define( \"keycloak\", [], function () { return Keycloak; } );\n }\n }\n})(window, function (sha256_imported, base64js_imported) {\n if (typeof Promise === 'undefined') {\n throw Error('Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill.');\n }\n\n var loggedPromiseDeprecation = false;\n\n function logPromiseDeprecation() {\n if (!loggedPromiseDeprecation) {\n loggedPromiseDeprecation = true;\n console.warn('[KEYCLOAK] Usage of legacy style promise methods such as `.error()` and `.success()` has been deprecated and support will be removed in future versions. Use standard style promise methods such as `.then() and `.catch()` instead.');\n }\n }\n\n function toKeycloakPromise(promise) {\n promise.__proto__ = KeycloakPromise.prototype;\n return promise;\n }\n\n function KeycloakPromise(executor) {\n return toKeycloakPromise(new Promise(executor));\n }\n\n KeycloakPromise.prototype = Object.create(Promise.prototype);\n KeycloakPromise.prototype.constructor = KeycloakPromise;\n\n KeycloakPromise.prototype.success = function(callback) {\n logPromiseDeprecation();\n\n var promise = this.then(function handleSuccess(value) {\n callback(value);\n });\n \n return toKeycloakPromise(promise);\n };\n\n KeycloakPromise.prototype.error = function(callback) {\n logPromiseDeprecation();\n\n var promise = this.catch(function handleError(error) {\n callback(error);\n });\n\n return toKeycloakPromise(promise);\n };\n\n function Keycloak (config) {\n if (!(this instanceof Keycloak)) {\n return new Keycloak(config);\n }\n\n var kc = this;\n var adapter;\n var refreshQueue = [];\n var callbackStorage;\n\n var loginIframe = {\n enable: true,\n callbackList: [],\n interval: 5\n };\n\n var scripts = document.getElementsByTagName('script');\n for (var i = 0; i < scripts.length; i++) {\n if ((scripts[i].src.indexOf('keycloak.js') !== -1 || scripts[i].src.indexOf('keycloak.min.js') !== -1) && scripts[i].src.indexOf('version=') !== -1) {\n kc.iframeVersion = scripts[i].src.substring(scripts[i].src.indexOf('version=') + 8).split('&')[0];\n }\n }\n\n var useNonce = true;\n var logInfo = createLogger(console.info);\n var logWarn = createLogger(console.warn);\n \n kc.init = function (initOptions) {\n kc.authenticated = false;\n\n callbackStorage = createCallbackStorage();\n var adapters = ['default', 'cordova', 'cordova-native'];\n\n if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {\n adapter = loadAdapter(initOptions.adapter);\n } else if (initOptions && typeof initOptions.adapter === \"object\") {\n adapter = initOptions.adapter;\n } else {\n if (window.Cordova || window.cordova) {\n adapter = loadAdapter('cordova');\n } else {\n adapter = loadAdapter();\n }\n }\n\n if (initOptions) {\n if (typeof initOptions.useNonce !== 'undefined') {\n useNonce = initOptions.useNonce;\n }\n\n if (typeof initOptions.checkLoginIframe !== 'undefined') {\n loginIframe.enable = initOptions.checkLoginIframe;\n }\n\n if (initOptions.checkLoginIframeInterval) {\n loginIframe.interval = initOptions.checkLoginIframeInterval;\n }\n\n if (initOptions.onLoad === 'login-required') {\n kc.loginRequired = true;\n }\n\n if (initOptions.responseMode) {\n if (initOptions.responseMode === 'query' || initOptions.responseMode === 'fragment') {\n kc.responseMode = initOptions.responseMode;\n } else {\n throw 'Invalid value for responseMode';\n }\n }\n\n if (initOptions.flow) {\n switch (initOptions.flow) {\n case 'standard':\n kc.responseType = 'code';\n break;\n case 'implicit':\n kc.responseType = 'id_token token';\n break;\n case 'hybrid':\n kc.responseType = 'code id_token token';\n break;\n default:\n throw 'Invalid value for flow';\n }\n kc.flow = initOptions.flow;\n }\n\n if (initOptions.timeSkew != null) {\n kc.timeSkew = initOptions.timeSkew;\n }\n\n if(initOptions.redirectUri) {\n kc.redirectUri = initOptions.redirectUri;\n }\n\n if (initOptions.silentCheckSsoRedirectUri) {\n kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;\n }\n\n if (initOptions.pkceMethod) {\n if (initOptions.pkceMethod !== \"S256\") {\n throw 'Invalid value for pkceMethod';\n }\n kc.pkceMethod = initOptions.pkceMethod;\n }\n\n if (typeof initOptions.enableLogging === 'boolean') {\n kc.enableLogging = initOptions.enableLogging;\n } else {\n kc.enableLogging = false;\n }\n }\n\n if (!kc.responseMode) {\n kc.responseMode = 'fragment';\n }\n if (!kc.responseType) {\n kc.responseType = 'code';\n kc.flow = 'standard';\n }\n\n var promise = createPromise();\n\n var initPromise = createPromise();\n initPromise.promise.then(function() {\n kc.onReady && kc.onReady(kc.authenticated);\n promise.setSuccess(kc.authenticated);\n }).catch(function(errorData) {\n promise.setError(errorData);\n });\n\n var configPromise = loadConfig(config);\n\n function onLoad() {\n var doLogin = function(prompt) {\n if (!prompt) {\n options.prompt = 'none';\n }\n\n kc.login(options).then(function () {\n initPromise.setSuccess();\n }).catch(function () {\n initPromise.setError();\n });\n }\n\n var checkSsoSilently = function() {\n var ifrm = document.createElement(\"iframe\");\n var src = kc.createLoginUrl({prompt: 'none', redirectUri: kc.silentCheckSsoRedirectUri});\n ifrm.setAttribute(\"src\", src);\n ifrm.setAttribute(\"title\", \"keycloak-silent-check-sso\");\n ifrm.style.display = \"none\";\n document.body.appendChild(ifrm);\n\n var messageCallback = function(event) {\n if (event.origin !== window.location.origin || ifrm.contentWindow !== event.source) {\n return;\n }\n\n var oauth = parseCallback(event.data);\n processCallback(oauth, initPromise);\n\n document.body.removeChild(ifrm);\n window.removeEventListener(\"message\", messageCallback);\n };\n\n window.addEventListener(\"message\", messageCallback);\n };\n\n var options = {};\n switch (initOptions.onLoad) {\n case 'check-sso':\n if (loginIframe.enable) {\n setupCheckLoginIframe().then(function() {\n checkLoginIframe().then(function (unchanged) {\n if (!unchanged) {\n kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);\n } else {\n initPromise.setSuccess();\n }\n }).catch(function () {\n initPromise.setError();\n });\n });\n } else {\n kc.silentCheckSsoRedirectUri ? checkSsoSilently() : doLogin(false);\n }\n break;\n case 'login-required':\n doLogin(true);\n break;\n default:\n throw 'Invalid value for onLoad';\n }\n }\n\n function processInit() {\n var callback = parseCallback(window.location.href);\n\n if (callback) {\n window.history.replaceState(window.history.state, null, callback.newUrl);\n }\n\n if (callback && callback.valid) {\n return setupCheckLoginIframe().then(function() {\n processCallback(callback, initPromise);\n }).catch(function (e) {\n initPromise.setError();\n });\n } else if (initOptions) {\n if (initOptions.token && initOptions.refreshToken) {\n setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);\n\n if (loginIframe.enable) {\n setupCheckLoginIframe().then(function() {\n checkLoginIframe().then(function (unchanged) {\n if (unchanged) {\n kc.onAuthSuccess && kc.onAuthSuccess();\n initPromise.setSuccess();\n scheduleCheckIframe();\n } else {\n initPromise.setSuccess();\n }\n }).catch(function () {\n initPromise.setError();\n });\n });\n } else {\n kc.updateToken(-1).then(function() {\n kc.onAuthSuccess && kc.onAuthSuccess();\n initPromise.setSuccess();\n }).catch(function() {\n kc.onAuthError && kc.onAuthError();\n if (initOptions.onLoad) {\n onLoad();\n } else {\n initPromise.setError();\n }\n });\n }\n } else if (initOptions.onLoad) {\n onLoad();\n } else {\n initPromise.setSuccess();\n }\n } else {\n initPromise.setSuccess();\n }\n }\n\n configPromise.then(processInit);\n configPromise.catch(function() {\n promise.setError();\n });\n\n return promise.promise;\n }\n\n kc.login = function (options) {\n return adapter.login(options);\n }\n\n function generateRandomData(len) {\n // use web crypto APIs if possible\n var array = null;\n var crypto = window.crypto || window.msCrypto;\n if (crypto && crypto.getRandomValues && window.Uint8Array) {\n array = new Uint8Array(len);\n crypto.getRandomValues(array);\n return array;\n }\n\n // fallback to Math random\n array = new Array(len);\n for (var j = 0; j < array.length; j++) {\n array[j] = Math.floor(256 * Math.random());\n }\n return array;\n }\n\n function generateCodeVerifier(len) {\n return generateRandomString(len, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789');\n }\n\n function generateRandomString(len, alphabet){\n var randomData = generateRandomData(len);\n var chars = new Array(len);\n for (var i = 0; i < len; i++) {\n chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length);\n }\n return String.fromCharCode.apply(null, chars);\n }\n\n function generatePkceChallenge(pkceMethod, codeVerifier) {\n switch (pkceMethod) {\n // The use of the \"plain\" method is considered insecure and therefore not supported.\n case \"S256\":\n // hash codeVerifier, then encode as url-safe base64 without padding\n var hashBytes = new Uint8Array(sha256_imported.arrayBuffer(codeVerifier));\n var encodedHash = base64js_imported.fromByteArray(hashBytes)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/\\=/g, '');\n return encodedHash;\n default:\n throw 'Invalid value for pkceMethod';\n }\n }\n\n kc.createLoginUrl = function(options) {\n var state = createUUID();\n var nonce = createUUID();\n\n var redirectUri = adapter.redirectUri(options);\n\n var callbackState = {\n state: state,\n nonce: nonce,\n redirectUri: encodeURIComponent(redirectUri)\n };\n\n if (options && options.prompt) {\n callbackState.prompt = options.prompt;\n }\n\n var baseUrl;\n if (options && options.action == 'register') {\n baseUrl = kc.endpoints.register();\n } else {\n baseUrl = kc.endpoints.authorize();\n }\n\n var scope;\n if (options && options.scope) {\n if (options.scope.indexOf(\"openid\") != -1) {\n scope = options.scope;\n } else {\n scope = \"openid \" + options.scope;\n }\n } else {\n scope = \"openid\";\n }\n\n var url = baseUrl\n + '?client_id=' + encodeURIComponent(kc.clientId)\n + '&redirect_uri=' + encodeURIComponent(redirectUri)\n + '&state=' + encodeURIComponent(state)\n + '&response_mode=' + encodeURIComponent(kc.responseMode)\n + '&response_type=' + encodeURIComponent(kc.responseType)\n + '&scope=' + encodeURIComponent(scope);\n if (useNonce) {\n url = url + '&nonce=' + encodeURIComponent(nonce);\n }\n\n if (options && options.prompt) {\n url += '&prompt=' + encodeURIComponent(options.prompt);\n }\n\n if (options && options.maxAge) {\n url += '&max_age=' + encodeURIComponent(options.maxAge);\n }\n\n if (options && options.loginHint) {\n url += '&login_hint=' + encodeURIComponent(options.loginHint);\n }\n\n if (options && options.idpHint) {\n url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);\n }\n\n if (options && options.locale) {\n url += '&ui_locales=' + encodeURIComponent(options.locale);\n }\n\n if (kc.pkceMethod) {\n var codeVerifier = generateCodeVerifier(96);\n callbackState.pkceCodeVerifier = codeVerifier;\n var pkceChallenge = generatePkceChallenge(kc.pkceMethod, codeVerifier);\n url += '&code_challenge=' + pkceChallenge;\n url += '&code_challenge_method=' + kc.pkceMethod;\n }\n\n callbackStorage.add(callbackState);\n\n return url;\n }\n\n kc.logout = function(options) {\n return adapter.logout(options);\n }\n\n kc.createLogoutUrl = function(options) {\n var url = kc.endpoints.logout()\n + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options, false));\n\n return url;\n }\n\n kc.register = function (options) {\n return adapter.register(options);\n }\n\n kc.createRegisterUrl = function(options) {\n if (!options) {\n options = {};\n }\n options.action = 'register';\n return kc.createLoginUrl(options);\n }\n\n kc.createAccountUrl = function(options) {\n var realm = getRealmUrl();\n var url = undefined;\n if (typeof realm !== 'undefined') {\n url = realm\n + '/account'\n + '?referrer=' + encodeURIComponent(kc.clientId)\n + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));\n }\n return url;\n }\n\n kc.accountManagement = function() {\n return adapter.accountManagement();\n }\n\n kc.hasRealmRole = function (role) {\n var access = kc.realmAccess;\n return !!access && access.roles.indexOf(role) >= 0;\n }\n\n kc.hasResourceRole = function(role, resource) {\n if (!kc.resourceAccess) {\n return false;\n }\n\n var access = kc.resourceAccess[resource || kc.clientId];\n return !!access && access.roles.indexOf(role) >= 0;\n }\n\n kc.loadUserProfile = function() {\n var url = getRealmUrl() + '/account';\n var req = new XMLHttpRequest();\n req.open('GET', url, true);\n req.setRequestHeader('Accept', 'application/json');\n req.setRequestHeader('Authorization', 'bearer ' + kc.token);\n\n var promise = createPromise();\n\n req.onreadystatechange = function () {\n if (req.readyState == 4) {\n if (req.status == 200) {\n kc.profile = JSON.parse(req.responseText);\n promise.setSuccess(kc.profile);\n } else {\n promise.setError();\n }\n }\n }\n\n req.send();\n\n return promise.promise;\n }\n\n kc.loadUserInfo = function() {\n var url = kc.endpoints.userinfo();\n var req = new XMLHttpRequest();\n req.open('GET', url, true);\n req.setRequestHeader('Accept', 'application/json');\n req.setRequestHeader('Authorization', 'bearer ' + kc.token);\n\n var promise = createPromise();\n\n req.onreadystatechange = function () {\n if (req.readyState == 4) {\n if (req.status == 200) {\n kc.userInfo = JSON.parse(req.responseText);\n promise.setSuccess(kc.userInfo);\n } else {\n promise.setError();\n }\n }\n }\n\n req.send();\n\n return promise.promise;\n }\n\n kc.isTokenExpired = function(minValidity) {\n if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != 'implicit' )) {\n throw 'Not authenticated';\n }\n\n if (kc.timeSkew == null) {\n logInfo('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set');\n return true;\n }\n\n var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;\n if (minValidity) {\n if (isNaN(minValidity)) {\n throw 'Invalid minValidity';\n }\n expiresIn -= minValidity;\n }\n return expiresIn < 0;\n }\n\n kc.updateToken = function(minValidity) {\n var promise = createPromise();\n\n if (!kc.refreshToken) {\n promise.setError();\n return promise.promise;\n }\n\n minValidity = minValidity || 5;\n\n var exec = function() {\n var refreshToken = false;\n if (minValidity == -1) {\n refreshToken = true;\n logInfo('[KEYCLOAK] Refreshing token: forced refresh');\n } else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {\n refreshToken = true;\n logInfo('[KEYCLOAK] Refreshing token: token expired');\n }\n\n if (!refreshToken) {\n promise.setSuccess(false);\n } else {\n var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;\n var url = kc.endpoints.token();\n\n refreshQueue.push(promise);\n\n if (refreshQueue.length == 1) {\n var req = new XMLHttpRequest();\n req.open('POST', url, true);\n req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n req.withCredentials = true;\n\n params += '&client_id=' + encodeURIComponent(kc.clientId);\n\n var timeLocal = new Date().getTime();\n\n req.onreadystatechange = function () {\n if (req.readyState == 4) {\n if (req.status == 200) {\n logInfo('[KEYCLOAK] Token refreshed');\n\n timeLocal = (timeLocal + new Date().getTime()) / 2;\n\n var tokenResponse = JSON.parse(req.responseText);\n\n setToken(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], timeLocal);\n\n kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();\n for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {\n p.setSuccess(true);\n }\n } else {\n logWarn('[KEYCLOAK] Failed to refresh token');\n\n if (req.status == 400) {\n kc.clearToken();\n }\n\n kc.onAuthRefreshError && kc.onAuthRefreshError();\n for (var p = refreshQueue.pop(); p != null; p = refreshQueue.pop()) {\n p.setError(true);\n }\n }\n }\n };\n\n req.send(params);\n }\n }\n }\n\n if (loginIframe.enable) {\n var iframePromise = checkLoginIframe();\n iframePromise.then(function() {\n exec();\n }).catch(function() {\n promise.setError();\n });\n } else {\n exec();\n }\n\n return promise.promise;\n }\n\n kc.clearToken = function() {\n if (kc.token) {\n setToken(null, null, null);\n kc.onAuthLogout && kc.onAuthLogout();\n if (kc.loginRequired) {\n kc.login();\n }\n }\n }\n\n function getRealmUrl() {\n if (typeof kc.authServerUrl !== 'undefined') {\n if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == '/') {\n return kc.authServerUrl + 'realms/' + encodeURIComponent(kc.realm);\n } else {\n return kc.authServerUrl + '/realms/' + encodeURIComponent(kc.realm);\n }\n } else {\n \treturn undefined;\n }\n }\n\n function getOrigin() {\n if (!window.location.origin) {\n return window.location.protocol + \"//\" + window.location.hostname + (window.location.port ? ':' + window.location.port: '');\n } else {\n return window.location.origin;\n }\n }\n\n function processCallback(oauth, promise) {\n var code = oauth.code;\n var error = oauth.error;\n var prompt = oauth.prompt;\n\n var timeLocal = new Date().getTime();\n\n if (error) {\n if (prompt != 'none') {\n var errorData = { error: error, error_description: oauth.error_description };\n kc.onAuthError && kc.onAuthError(errorData);\n promise && promise.setError(errorData);\n } else {\n promise && promise.setSuccess();\n }\n return;\n } else if ((kc.flow != 'standard') && (oauth.access_token || oauth.id_token)) {\n authSuccess(oauth.access_token, null, oauth.id_token, true);\n }\n\n if ((kc.flow != 'implicit') && code) {\n var params = 'code=' + code + '&grant_type=authorization_code';\n var url = kc.endpoints.token();\n\n var req = new XMLHttpRequest();\n req.open('POST', url, true);\n req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');\n\n params += '&client_id=' + encodeURIComponent(kc.clientId);\n params += '&redirect_uri=' + oauth.redirectUri;\n\n if (oauth.pkceCodeVerifier) {\n params += '&code_verifier=' + oauth.pkceCodeVerifier;\n }\n\n req.withCredentials = true;\n\n req.onreadystatechange = function() {\n if (req.readyState == 4) {\n if (req.status == 200) {\n\n var tokenResponse = JSON.parse(req.responseText);\n authSuccess(tokenResponse['access_token'], tokenResponse['refresh_token'], tokenResponse['id_token'], kc.flow === 'standard');\n scheduleCheckIframe();\n } else {\n kc.onAuthError && kc.onAuthError();\n promise && promise.setError();\n }\n }\n };\n\n req.send(params);\n }\n\n function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {\n timeLocal = (timeLocal + new Date().getTime()) / 2;\n\n setToken(accessToken, refreshToken, idToken, timeLocal);\n\n if (useNonce && ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||\n (kc.refreshTokenParsed && kc.refreshTokenParsed.nonce != oauth.storedNonce) ||\n (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))) {\n\n logInfo('[KEYCLOAK] Invalid nonce, clearing token');\n kc.clearToken();\n promise && promise.setError();\n } else {\n if (fulfillPromise) {\n kc.onAuthSuccess && kc.onAuthSuccess();\n promise && promise.setSuccess();\n }\n }\n }\n\n }\n\n function loadConfig(url) {\n var promise = createPromise();\n var configUrl;\n\n if (!config) {\n configUrl = 'keycloak.json';\n } else if (typeof config === 'string') {\n configUrl = config;\n }\n\n function setupOidcEndoints(oidcConfiguration) {\n if (! oidcConfiguration) {\n kc.endpoints = {\n authorize: function() {\n return getRealmUrl() + '/protocol/openid-connect/auth';\n },\n token: function() {\n return getRealmUrl() + '/protocol/openid-connect/token';\n },\n logout: function() {\n return getRealmUrl() + '/protocol/openid-connect/logout';\n },\n checkSessionIframe: function() {\n var src = getRealmUrl() + '/protocol/openid-connect/login-status-iframe.html';\n if (kc.iframeVersion) {\n src = src + '?version=' + kc.iframeVersion;\n }\n return src;\n },\n register: function() {\n return getRealmUrl() + '/protocol/openid-connect/registrations';\n },\n userinfo: function() {\n return getRealmUrl() + '/protocol/openid-connect/userinfo';\n }\n };\n } else {\n kc.endpoints = {\n authorize: function() {\n return oidcConfiguration.authorization_endpoint;\n },\n token: function() {\n return oidcConfiguration.token_endpoint;\n },\n logout: function() {\n if (!oidcConfiguration.end_session_endpoint) {\n throw \"Not supported by the OIDC server\";\n }\n return oidcConfiguration.end_session_endpoint;\n },\n checkSessionIframe: function() {\n if (!oidcConfiguration.check_session_iframe) {\n throw \"Not supported by the OIDC server\";\n }\n return oidcConfiguration.check_session_iframe;\n },\n register: function() {\n throw 'Redirection to \"Register user\" page not supported in standard OIDC mode';\n },\n userinfo: function() {\n if (!oidcConfiguration.userinfo_endpoint) {\n throw \"Not supported by the OIDC server\";\n }\n return oidcConfiguration.userinfo_endpoint;\n }\n }\n }\n }\n\n if (configUrl) {\n var req = new XMLHttpRequest();\n req.open('GET', configUrl, true);\n req.setRequestHeader('Accept', 'application/json');\n\n req.onreadystatechange = function () {\n if (req.readyState == 4) {\n if (req.status == 200 || fileLoaded(req)) {\n var config = JSON.parse(req.responseText);\n\n kc.authServerUrl = config['auth-server-url'];\n kc.realm = config['realm'];\n kc.clientId = config['resource'];\n setupOidcEndoints(null);\n promise.setSuccess();\n } else {\n promise.setError();\n }\n }\n };\n\n req.send();\n } else {\n if (!config.clientId) {\n throw 'clientId missing';\n }\n\n kc.clientId = config.clientId;\n\n var oidcProvider = config['oidcProvider'];\n if (!oidcProvider) {\n if (!config['url']) {\n var scripts = document.getElementsByTagName('script');\n for (var i = 0; i < scripts.length; i++) {\n if (scripts[i].src.match(/.*keycloak\\.js/)) {\n config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));\n break;\n }\n }\n }\n if (!config.realm) {\n throw 'realm missing';\n }\n\n kc.authServerUrl = config.url;\n kc.realm = config.realm;\n setupOidcEndoints(null);\n promise.setSuccess();\n } else {\n if (typeof oidcProvider === 'string') {\n var oidcProviderConfigUrl;\n if (oidcProvider.charAt(oidcProvider.length - 1) == '/') {\n oidcProviderConfigUrl = oidcProvider + '.well-known/openid-configuration';\n } else {\n oidcProviderConfigUrl = oidcProvider + '/.well-known/openid-configuration';\n }\n var req = new XMLHttpRequest();\n req.open('GET', oidcProviderConfigUrl, true);\n req.setRequestHeader('Accept', 'application/json');\n\n req.onreadystatechange = function () {\n if (req.readyState == 4) {\n if (req.status == 200 || fileLoaded(req)) {\n var oidcProviderConfig = JSON.parse(req.responseText);\n setupOidcEndoints(oidcProviderConfig);\n promise.setSuccess();\n } else {\n promise.setError();\n }\n }\n };\n\n req.send();\n } else {\n setupOidcEndoints(oidcProvider);\n promise.setSuccess();\n }\n }\n }\n\n return promise.promise;\n }\n\n function fileLoaded(xhr) {\n return xhr.status == 0 && xhr.responseText && xhr.responseURL.startsWith('file:');\n }\n\n function setToken(token, refreshToken, idToken, timeLocal) {\n if (kc.tokenTimeoutHandle) {\n clearTimeout(kc.tokenTimeoutHandle);\n kc.tokenTimeoutHandle = null;\n }\n\n if (refreshToken) {\n kc.refreshToken = refreshToken;\n kc.refreshTokenParsed = decodeToken(refreshToken);\n } else {\n delete kc.refreshToken;\n delete kc.refreshTokenParsed;\n }\n\n if (idToken) {\n kc.idToken = idToken;\n kc.idTokenParsed = decodeToken(idToken);\n } else {\n delete kc.idToken;\n delete kc.idTokenParsed;\n }\n\n if (token) {\n kc.token = token;\n kc.tokenParsed = decodeToken(token);\n kc.sessionId = kc.tokenParsed.session_state;\n kc.authenticated = true;\n kc.subject = kc.tokenParsed.sub;\n kc.realmAccess = kc.tokenParsed.realm_access;\n kc.resourceAccess = kc.tokenParsed.resource_access;\n\n if (timeLocal) {\n kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;\n }\n\n if (kc.timeSkew != null) {\n logInfo('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');\n\n if (kc.onTokenExpired) {\n var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;\n logInfo('[KEYCLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s');\n if (expiresIn <= 0) {\n kc.onTokenExpired();\n } else {\n kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);\n }\n }\n }\n } else {\n delete kc.token;\n delete kc.tokenParsed;\n delete kc.subject;\n delete kc.realmAccess;\n delete kc.resourceAccess;\n\n kc.authenticated = false;\n }\n }\n\n function decodeToken(str) {\n str = str.split('.')[1];\n\n str = str.replace('/-/g', '+');\n str = str.replace('/_/g', '/');\n switch (str.length % 4)\n {\n case 0:\n break;\n case 2:\n str += '==';\n break;\n case 3:\n str += '=';\n break;\n default:\n throw 'Invalid token';\n }\n\n str = (str + '===').slice(0, str.length + (str.length % 4));\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n\n str = decodeURIComponent(escape(atob(str)));\n\n str = JSON.parse(str);\n return str;\n }\n\n function createUUID() {\n var hexDigits = '0123456789abcdef';\n var s = generateRandomString(36, hexDigits).split(\"\");\n s[14] = '4';\n s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);\n s[8] = s[13] = s[18] = s[23] = '-';\n var uuid = s.join('');\n return uuid;\n }\n\n function parseCallback(url) {\n var oauth = parseCallbackUrl(url);\n if (!oauth) {\n return;\n }\n\n var oauthState = callbackStorage.get(oauth.state);\n\n if (oauthState) {\n oauth.valid = true;\n oauth.redirectUri = oauthState.redirectUri;\n oauth.storedNonce = oauthState.nonce;\n oauth.prompt = oauthState.prompt;\n oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;\n }\n\n return oauth;\n }\n\n function parseCallbackUrl(url) {\n var supportedParams;\n switch (kc.flow) {\n case 'standard':\n supportedParams = ['code', 'state', 'session_state'];\n break;\n case 'implicit':\n supportedParams = ['access_token', 'token_type', 'id_token', 'state', 'session_state', 'expires_in'];\n break;\n case 'hybrid':\n supportedParams = ['access_token', 'id_token', 'code', 'state', 'session_state'];\n break;\n }\n\n supportedParams.push('error');\n supportedParams.push('error_description');\n supportedParams.push('error_uri');\n\n var queryIndex = url.indexOf('?');\n var fragmentIndex = url.indexOf('#');\n\n var newUrl;\n var parsed;\n\n if (kc.responseMode === 'query' && queryIndex !== -1) {\n newUrl = url.substring(0, queryIndex);\n parsed = parseCallbackParams(url.substring(queryIndex + 1, fragmentIndex !== -1 ? fragmentIndex : url.length), supportedParams);\n if (parsed.paramsString !== '') {\n newUrl += '?' + parsed.paramsString;\n }\n if (fragmentIndex !== -1) {\n newUrl += url.substring(fragmentIndex);\n }\n } else if (kc.responseMode === 'fragment' && fragmentIndex !== -1) {\n newUrl = url.substring(0, fragmentIndex);\n parsed = parseCallbackParams(url.substring(fragmentIndex + 1), supportedParams);\n if (parsed.paramsString !== '') {\n newUrl += '#' + parsed.paramsString;\n }\n }\n\n if (parsed && parsed.oauthParams) {\n if (kc.flow === 'standard' || kc.flow === 'hybrid') {\n if ((parsed.oauthParams.code || parsed.oauthParams.error) && parsed.oauthParams.state) {\n parsed.oauthParams.newUrl = newUrl;\n return parsed.oauthParams;\n }\n } else if (kc.flow === 'implicit') {\n if ((parsed.oauthParams.access_token || parsed.oauthParams.error) && parsed.oauthParams.state) {\n parsed.oauthParams.newUrl = newUrl;\n return parsed.oauthParams;\n }\n }\n }\n }\n\n function parseCallbackParams(paramsString, supportedParams) {\n var p = paramsString.split('&');\n var result = {\n paramsString: '',\n oauthParams: {}\n }\n for (var i = 0; i < p.length; i++) {\n var split = p[i].indexOf(\"=\");\n var key = p[i].slice(0, split);\n if (supportedParams.indexOf(key) !== -1) {\n result.oauthParams[key] = p[i].slice(split + 1);\n } else {\n if (result.paramsString !== '') {\n result.paramsString += '&';\n }\n result.paramsString += p[i];\n }\n }\n return result;\n }\n\n function createPromise() {\n // Need to create a native Promise which also preserves the\n // interface of the custom promise type previously used by the API\n var p = {\n setSuccess: function(result) {\n p.resolve(result);\n },\n\n setError: function(result) {\n p.reject(result);\n }\n };\n p.promise = new KeycloakPromise(function(resolve, reject) {\n p.resolve = resolve;\n p.reject = reject;\n });\n return p;\n }\n\n\n function setupCheckLoginIframe() {\n var promise = createPromise();\n\n if (!loginIframe.enable) {\n promise.setSuccess();\n return promise.promise;\n }\n\n if (loginIframe.iframe) {\n promise.setSuccess();\n return promise.promise;\n }\n\n var iframe = document.createElement('iframe');\n loginIframe.iframe = iframe;\n\n iframe.onload = function() {\n var authUrl = kc.endpoints.authorize();\n if (authUrl.charAt(0) === '/') {\n loginIframe.iframeOrigin = getOrigin();\n } else {\n loginIframe.iframeOrigin = authUrl.substring(0, authUrl.indexOf('/', 8));\n }\n promise.setSuccess();\n }\n\n var src = kc.endpoints.checkSessionIframe();\n iframe.setAttribute('src', src );\n iframe.setAttribute('title', 'keycloak-session-iframe' );\n iframe.style.display = 'none';\n document.body.appendChild(iframe);\n\n var messageCallback = function(event) {\n if ((event.origin !== loginIframe.iframeOrigin) || (loginIframe.iframe.contentWindow !== event.source)) {\n return;\n }\n\n if (!(event.data == 'unchanged' || event.data == 'changed' || event.data == 'error')) {\n return;\n }\n\n\n if (event.data != 'unchanged') {\n kc.clearToken();\n }\n\n var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length);\n\n for (var i = callbacks.length - 1; i >= 0; --i) {\n var promise = callbacks[i];\n if (event.data == 'error') {\n promise.setError();\n } else {\n promise.setSuccess(event.data == 'unchanged');\n }\n }\n };\n\n window.addEventListener('message', messageCallback, false);\n\n return promise.promise;\n }\n\n function scheduleCheckIframe() {\n if (loginIframe.enable) {\n if (kc.token) {\n setTimeout(function() {\n checkLoginIframe().then(function(unchanged) {\n if (unchanged) {\n scheduleCheckIframe();\n }\n });\n }, loginIframe.interval * 1000);\n }\n }\n }\n\n function checkLoginIframe() {\n var promise = createPromise();\n\n if (loginIframe.iframe && loginIframe.iframeOrigin ) {\n var msg = kc.clientId + ' ' + (kc.sessionId ? kc.sessionId : '');\n loginIframe.callbackList.push(promise);\n var origin = loginIframe.iframeOrigin;\n if (loginIframe.callbackList.length == 1) {\n loginIframe.iframe.contentWindow.postMessage(msg, origin);\n }\n } else {\n promise.setSuccess();\n }\n\n return promise.promise;\n }\n\n function loadAdapter(type) {\n if (!type || type == 'default') {\n return {\n login: function(options) {\n window.location.replace(kc.createLoginUrl(options));\n return createPromise().promise;\n },\n\n logout: function(options) {\n window.location.replace(kc.createLogoutUrl(options));\n return createPromise().promise;\n },\n\n register: function(options) {\n window.location.replace(kc.createRegisterUrl(options));\n return createPromise().promise;\n },\n\n accountManagement : function() {\n var accountUrl = kc.createAccountUrl();\n if (typeof accountUrl !== 'undefined') {\n window.location.href = accountUrl;\n } else {\n throw \"Not supported by the OIDC server\";\n }\n return createPromise().promise;\n },\n\n redirectUri: function(options, encodeHash) {\n if (arguments.length == 1) {\n encodeHash = true;\n }\n\n if (options && options.redirectUri) {\n return options.redirectUri;\n } else if (kc.redirectUri) {\n return kc.redirectUri;\n } else {\n return location.href;\n }\n }\n };\n }\n\n if (type == 'cordova') {\n loginIframe.enable = false;\n var cordovaOpenWindowWrapper = function(loginUrl, target, options) {\n if (window.cordova && window.cordova.InAppBrowser) {\n // Use inappbrowser for IOS and Android if available\n return window.cordova.InAppBrowser.open(loginUrl, target, options);\n } else {\n return window.open(loginUrl, target, options);\n }\n };\n\n var shallowCloneCordovaOptions = function (userOptions) {\n if (userOptions && userOptions.cordovaOptions) {\n return Object.keys(userOptions.cordovaOptions).reduce(function (options, optionName) {\n options[optionName] = userOptions.cordovaOptions[optionName];\n return options;\n }, {});\n } else {\n return {};\n }\n };\n\n var formatCordovaOptions = function (cordovaOptions) {\n return Object.keys(cordovaOptions).reduce(function (options, optionName) {\n options.push(optionName+\"=\"+cordovaOptions[optionName]);\n return options;\n }, []).join(\",\");\n };\n\n var createCordovaOptions = function (userOptions) {\n var cordovaOptions = shallowCloneCordovaOptions(userOptions);\n cordovaOptions.location = 'no';\n if (userOptions && userOptions.prompt == 'none') {\n cordovaOptions.hidden = 'yes';\n }\n return formatCordovaOptions(cordovaOptions);\n };\n\n return {\n login: function(options) {\n var promise = createPromise();\n\n var cordovaOptions = createCordovaOptions(options);\n var loginUrl = kc.createLoginUrl(options);\n var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', cordovaOptions);\n var completed = false;\n\n var closed = false;\n var closeBrowser = function() {\n closed = true;\n ref.close();\n };\n\n ref.addEventListener('loadstart', function(event) {\n if (event.url.indexOf('http://localhost') == 0) {\n var callback = parseCallback(event.url);\n processCallback(callback, promise);\n closeBrowser();\n completed = true;\n }\n });\n\n ref.addEventListener('loaderror', function(event) {\n if (!completed) {\n if (event.url.indexOf('http://localhost') == 0) {\n var callback = parseCallback(event.url);\n processCallback(callback, promise);\n closeBrowser();\n completed = true;\n } else {\n promise.setError();\n closeBrowser();\n }\n }\n });\n\n ref.addEventListener('exit', function(event) {\n if (!closed) {\n promise.setError({\n reason: \"closed_by_user\"\n });\n }\n });\n\n return promise.promise;\n },\n\n logout: function(options) {\n var promise = createPromise();\n\n var logoutUrl = kc.createLogoutUrl(options);\n var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes');\n\n var error;\n\n ref.addEventListener('loadstart', function(event) {\n if (event.url.indexOf('http://localhost') == 0) {\n ref.close();\n }\n });\n\n ref.addEventListener('loaderror', function(event) {\n if (event.url.indexOf('http://localhost') == 0) {\n ref.close();\n } else {\n error = true;\n ref.close();\n }\n });\n\n ref.addEventListener('exit', function(event) {\n if (error) {\n promise.setError();\n } else {\n kc.clearToken();\n promise.setSuccess();\n }\n });\n\n return promise.promise;\n },\n\n register : function(options) {\n var promise = createPromise();\n var registerUrl = kc.createRegisterUrl();\n var cordovaOptions = createCordovaOptions(options);\n var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', cordovaOptions);\n ref.addEventListener('loadstart', function(event) {\n if (event.url.indexOf('http://localhost') == 0) {\n ref.close();\n var oauth = parseCallback(event.url);\n processCallback(oauth, promise);\n }\n });\n return promise.promise;\n },\n\n accountManagement : function() {\n var accountUrl = kc.createAccountUrl();\n if (typeof accountUrl !== 'undefined') {\n var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');\n ref.addEventListener('loadstart', function(event) {\n if (event.url.indexOf('http://localhost') == 0) {\n ref.close();\n }\n });\n } else {\n throw \"Not supported by the OIDC server\";\n }\n },\n\n redirectUri: function(options) {\n return 'http://localhost';\n }\n }\n }\n\n if (type == 'cordova-native') {\n loginIframe.enable = false;\n\n return {\n login: function(options) {\n var promise = createPromise();\n var loginUrl = kc.createLoginUrl(options);\n\n universalLinks.subscribe('keycloak', function(event) {\n universalLinks.unsubscribe('keycloak');\n window.cordova.plugins.browsertab.close();\n var oauth = parseCallback(event.url);\n processCallback(oauth, promise);\n });\n\n window.cordova.plugins.browsertab.openUrl(loginUrl);\n return promise.promise;\n },\n\n logout: function(options) {\n var promise = createPromise();\n var logoutUrl = kc.createLogoutUrl(options);\n\n universalLinks.subscribe('keycloak', function(event) {\n universalLinks.unsubscribe('keycloak');\n window.cordova.plugins.browsertab.close();\n kc.clearToken();\n promise.setSuccess();\n });\n\n window.cordova.plugins.browsertab.openUrl(logoutUrl);\n return promise.promise;\n },\n\n register : function(options) {\n var promise = createPromise();\n var registerUrl = kc.createRegisterUrl(options);\n universalLinks.subscribe('keycloak' , function(event) {\n universalLinks.unsubscribe('keycloak');\n window.cordova.plugins.browsertab.close();\n var oauth = parseCallback(event.url);\n processCallback(oauth, promise);\n });\n window.cordova.plugins.browsertab.openUrl(registerUrl);\n return promise.promise;\n\n },\n\n accountManagement : function() {\n var accountUrl = kc.createAccountUrl();\n if (typeof accountUrl !== 'undefined') {\n window.cordova.plugins.browsertab.openUrl(accountUrl);\n } else {\n throw \"Not supported by the OIDC server\";\n }\n },\n\n redirectUri: function(options) {\n if (options && options.redirectUri) {\n return options.redirectUri;\n } else if (kc.redirectUri) {\n return kc.redirectUri;\n } else {\n return \"http://localhost\";\n }\n }\n }\n }\n\n throw 'invalid adapter type: ' + type;\n }\n\n var LocalStorage = function() {\n if (!(this instanceof LocalStorage)) {\n return new LocalStorage();\n }\n\n localStorage.setItem('kc-test', 'test');\n localStorage.removeItem('kc-test');\n\n var cs = this;\n\n function clearExpired() {\n var time = new Date().getTime();\n for (var i = 0; i < localStorage.length; i++) {\n var key = localStorage.key(i);\n if (key && key.indexOf('kc-callback-') == 0) {\n var value = localStorage.getItem(key);\n if (value) {\n try {\n var expires = JSON.parse(value).expires;\n if (!expires || expires < time) {\n localStorage.removeItem(key);\n }\n } catch (err) {\n localStorage.removeItem(key);\n }\n }\n }\n }\n }\n\n cs.get = function(state) {\n if (!state) {\n return;\n }\n\n var key = 'kc-callback-' + state;\n var value = localStorage.getItem(key);\n if (value) {\n localStorage.removeItem(key);\n value = JSON.parse(value);\n }\n\n clearExpired();\n return value;\n };\n\n cs.add = function(state) {\n clearExpired();\n\n var key = 'kc-callback-' + state.state;\n state.expires = new Date().getTime() + (60 * 60 * 1000);\n localStorage.setItem(key, JSON.stringify(state));\n };\n };\n\n var CookieStorage = function() {\n if (!(this instanceof CookieStorage)) {\n return new CookieStorage();\n }\n\n var cs = this;\n\n cs.get = function(state) {\n if (!state) {\n return;\n }\n\n var value = getCookie('kc-callback-' + state);\n setCookie('kc-callback-' + state, '', cookieExpiration(-100));\n if (value) {\n return JSON.parse(value);\n }\n };\n\n cs.add = function(state) {\n setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60));\n };\n\n cs.removeItem = function(key) {\n setCookie(key, '', cookieExpiration(-100));\n };\n\n var cookieExpiration = function (minutes) {\n var exp = new Date();\n exp.setTime(exp.getTime() + (minutes*60*1000));\n return exp;\n };\n\n var getCookie = function (key) {\n var name = key + '=';\n var ca = document.cookie.split(';');\n for (var i = 0; i < ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) == ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) == 0) {\n return c.substring(name.length, c.length);\n }\n }\n return '';\n };\n\n var setCookie = function (key, value, expirationDate) {\n var cookie = key + '=' + value + '; '\n + 'expires=' + expirationDate.toUTCString() + '; ';\n document.cookie = cookie;\n }\n };\n\n function createCallbackStorage() {\n try {\n return new LocalStorage();\n } catch (err) {\n }\n\n return new CookieStorage();\n }\n\n function createLogger(fn) {\n return function() {\n if (kc.enableLogging) {\n fn.apply(console, Array.prototype.slice.call(arguments));\n }\n };\n }\n }\n\n return Keycloak;\n})\n","export enum SessionStorageKeys {\n KeyCloakToken = 'KEYCLOAK_TOKEN',\n KeyCloakRefreshToken = 'KEYCLOAK_REFRESH_TOKEN',\n KeyCloakIdToken = 'KEYCLOAK_ID_TOKEN',\n ApiConfigKey = 'AUTH_API_CONFIG',\n PreventStorageSync = 'PREVENT_STORAGE_SYNC',\n LaunchDarklyFlags = 'LD_FLAGS',\n CurrentAccount = 'CURRENT_ACCOUNT',\n AuthApiUrl = 'AUTH_API_URL',\n AuthWebUrl = 'AUTH_WEB_URL',\n StatusApiUrl = 'STATUS_API_URL',\n WhatsNew = 'WHATS_NEW',\n SessionSynced = 'SESSION_SYNCED',\n RegistryHomeUrl = 'REGISTRY_HOME_URL',\n NameRequestUrl = 'NAME_REQUEST_URL',\n PprWebUrl = 'PPR_WEB_URL',\n SiteminderLogoutUrl = 'SITEMINDER_LOGOUT_URL'\n}\n\nexport enum Account {\n ANONYMOUS = 'ANONYMOUS',\n PREMIUM = 'PREMIUM',\n BASIC = 'BASIC',\n SBC_STAFF = 'SBC_STAFF',\n STAFF = 'STAFF'\n}\n\nexport enum IdpHint {\n BCROS = 'bcros',\n IDIR = 'idir',\n BCSC = 'bcsc',\n BCEID = 'bceid'\n}\n\nexport enum LoginSource {\n BCROS = 'BCROS',\n IDIR = 'IDIR',\n BCSC = 'BCSC',\n BCEID = 'BCEID'\n}\n\nexport enum Role {\n AccountHolder = 'account_holder',\n PublicUser = 'public_user',\n Staff = 'staff',\n GOVMAccountUser = 'gov_account_user'\n}\n\nexport enum Pages {\n HOME = 'home',\n USER_PROFILE = 'userprofile',\n ACCOUNT = 'account',\n SETTINGS = 'settings',\n SIGNIN = 'signin',\n USER_PROFILE_TERMS = 'userprofileterms',\n CREATE_ACCOUNT = 'setup-account',\n CHOOSE_AUTH_METHOD = 'choose-authentication-method',\n NON_BCSC_INSTRUCTIONS = 'nonbcsc-info/instructions',\n ACCOUNT_FREEZ = 'account-freeze',\n PENDING_APPROVAL = 'pendingapproval',\n ACCOUNT_SWITCHING = 'account-switching',\n REGISTRY_DASHBOARD = 'dashboard'\n}\n\nexport const ALLOWED_URIS_FOR_PENDING_ORGS: string[] = ['setup-non-bcsc-account', 'signout']\n\nexport const ACCOUNT_ID = 'accountid'\n","import ConfigHelper from './config-helper'\nimport { SessionStorageKeys, ACCOUNT_ID } from './constants'\n\n/**\n * Place to put all the custom utility methods\n */\nexport function getBoolean (value: boolean | string | number): boolean {\n let resultVal = value\n if (typeof value === 'string') {\n resultVal = value.toLowerCase()\n }\n switch (resultVal) {\n case true:\n case 'true':\n case 1:\n case '1':\n case 'on':\n case 'yes':\n case 'none':\n return true\n default:\n return false\n }\n}\n\nexport function decodeKCToken () {\n try {\n const token = ConfigHelper.getFromSession(SessionStorageKeys.KeyCloakToken)\n if (token) {\n const base64Url = token.split('.')[1]\n const base64 = decodeURIComponent(window.atob(base64Url).split('').map(function (c) {\n return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)\n }).join(''))\n return JSON.parse(base64)\n } else {\n return {}\n }\n } catch (error) {\n throw new Error('Error parsing JWT - ' + error)\n }\n}\n\nexport function trimTrailingSlashURL (url) {\n return (url) ? url.trim().replace(/\\/+$/, '') : ''\n}\n\nexport function getAccountIdFromCurrentUrl () {\n const urlParams = new URLSearchParams(window.location.search)\n return urlParams.get(ACCOUNT_ID) || false\n}\n\nexport function checkAndAppend (url, key = '', value = '') {\n const separator = (/\\?/).test(url) ? '&' : '?'\n // remove key from URL if existing\n const newUrl = removeAccountIdFromUrl(url, key)\n return (value !== '' && key !== '') ? `${newUrl}${separator}${key}=${value}` : url\n}\n\n// if account id is not passed, will get it from session\n// there are some cases we need to pass account id, ie to watch account id and get URL dynamically\nexport function appendAccountId (url, accountId = '') {\n const sessionAccountId = JSON.parse(ConfigHelper.getFromSession(SessionStorageKeys.CurrentAccount) || '{}').id || ''\n const currentAccount = accountId !== '' ? accountId : sessionAccountId\n return checkAndAppend(url, ACCOUNT_ID, currentAccount)\n}\n\nexport function removeAccountIdFromUrl (url, key = ACCOUNT_ID) {\n // replacing account id and formattig ie, removing extra ? or &\n return url?.replace(new RegExp(key + '=\\\\w+'), '').replace('?&', '?').replace(/\\?$/, '')\n .replace('&&', '&').replace(/&$/, '')\n}\n","import { SessionStorageKeys } from './constants'\nimport { trimTrailingSlashURL } from './common-util'\n\nexport default class ConfigHelper {\n static keycloakConfigUrl = ''\n\n static addToSession (key: string, value: any): void {\n sessionStorage.setItem(key, value)\n }\n\n static getFromSession (key: string): string | null {\n return sessionStorage.getItem(key)\n }\n\n static removeFromSession (key: string): void {\n sessionStorage.removeItem(key)\n }\n\n static clearSession (): void {\n sessionStorage.clear()\n }\n\n static getStatusAPIUrl (): string {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.StatusApiUrl) || '')\n }\n\n static getAuthAPIUrl (): string {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.AuthApiUrl) || '')\n }\n\n static getAuthContextPath (): string {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.AuthWebUrl) || '')\n }\n\n static getRegistryHomeURL () {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.RegistryHomeUrl) || '')\n }\n\n static getNameRequestURL () {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.NameRequestUrl) || '')\n }\n\n static getPprWebURL () {\n return trimTrailingSlashURL(sessionStorage.getItem(SessionStorageKeys.PprWebUrl) || '')\n }\n\n static setKeycloakConfigUrl (keycloakConfigUrl: string) {\n this.keycloakConfigUrl = keycloakConfigUrl\n }\n\n static getKeycloakConfigUrl (): string {\n return this.keycloakConfigUrl\n }\n}\n","var VuexModule = /** @class */ (function () {\r\n function VuexModule(module) {\r\n this.actions = module.actions;\r\n this.mutations = module.mutations;\r\n this.state = module.state;\r\n this.getters = module.getters;\r\n this.namespaced = module.namespaced;\r\n this.modules = module.modules;\r\n }\r\n return VuexModule;\r\n}());\r\nfunction getModule(moduleClass, store) {\r\n if (moduleClass._statics) {\r\n return moduleClass._statics;\r\n }\r\n var genStatic = moduleClass._genStatic;\r\n if (!genStatic) {\r\n throw new Error(\"ERR_GET_MODULE_NO_STATICS : Could not get module accessor.\\n Make sure your module has name, we can't make accessors for unnamed modules\\n i.e. @Module({ name: 'something' })\");\r\n }\r\n return (moduleClass._statics = genStatic(store));\r\n}\n\nvar reservedKeys = ['actions', 'getters', 'mutations', 'modules', 'state', 'namespaced', 'commit'];\r\nfunction stateFactory(module) {\r\n var state = new module.prototype.constructor({});\r\n var s = {};\r\n Object.keys(state).forEach(function (key) {\r\n if (reservedKeys.indexOf(key) !== -1) {\r\n if (typeof state[key] !== 'undefined') {\r\n throw new Error(\"ERR_RESERVED_STATE_KEY_USED: You cannot use the following\\n ['actions', 'getters', 'mutations', 'modules', 'state', 'namespaced', 'commit']\\n as fields in your module. These are reserved as they have special purpose in Vuex\");\r\n }\r\n return;\r\n }\r\n if (state.hasOwnProperty(key)) {\r\n if (typeof state[key] !== 'function') {\r\n s[key] = state[key];\r\n }\r\n }\r\n });\r\n return s;\r\n}\n\n/**\r\n * Takes the properties on object from parameter source and adds them to the object\r\n * parameter target\r\n * @param {object} target Object to have properties copied onto from y\r\n * @param {object} source Object with properties to be copied to x\r\n */\r\nfunction addPropertiesToObject(target, source) {\r\n var _loop_1 = function (k) {\r\n Object.defineProperty(target, k, {\r\n get: function () { return source[k]; }\r\n });\r\n };\r\n for (var _i = 0, _a = Object.keys(source || {}); _i < _a.length; _i++) {\r\n var k = _a[_i];\r\n _loop_1(k);\r\n }\r\n}\n\n/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n\r\nfunction __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nfunction __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\n\nfunction staticStateGenerator(module, modOpt, statics) {\r\n var state = modOpt.stateFactory ? module.state() : module.state;\r\n Object.keys(state).forEach(function (key) {\r\n if (state.hasOwnProperty(key)) {\r\n // If not undefined or function means it is a state value\r\n if (['undefined', 'function'].indexOf(typeof state[key]) === -1) {\r\n Object.defineProperty(statics, key, {\r\n get: function () {\r\n return modOpt.store.state[modOpt.name][key];\r\n }\r\n });\r\n }\r\n }\r\n });\r\n}\r\nfunction staticGetterGenerator(module, modOpt, statics) {\r\n Object.keys(module.getters).forEach(function (key) {\r\n if (module.namespaced) {\r\n Object.defineProperty(statics, key, {\r\n get: function () {\r\n return modOpt.store.getters[modOpt.name + \"/\" + key];\r\n }\r\n });\r\n }\r\n else {\r\n Object.defineProperty(statics, key, {\r\n get: function () {\r\n return modOpt.store.getters[key];\r\n }\r\n });\r\n }\r\n });\r\n}\r\nfunction staticMutationGenerator(module, modOpt, statics) {\r\n Object.keys(module.mutations).forEach(function (key) {\r\n if (module.namespaced) {\r\n statics[key] = function () {\r\n var _a;\r\n var args = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n args[_i] = arguments[_i];\r\n }\r\n (_a = modOpt.store).commit.apply(_a, [modOpt.name + \"/\" + key].concat(args));\r\n };\r\n }\r\n else {\r\n statics[key] = function () {\r\n var _a;\r\n var args = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n args[_i] = arguments[_i];\r\n }\r\n (_a = modOpt.store).commit.apply(_a, [key].concat(args));\r\n };\r\n }\r\n });\r\n}\r\nfunction staticActionGenerators(module, modOpt, statics) {\r\n Object.keys(module.actions).forEach(function (key) {\r\n if (module.namespaced) {\r\n statics[key] = function () {\r\n var args = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n args[_i] = arguments[_i];\r\n }\r\n return __awaiter(this, void 0, void 0, function () {\r\n var _a;\r\n return __generator(this, function (_b) {\r\n return [2 /*return*/, (_a = modOpt.store).dispatch.apply(_a, [modOpt.name + \"/\" + key].concat(args))];\r\n });\r\n });\r\n };\r\n }\r\n else {\r\n statics[key] = function () {\r\n var args = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n args[_i] = arguments[_i];\r\n }\r\n return __awaiter(this, void 0, void 0, function () {\r\n var _a;\r\n return __generator(this, function (_b) {\r\n return [2 /*return*/, (_a = modOpt.store).dispatch.apply(_a, [key].concat(args))];\r\n });\r\n });\r\n };\r\n }\r\n });\r\n}\n\nfunction moduleDecoratorFactory(moduleOptions) {\r\n return function (constructor) {\r\n var module = constructor;\r\n var stateFactory$1 = function () { return stateFactory(module); };\r\n if (!module.state) {\r\n module.state = moduleOptions && moduleOptions.stateFactory ? stateFactory$1 : stateFactory$1();\r\n }\r\n if (!module.getters) {\r\n module.getters = {};\r\n }\r\n if (!module.namespaced) {\r\n module.namespaced = moduleOptions && moduleOptions.namespaced;\r\n }\r\n Object.getOwnPropertyNames(module.prototype).forEach(function (funcName) {\r\n var descriptor = Object.getOwnPropertyDescriptor(module.prototype, funcName);\r\n if (descriptor.get && module.getters) {\r\n module.getters[funcName] = function (state, getters, rootState, rootGetters) {\r\n var thisObj = { context: { state: state, getters: getters, rootState: rootState, rootGetters: rootGetters } };\r\n addPropertiesToObject(thisObj, state);\r\n addPropertiesToObject(thisObj, getters);\r\n var got = descriptor.get.call(thisObj);\r\n return got;\r\n };\r\n }\r\n });\r\n var modOpt = moduleOptions;\r\n if (modOpt.name) {\r\n Object.defineProperty(constructor, '_genStatic', {\r\n value: function (store) {\r\n var statics = {};\r\n modOpt.store = modOpt.store || store;\r\n if (!modOpt.store) {\r\n throw new Error(\"ERR_STORE_NOT_PROVIDED: To use getModule(), either the module\\n should be decorated with store in decorator, i.e. @Module({store: store}) or\\n store should be passed when calling getModule(), i.e. getModule(MyModule, this.$store)\");\r\n }\r\n // =========== For statics ==============\r\n // ------ state -------\r\n staticStateGenerator(module, modOpt, statics);\r\n // ------- getters -------\r\n if (module.getters) {\r\n staticGetterGenerator(module, modOpt, statics);\r\n }\r\n // -------- mutations --------\r\n if (module.mutations) {\r\n staticMutationGenerator(module, modOpt, statics);\r\n }\r\n // -------- actions ---------\r\n if (module.actions) {\r\n staticActionGenerators(module, modOpt, statics);\r\n }\r\n return statics;\r\n }\r\n });\r\n }\r\n if (modOpt.dynamic) {\r\n if (!modOpt.name) {\r\n throw new Error('Name of module not provided in decorator options');\r\n }\r\n modOpt.store.registerModule(modOpt.name, // TODO: Handle nested modules too in future\r\n module);\r\n }\r\n return constructor;\r\n };\r\n}\r\nfunction Module(modOrOpt) {\r\n if (typeof modOrOpt === 'function') {\r\n /*\r\n * @Module decorator called without options (directly on the class definition)\r\n */\r\n moduleDecoratorFactory({})(modOrOpt);\r\n }\r\n else {\r\n /*\r\n * @Module({...}) decorator called with options\r\n */\r\n return moduleDecoratorFactory(modOrOpt);\r\n }\r\n}\n\nfunction actionDecoratorFactory(params) {\r\n var _a = params || {}, _b = _a.commit, commit = _b === void 0 ? undefined : _b, _c = _a.rawError, rawError = _c === void 0 ? false : _c, _d = _a.root, root = _d === void 0 ? false : _d;\r\n return function (target, key, descriptor) {\r\n var module = target.constructor;\r\n if (!module.actions) {\r\n module.actions = {};\r\n }\r\n var actionFunction = descriptor.value;\r\n var action = function (context, payload) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var actionPayload, moduleAccessor, thisObj, e_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n _a.trys.push([0, 5, , 6]);\r\n actionPayload = null;\r\n if (!module._genStatic) return [3 /*break*/, 2];\r\n moduleAccessor = getModule(module);\r\n moduleAccessor.context = context;\r\n return [4 /*yield*/, actionFunction.call(moduleAccessor, payload)];\r\n case 1:\r\n actionPayload = _a.sent();\r\n return [3 /*break*/, 4];\r\n case 2:\r\n thisObj = { context: context };\r\n addPropertiesToObject(thisObj, context.state);\r\n addPropertiesToObject(thisObj, context.getters);\r\n return [4 /*yield*/, actionFunction.call(thisObj, payload)];\r\n case 3:\r\n actionPayload = _a.sent();\r\n _a.label = 4;\r\n case 4:\r\n if (commit) {\r\n context.commit(commit, actionPayload);\r\n }\r\n return [2 /*return*/, actionPayload];\r\n case 5:\r\n e_1 = _a.sent();\r\n throw rawError\r\n ? e_1\r\n : new Error('ERR_ACTION_ACCESS_UNDEFINED: Are you trying to access ' +\r\n 'this.someMutation() or this.someGetter inside an @Action? \\n' +\r\n 'That works only in dynamic modules. \\n' +\r\n 'If not dynamic use this.context.commit(\"mutationName\", payload) ' +\r\n 'and this.context.getters[\"getterName\"]' +\r\n '\\n' +\r\n new Error(\"Could not perform action \" + key.toString()).stack +\r\n '\\n' +\r\n e_1.stack);\r\n case 6: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n module.actions[key] = root ? { root: root, handler: action } : action;\r\n };\r\n}\r\n/**\r\n * The @Action decorator turns an async function into an Vuex action\r\n *\r\n * @param targetOrParams the module class\r\n * @param key name of the action\r\n * @param descriptor the action function descriptor\r\n * @constructor\r\n */\r\nfunction Action(targetOrParams, key, descriptor) {\r\n if (!key && !descriptor) {\r\n /*\r\n * This is the case when `targetOrParams` is params.\r\n * i.e. when used as -\r\n * \r\n @Action({commit: 'incrCount'})\r\n async getCountDelta() {\r\n return 5\r\n }\r\n * \r\n */\r\n return actionDecoratorFactory(targetOrParams);\r\n }\r\n else {\r\n /*\r\n * This is the case when @Action is called on action function\r\n * without any params\r\n * \r\n * @Action\r\n * async doSomething() {\r\n * ...\r\n * }\r\n * \r\n */\r\n actionDecoratorFactory()(targetOrParams, key, descriptor);\r\n }\r\n}\n\nfunction Mutation(target, key, descriptor) {\r\n var module = target.constructor;\r\n if (!module.mutations) {\r\n module.mutations = {};\r\n }\r\n var mutationFunction = descriptor.value ? descriptor.value : function () {\r\n var args = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n args[_i] = arguments[_i];\r\n }\r\n return ({});\r\n };\r\n var mutation = function (state, payload) {\r\n mutationFunction.call(state, payload);\r\n };\r\n module.mutations[key] = mutation;\r\n}\n\nfunction mutationActionDecoratorFactory(params) {\r\n return function (target, key, descriptor) {\r\n var module = target.constructor;\r\n if (!module.mutations) {\r\n module.mutations = {};\r\n }\r\n if (!module.actions) {\r\n module.actions = {};\r\n }\r\n var mutactFunction = descriptor.value;\r\n var action = function (context, payload) {\r\n return __awaiter(this, void 0, void 0, function () {\r\n var actionPayload, e_1;\r\n return __generator(this, function (_a) {\r\n switch (_a.label) {\r\n case 0:\r\n _a.trys.push([0, 2, , 3]);\r\n return [4 /*yield*/, mutactFunction.call(context, payload)];\r\n case 1:\r\n actionPayload = _a.sent();\r\n context.commit(key, actionPayload);\r\n return [3 /*break*/, 3];\r\n case 2:\r\n e_1 = _a.sent();\r\n if (params.rawError) {\r\n throw e_1;\r\n }\r\n else {\r\n console.error('Could not perform action ' + key.toString());\r\n console.error(e_1);\r\n }\r\n return [3 /*break*/, 3];\r\n case 3: return [2 /*return*/];\r\n }\r\n });\r\n });\r\n };\r\n var mutation = function (state, payload) {\r\n if (!params.mutate) {\r\n params.mutate = Object.keys(payload);\r\n }\r\n for (var _i = 0, _a = params.mutate; _i < _a.length; _i++) {\r\n var stateItem = _a[_i];\r\n if (state.hasOwnProperty(stateItem) && payload.hasOwnProperty(stateItem)) {\r\n state[stateItem] = payload[stateItem];\r\n }\r\n else {\r\n throw new Error(\"ERR_MUTATE_PARAMS_NOT_IN_PAYLOAD\\n In @MutationAction, mutate: ['a', 'b', ...] array keys must\\n match with return type = {a: {}, b: {}, ...} and must\\n also be in state.\");\r\n }\r\n }\r\n };\r\n module.actions[key] = params.root ? { root: true, handler: action } : action;\r\n module.mutations[key] = mutation;\r\n };\r\n}\r\n/**\r\n * The @MutationAction decorator turns this into an action that further calls a mutation\r\n * Both the action and the mutation are generated for you\r\n *\r\n * @param paramsOrTarget the params or the target class\r\n * @param key the name of the function\r\n * @param descriptor the function body\r\n * @constructor\r\n */\r\nfunction MutationAction(paramsOrTarget, key, descriptor) {\r\n if (!key && !descriptor) {\r\n /*\r\n * This is the case when `paramsOrTarget` is params.\r\n * i.e. when used as -\r\n * \r\n @MutationAction({mutate: ['incrCount']})\r\n async getCountDelta() {\r\n return {incrCount: 5}\r\n }\r\n * \r\n */\r\n return mutationActionDecoratorFactory(paramsOrTarget);\r\n }\r\n else {\r\n /*\r\n * This is the case when `paramsOrTarget` is target.\r\n * i.e. when used as -\r\n * \r\n @MutationAction\r\n async getCountDelta() {\r\n return {incrCount: 5}\r\n }\r\n * \r\n */\r\n mutationActionDecoratorFactory({})(paramsOrTarget, key, descriptor);\r\n }\r\n}\n\nexport { Action, Module, Mutation, MutationAction, VuexModule, getModule };\n//# sourceMappingURL=index.js.map\n","import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'\nimport ConfigHelper from '../../util/config-helper'\nimport KeycloakServices from '../../services/keycloak.services'\nimport { SessionStorageKeys } from '../../util/constants'\n\n@Module({\n name: 'auth',\n namespaced: true\n})\nexport default class AuthModule extends VuexModule {\n token: string = ''\n idToken: string = ''\n refreshToken: string = ''\n kcGuid: string = ''\n loginSource: string = ''\n\n get isAuthenticated (): boolean {\n return !!this.token\n }\n\n get keycloakGuid (): string {\n return this.kcGuid || KeycloakServices.getUserInfo().keycloakGuid\n }\n\n get currentLoginSource (): string {\n return this.loginSource || KeycloakServices.getUserInfo().loginSource\n }\n\n @Mutation\n public setKCToken (token: string): void {\n this.token = token\n ConfigHelper.addToSession(SessionStorageKeys.KeyCloakToken, token)\n }\n\n @Mutation\n public setIDToken (idToken: string): void {\n this.idToken = idToken\n ConfigHelper.addToSession(SessionStorageKeys.KeyCloakIdToken, idToken)\n }\n\n @Mutation\n public setRefreshToken (refreshToken: string): void {\n this.refreshToken = refreshToken\n ConfigHelper.addToSession(SessionStorageKeys.KeyCloakRefreshToken, refreshToken)\n }\n\n @Mutation\n public setKCGuid (kcGuid: string): void {\n this.kcGuid = kcGuid\n }\n\n @Mutation\n public setLoginSource (loginSource: string): void {\n this.loginSource = loginSource\n }\n\n @Action({ rawError: true })\n public clearSession (): void {\n this.context.commit('setKCToken', '')\n this.context.commit('setIDToken', '')\n this.context.commit('setRefreshToken', '')\n this.context.commit('setKCGuid', '')\n this.context.commit('setLoginSource', '')\n }\n\n @Action({ rawError: true })\n public syncWithSessionStorage (): void {\n this.context.commit('setKCToken', ConfigHelper.getFromSession(SessionStorageKeys.KeyCloakToken) || '')\n this.context.commit('setIDToken', ConfigHelper.getFromSession(SessionStorageKeys.KeyCloakIdToken) || '')\n this.context.commit('setRefreshToken', ConfigHelper.getFromSession(SessionStorageKeys.KeyCloakRefreshToken) || '')\n }\n}\n","import Keycloak, { KeycloakInitOptions, KeycloakInstance, KeycloakLoginOptions, KeycloakTokenParsed } from 'keycloak-js'\nimport { KCUserProfile } from '../models/KCUserProfile'\nimport ConfigHelper from '../util/config-helper'\nimport { SessionStorageKeys } from '../util/constants'\nimport { Store } from 'vuex'\nimport { getModule } from 'vuex-module-decorators'\nimport AuthModule from '../store/modules/auth'\nimport { decodeKCToken } from '../util/common-util'\n\nclass KeyCloakService {\n private kc: KeycloakInstance | undefined\n private parsedToken: any\n private static instance: KeyCloakService\n private store: Store([])\r\n\r\nexport const useCodes = () => {\r\n const getRoutingSlipStatusList = async () => {\r\n if (routingSlipStatusList.value.length === 0) {\r\n const response: any = await CodesService.getCodes(\r\n 'routing_slip_statuses'\r\n )\r\n if (response && response.data && response.status === 200) {\r\n routingSlipStatusList.value = response.data?.codes.filter(\r\n code => code.code !== SlipStatus.REFUNDREJECTED\r\n )\r\n return\r\n }\r\n routingSlipStatusList.value = []\r\n }\r\n }\r\n return {\r\n routingSlipStatusList,\r\n getRoutingSlipStatusList\r\n }\r\n}\r\n","import { Code } from '@/models/Code'\r\nimport { SlipStatus } from '@/util/constants'\r\nimport { ref, computed, toRefs, onMounted } from '@vue/composition-api'\r\nimport { useCodes } from '../useCodes'\r\n\r\nexport function useStatusList (props, context) {\r\n const { getRoutingSlipStatusList, routingSlipStatusList } = useCodes()\r\n // default value set blank incase if we didnt pass props\r\n const { value = ref('') } = toRefs(props)\r\n\r\n // using same v-model value for getting value and update parent on change\r\n const currentStatus = computed({\r\n get: () => {\r\n return value.value || ''\r\n },\r\n set: (modalValue: Code) => {\r\n context.emit('input', modalValue.code)\r\n }\r\n })\r\n\r\n onMounted(() => {\r\n // getting status list mouint and setting inside store\r\n // will make call once till page refresh\r\n getRoutingSlipStatusList()\r\n })\r\n\r\n /**\r\n * return status label on code\r\n *\r\n * @param {string} code\r\n * @returns {string} description - label\r\n */\r\n function statusLabel (code: string) {\r\n const codeArray = selectedStatusObject(code)\r\n return codeArray[0]?.description || ''\r\n }\r\n\r\n /**\r\n * filtering array and find given value of object\r\n * use full when needed to set object of status\r\n * @param {string} code\r\n * @returns [{code, description}]\r\n */\r\n\r\n function selectedStatusObject (code: string) {\r\n return routingSlipStatusList.value?.filter(\r\n statusList => statusList.code === code\r\n )\r\n }\r\n\r\n return {\r\n routingSlipStatusList,\r\n currentStatus,\r\n statusLabel,\r\n selectedStatusObject\r\n }\r\n}\r\n","import { AxiosResponse } from 'axios'\r\nimport CommonUtils from '@/util/common-util'\r\nimport ConfigHelper from '@/util/config-helper'\r\nimport { GetFeeRequestParams, Payment } from '@/models/Payment'\r\nimport { LinkRoutingSlipPrams } from '@/models/RoutingSlip'\r\nimport axios from '@/util/http-util'\r\nimport { CreateRoutingSlipStatus, PatchActions, SlipStatus } from '@/util/constants'\r\n\r\nexport default class RoutingSlip {\r\n public static async getRoutingSlip (\r\n routingNumber: string,\r\n showGlobalLoader: boolean = false\r\n ): Promise\r\n {{ isLibraryMode ? 'Recent Routing Slip' : 'Search Routing Slip' }}\r\n
\r\n \r\n \r\n\r\n \r\n {{ header.text }}\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {{ item.number ? item.number : '-' }}\r\n \r\n \r\n \r\n {{\r\n item.paymentAccount &&\r\n item.paymentAccount.paymentMethod === 'CASH'\r\n ? item.payments &&\r\n item.payments[0] &&\r\n item.payments[0].chequeReceiptNumber\r\n : '-'\r\n }}\r\n \r\n \r\n {{ item.paymentAccount.accountName ? item.paymentAccount.accountName : '-' }}\r\n \r\n \r\n {{ item.createdName ? item.createdName : '-' }}\r\n \r\n \r\n {{\r\n item.routingSlipDate\r\n ? formatDisplayDate(\r\n item.routingSlipDate,\r\n 'MMMM DD, YYYY'\r\n )\r\n : '-'\r\n }}\r\n \r\n \r\n {{\r\n getStatusLabel(item.status)\r\n ? getStatusLabel(item.status)\r\n : '-'\r\n }}\r\n \r\n \r\n \r\n {{ item.refundStatus ? getRefundStatusText(item.refundStatus) : '-' }}\r\n \r\n \r\n \r\n 0 &&\r\n !showExpandedFolio.includes(item.id)\r\n \"\r\n @click=\"toggleFolio(item.id)\"\r\n class=\"cursor-pointer\"\r\n >\r\n {{ formatFolioResult(item)[0] }}\r\n \r\n \r\n \r\n 0 &&\r\n !showExpandedCheque.includes(\r\n item.payments[0].chequeReceiptNumber\r\n )\r\n \"\r\n @click=\"\r\n toggleCheque(\r\n item.payments[0].chequeReceiptNumber\r\n )\r\n \"\r\n class=\"cursor-pointer\"\r\n >\r\n {{ item.payments[0].chequeReceiptNumber }}\r\n \r\n \r\n \r\n {{\r\n item.remainingAmount\r\n ? appendCurrencySymbol(item.remainingAmount.toFixed(2))\r\n : '-'\r\n }}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \n {{ isLibraryMode ? 'Recent Routing Slip' : 'Search Routing Slip' }}\n
\n \n \n\n \n {{ header.text }}\n \n \n \n \n \n\n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {{ item.number ? item.number : '-' }}\n \n \n \n {{\n item.paymentAccount &&\n item.paymentAccount.paymentMethod === 'CASH'\n ? item.payments &&\n item.payments[0] &&\n item.payments[0].chequeReceiptNumber\n : '-'\n }}\n \n \n {{ item.paymentAccount.accountName ? item.paymentAccount.accountName : '-' }}\n \n \n {{ item.createdName ? item.createdName : '-' }}\n \n \n {{\n item.routingSlipDate\n ? formatDisplayDate(\n item.routingSlipDate,\n 'MMMM DD, YYYY'\n )\n : '-'\n }}\n \n \n {{\n getStatusLabel(item.status)\n ? getStatusLabel(item.status)\n : '-'\n }}\n \n \n \n {{ item.refundStatus ? getRefundStatusText(item.refundStatus) : '-' }}\n \n \n \n 0 &&\n !showExpandedFolio.includes(item.id)\n \"\n @click=\"toggleFolio(item.id)\"\n class=\"cursor-pointer\"\n >\n {{ formatFolioResult(item)[0] }}\n \n \n \n 0 &&\n !showExpandedCheque.includes(\n item.payments[0].chequeReceiptNumber\n )\n \"\n @click=\"\n toggleCheque(\n item.payments[0].chequeReceiptNumber\n )\n \"\n class=\"cursor-pointer\"\n >\n {{ item.payments[0].chequeReceiptNumber }}\n \n \n \n {{\n item.remainingAmount\n ? appendCurrencySymbol(item.remainingAmount.toFixed(2))\n : '-'\n }}\n \n \n \n \n \n \n \n \n \n 1?t.substring(0,2).toLowerCase():"en",n.messages[r.language]||(r.language="en")},r.setCulture=function(n){r.options.culture=n,r.reload()},r.setWidth=function(n){r.autocomplete.setWidth(n),r.countrylist.autocomplete.setWidth(n)},r.setHeight=function(n){r.autocomplete.setHeight(n),r.countrylist.autocomplete.setHeight(n)},r.clear=function(){for(var t=0;tFAS Staff Dashboard
-
- {{ isLibraryMode ? 'Recent Routing Slip' : 'Search Routing Slip' }}
-
-
-
-
-
- {{ header.text }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ item.number ? item.number : '-' }}
-
-
-
- {{
- item.paymentAccount &&
- item.paymentAccount.paymentMethod === 'CASH'
- ? item.payments &&
- item.payments[0] &&
- item.payments[0].chequeReceiptNumber
- : '-'
- }}
-
-
- {{ item.paymentAccount.accountName ? item.paymentAccount.accountName : '-' }}
-
-
- {{ item.createdName ? item.createdName : '-' }}
-
-
- {{
- item.routingSlipDate
- ? formatDisplayDate(
- item.routingSlipDate,
- 'MMMM DD, YYYY'
- )
- : '-'
- }}
-
-
- {{
- getStatusLabel(item.status)
- ? getStatusLabel(item.status)
- : '-'
- }}
-
-
-
- {{ item.refundStatus ? getRefundStatusText(item.refundStatus) : '-' }}
-
-
-
-
- {{ formatFolioResult(item)[0] }}
-
-
-
-
- {{ item.payments[0].chequeReceiptNumber }}
-
-
-
- {{
- item.remainingAmount
- ? appendCurrencySymbol(item.remainingAmount.toFixed(2))
- : '-'
- }}
-
-
-
-
-
-
-
-
-
- Add Routing Slip
- {{ isReviewMode ? "Review New Routing Slip" : "Add New Routing Slip" }}
-
- {{ title }}
-
-
-
-
-
-
-
-
-
- {{ dropdownItem.type }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Application
-
-
- Type
-
-
- Number
-
-
- Detail
-
-
-
-
-
-
- {{transactionData.applicationName}}
-
-
- {{transactionData.applicationType}}
-
-
- {{transactionData.businessIdentifier}}
-
-
-
-
-
-
-
-
-
- Transaction ID
-
-
- Invoice Reference ID
-
-
-
-
-
-
- {{transactionData.invoiceId}}
-
-
- {{transactionData.invoiceReferenceId}}
-
- Linking Routing Slip
- Linked routing slip
-
- Payment Information
- Routing Slip Information
- Routing Slip Transaction
- {{ summary }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page {{ tableDataOptions.page }}
-
-
-
-
- EFT Enabled Accounts
-
- ({{ totalResults }})
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ shortNameDetails.shortName }}
-
-
- Search by Account ID or Name to Link:
-
-
- Payment Information
-
-
-
-
-
-
- {{ formatDate(item.createdOn, dateDisplayFormat) }}
-
-
- {{ formatDescription(item) }}
-
- Refund Information
-
-
- Refund Information
-
-
- All Short Names
-
- ({{ totalResults }})
-
-
-
-
- {{ item.shortName }}
-
-
- (null)
- const errorMessage = ref([])
-const paymentMethods = refNo Results
Click on the routing slip number above to access to the linked routing slip.",
- "linkRSSearchInfo": "When you link to another routing slip, this routing slip’s total balance will transfer to the linked routing slip. After linking to another routing slip this routing slip will be inactive.",
- "linkRoutingSlipSearchTitleParent": "This routing slip is linked with:",
- "linkRoutingSlipSearchTitleChild": "This routing slip has been linked to:",
- "addManualTransactionQuantityInfoText": "The priority or future effective fee will only be applied once. Input transactions separately to add additional fee",
- "cantLinkSinceInvoicesExistMsg": "This routing slip cannot link to another routing slip since transactions were made.
Other routing slips can link to this routing slip",
- "cantLinkBecauseVoidedMsg": "This routing slip cannot link to another routing slip since it is voided.",
- "cantAddTransactions": "Transaction can't be added, since the filling type total amount exceeds the routing slip's current balance",
- "reviewRoutingSlipText": "Manage, and review details for this routing slip",
- "NSFWarningText":"By placing status to NSF, this routing slip will not be usable, and current transactions will change to pending until it has been repaid by having another slip linked to it.",
- "NSFWarningTitle":"Place Routing Slip to NSF?",
- "WriteOffWarningTitle":"Authorize Write-off?",
- "WriteOffWarningText":"By approving write-off, the routing slip balance will close, and no further transactions may be made using this routing slip.",
- "VoidWarningTitle": "Void Routing Slip?",
- "VoidWarningText": "By placing status to void, this routing slip will not be usable, and this action cannot be undone."
-}
diff --git a/src/locales/fr.json b/src/locales/fr.json
deleted file mode 100644
index a7b07f86..00000000
--- a/src/locales/fr.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "message": "Hello French i18n !!",
- "test": "French"
-}
diff --git a/src/main.ts b/src/main.ts
deleted file mode 100644
index 207738f8..00000000
--- a/src/main.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/* eslint-disable */
-
-import '@mdi/font/css/materialdesignicons.min.css' // icon library (https://materialdesignicons.com/)
-import './shims-vue-composition-api'
-
-import App from './App.vue'
-import CommonUtils from '@/util/common-util'
-import ConfigHelper from '@/util/config-helper'
-import KeyCloakService from 'sbc-common-components/src/services/keycloak.services'
-import LaunchDarklyService from 'sbc-common-components/src/services/launchdarkly.services'
-import Vue from 'vue'
-import VueCompositionAPI from '@vue/composition-api'
-import VueGtag from 'vue-gtag'
-import VueSanitize from 'vue-sanitize-directive'
-import Vuelidate from 'vuelidate'
-import can from '@/directives/can'
-import initializeI18n from './plugins/i18n'
-import router from './router'
-import { getPiniaStore } from './store'
-import vuetify from './plugins/vuetify'
-
-Vue.config.productionTip = false
-
-Vue.use(Vuelidate)
-Vue.use(VueCompositionAPI)
-const i18n = initializeI18n(Vue)
-Vue.use(VueSanitize)
-
-if (import.meta.env.VUE_APP_GTAG_ID) {
- Vue.use(VueGtag, {
- config: {
- id: import.meta.env.VUE_APP_GTAG_ID
- }
- }, router)
-}
-/**
- * The server side configs are necessary for app to work , since they are reference in templates and all
- */
-ConfigHelper.saveConfigToSessionStorage().then(async () => {
- // Initializing Launch Darkly services
- await LaunchDarklyService.init(ConfigHelper.getLdClientId());
-
- // addressCompleteKey is for canada post address lookup, which is to be used in sbc-common-components
- (
`, ''),
- minWidth: '200px',
- value: 'Transaction Type'
- },
- {
- col: 'details',
- customFilter: {
- clearable: true,
- label: 'Transaction Details',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- itemFn: (val: Transaction) => val.details?.reduce((resp, detail) => `${resp}${detail.label || ''} ${detail.value}
`, '') || 'N/A',
- minWidth: '200px',
- value: 'Transaction Details'
- },
- {
- col: 'businessIdentifier',
- customFilter: {
- clearable: true,
- label: 'Number',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- itemFn: (val: Transaction) => val.businessIdentifier || 'N/A',
- minWidth: '200px',
- value: 'Number'
- },
- {
- col: 'folioNumber',
- customFilter: {
- clearable: true,
- label: 'Folio #',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- minWidth: '125px',
- value: 'Folio #'
- },
- {
- col: 'createdName',
- customFilter: {
- clearable: true,
- label: 'Initiated by',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- itemFn: (val: Transaction) => (val.createdName === 'None None') ? '-' : val.createdName,
- minWidth: '155px',
- value: 'Initiated by'
- },
- {
- col: 'createdOn',
- hasFilter: false,
- itemFn: (val: Transaction) => {
- // Example format: 2023-03-11T00:55:05.909229 without timezone
- const createdOn = moment.utc(val.createdOn).toDate()
- return CommonUtils.formatDisplayDateInPacific(createdOn, 'MMMM DD, YYYY
h:mm A')
- },
- minWidth: '165px',
- value: 'Date (Pacific Time)'
- },
- {
- col: 'total',
- hasFilter: false,
- itemClass: 'font-weight-bold',
- minWidth: '135px',
- value: 'Total Amount'
- },
- {
- col: 'id',
- customFilter: {
- clearable: true,
- label: 'Transaction ID',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- minWidth: '175px',
- value: 'Transaction ID'
- },
- {
- col: 'invoiceNumber',
- customFilter: {
- clearable: true,
- label: 'Reference Number',
- type: 'text',
- value: ''
- },
- hasFilter: true,
- minWidth: '250px',
- value: 'Invoice Reference Number'
- },
- {
- col: 'paymentMethod',
- customFilter: {
- clearable: true,
- items: [
- { text: paymentTypeDisplay[PaymentTypes.BCOL], value: PaymentTypes.BCOL },
- { text: paymentTypeDisplay[PaymentTypes.CREDIT_CARD], value: PaymentTypes.CREDIT_CARD },
- { text: paymentTypeDisplay[PaymentTypes.DIRECT_PAY], value: PaymentTypes.DIRECT_PAY },
- { text: paymentTypeDisplay[PaymentTypes.EJV], value: PaymentTypes.EJV },
- { text: paymentTypeDisplay[PaymentTypes.ONLINE_BANKING], value: PaymentTypes.ONLINE_BANKING },
- { text: paymentTypeDisplay[PaymentTypes.PAD], value: PaymentTypes.PAD },
- { text: paymentTypeDisplay[PaymentTypes.CREDIT], value: PaymentTypes.CREDIT },
- { text: paymentTypeDisplay[PaymentTypes.INTERNAL], value: PaymentTypes.INTERNAL },
- { text: paymentTypeDisplay[PaymentTypes.NO_FEE], value: PaymentTypes.NO_FEE }
- ],
- label: 'Payment Method',
- type: 'select',
- value: ''
- },
- hasFilter: true,
- itemFn: (val: Transaction) => {
- if (val.total === 0 && val.paymentMethod === PaymentTypes.INTERNAL) {
- return paymentTypeDisplay[PaymentTypes.NO_FEE]
- }
-
- if (val.appliedCredits?.length > 0) {
- const totalAppliedCredits = val.appliedCredits.reduce((sum, credit) => sum + credit.amountApplied, 0)
- const remainingAmount = val.total - totalAppliedCredits
- if (remainingAmount > 0) {
- if (val.paymentMethod === PaymentTypes.PAD) {
- return `${paymentTypeDisplay[PaymentTypes.CREDIT]} and ${paymentTypeDisplay[PaymentTypes.PAD]}`
- } else if (val.paymentMethod === PaymentTypes.ONLINE_BANKING) {
- return `${paymentTypeDisplay[PaymentTypes.CREDIT]} and ${paymentTypeDisplay[PaymentTypes.ONLINE_BANKING]}`
- }
- } else {
- return paymentTypeDisplay[PaymentTypes.CREDIT]
- }
- }
-
- return paymentTypeDisplay[val.paymentMethod]
- },
- minWidth: '185px',
- value: 'Payment Method'
- },
- {
- col: 'statusCode',
- customFilter: {
- clearable: true,
- items: [
- { text: invoiceStatusDisplay[InvoiceStatus.CANCELLED], value: InvoiceStatus.CANCELLED },
- { text: invoiceStatusDisplay[InvoiceStatus.PAID], value: InvoiceStatus.PAID },
- { text: invoiceStatusDisplay[InvoiceStatus.CREATED], value: InvoiceStatus.CREATED },
- { text: invoiceStatusDisplay[InvoiceStatus.CREDITED], value: InvoiceStatus.CREDITED },
- { text: invoiceStatusDisplay[InvoiceStatus.PENDING], value: InvoiceStatus.PENDING },
- { text: invoiceStatusDisplay[InvoiceStatus.APPROVED], value: InvoiceStatus.APPROVED },
- { text: invoiceStatusDisplay[InvoiceStatus.REFUNDED], value: InvoiceStatus.REFUNDED },
- { text: invoiceStatusDisplay[InvoiceStatus.REFUND_REQUESTED], value: InvoiceStatus.REFUND_REQUESTED },
- // These are FE only on the backend they are PAID
- { text: invoiceStatusDisplay[InvoiceStatus.PARTIALLY_CREDITED], value: InvoiceStatus.PARTIALLY_CREDITED },
- { text: invoiceStatusDisplay[InvoiceStatus.PARTIALLY_REFUNDED], value: InvoiceStatus.PARTIALLY_REFUNDED }
- ],
- label: 'Status',
- type: 'select',
- value: ''
- },
- itemFn: (val: Transaction) => {
- // Special case for Online Banking - it shouldn't show NSF, should show Pending.
- if (val.paymentMethod === PaymentTypes.ONLINE_BANKING &&
- val.statusCode === InvoiceStatus.SETTLEMENT_SCHEDULED) {
- return invoiceStatusDisplay[InvoiceStatus.PENDING]
- }
- return invoiceStatusDisplay[val.statusCode]
- },
- hasFilter: true,
- minWidth: '195px',
- value: 'Payment Status'
- },
- {
- col: 'actions',
- hasFilter: false,
- minWidth: '200px',
- value: '',
- width: '200px'
- },
- {
- col: 'downloads',
- hasFilter: false,
- itemClass: 'line-item',
- width: '164px',
- value: 'Downloads'
- }
-]
diff --git a/src/resources/table-headers/transactions-table/index.ts b/src/resources/table-headers/transactions-table/index.ts
deleted file mode 100644
index c5ebd6fd..00000000
--- a/src/resources/table-headers/transactions-table/index.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { BaseTableHeaderI } from '@/components/datatable/interfaces'
-import { TransactionTableHeaders } from './headers'
-
-export const getTransactionTableHeaders = (extended = false): BaseTableHeaderI[] => {
- const headers: BaseTableHeaderI[] = []
- // values + order of headers wanted. NOTE: '' is for the actions header
- let headerTitles = []
- if (extended) {
- headerTitles = ['accountName', 'product', 'lineItems', 'details', 'businessIdentifier', 'folioNumber',
- 'createdName', 'createdOn', 'total', 'id', 'invoiceNumber', 'paymentMethod', 'statusCode', 'downloads', 'actions']
- } else {
- headerTitles = ['lineItemsAndDetails', 'folioNumber', 'createdName', 'createdOn',
- 'total', 'id', 'invoiceNumber', 'paymentMethod', 'statusCode', 'downloads', 'actions']
- }
-
- for (const i in headerTitles) {
- headers.push(TransactionTableHeaders.find((header) => header.col === headerTitles[i]))
- }
-
- return headers
-}
diff --git a/src/router/index.ts b/src/router/index.ts
deleted file mode 100644
index 0e4d734e..00000000
--- a/src/router/index.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import KeyCloakService from 'sbc-common-components/src/services/keycloak.services'
-import Vue from 'vue'
-import VueRouter from 'vue-router'
-import { SessionStorageKeys } from '@/util/constants'
-import routes from './routes'
-
-Vue.use(VueRouter)
-
-const router = new VueRouter({
- mode: 'history',
- base: import.meta.env.BASE_URL,
- routes
-})
-
-router.beforeEach((to, from, next) => {
- // If the user is authenticated;
- // If there are allowed or disabled roles specified on the route check if the user has those roles else route to unauthorized
- // If the user is not authenticated
- // Redirect the user to unauthorized page
- if (to.matched.some(record => record.meta.requiresAuth)) {
- if (!sessionStorage.getItem(SessionStorageKeys.KeyCloakToken) || !KeyCloakService.verifyRoles(to.meta.allowedRoles, [])) {
- return next({
- path: '/unauthorized'
- })
- }
- }
- next()
-})
-
-export default router
diff --git a/src/router/routes.ts b/src/router/routes.ts
deleted file mode 100644
index 2a5baebc..00000000
--- a/src/router/routes.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-import CreateRoutingSlipView from '../views/CreateRoutingSlipView.vue'
-import Dashboard from '../views/Dashboard.vue'
-import PageNotFound from '../views/PageNotFound.vue'
-import { EFTRefundMethod, Role, RouteNames } from '@/util/constants'
-import { RouteConfig } from 'vue-router'
-import SigninView from '@/views/auth/SigninView.vue'
-import SignoutView from '@/views/auth/SignoutView.vue'
-import ShortNameMappingView from '@/views/eft/ShortNameMappingView.vue'
-import Unauthorized from '@/views/Unauthorized.vue'
-import ViewRoutingSlip from '../views/ViewRoutingSlip.vue'
-import ShortNameRefundSelection from '@/components/eft/ShortNameRefundSelection.vue'
-import ShortNameDetailsView from '@/components/eft/ShortNameDetailsView.vue'
-import ShortNameRefundView from '@/components/eft/ShortNameRefundView.vue'
-import RefundView from '@/views/pay/RefundView.vue'
-import TransactionRefundView from '@/views/TransactionRefundView.vue'
-import TransactionView from '@/views/TransactionView.vue'
-
-const routes: Array
- Transaction Refund
-
-
- Transactions
-
- {{$t('unauthorizedTitle')}}
- View Routing Slip: {{ slipId }}
- Electronic Funds Transfer Received Payments
-
- MVP Refunds - OPS only for now.
-
-
- Specify the fee amounts to be refunded and click 'Add to Refund', the refund summary entries will be appear for review.
-
-
-
-
-
-
- {{ item }}
-
-
-
-
- {{ index + 1 }}
- {{ item.description }}
-
-
-
-
-
-
-
-
-
-
-
- Refund Summary:
-
-
- By pressing the refund action, the specified amounts in the summary below will be refunded.
-
-
-
-
-
-
- {{ item }}
-
-
-
-
- {{ item + 1 }}
- {{ paymentLineItems[item].description }}
- {{ formatAmount(paymentLineItems[item].filingFees) }}
- {{ formatAmount(paymentLineItems[item].priorityFees) }}
- {{ formatAmount(paymentLineItems[item].futureEffectiveFees) }}
- {{ formatAmount(paymentLineItems[item].serviceFees) }}
-
- By pressing the refund action, the full paid amount will be refunded: ${{ invoicePaid.toFixed(2) }}
-
-
-
-
-
-
- Application
- Type
- Number
- Detail
-
-
-
- Name Request
- NR
- NR 1234567
-
-
-
-
-
-
- Transaction ID
- Invoice Reference ID
-
-
-
- 1234
- INV-123
-
${aboutText2}"`
- } else if (aboutText1) {
- return `"${aboutText1}"`
- } else if (aboutText2) {
- return `"${aboutText2}"`
- } else {
- return ''
- }
-}
-
-export default defineConfig(({ mode }) => {
- const isLibBuild = mode === 'lib'
- return {
- css: {
- preprocessorOptions: {
- scss: {
- additionalData: '@import "./src/assets/scss/theme.scss";'
- }
- }
- },
- define: {
- 'import.meta.env.ABOUT_TEXT': generateAboutText(aboutText1, aboutText2)
- },
- envPrefix: 'VUE_APP_', // Need to remove this after fixing vaults. Use import.meta.env with VUE_APP.
- build: {
- sourcemap: true,
- lib: isLibBuild ? {
- entry: path.resolve(__dirname, 'src/lib-setup.js'),
- name: 'lib',
- formats: ['umd'],
- fileName: (format) => `lib.${format}.min.js`
- } : undefined,
- terserOptions: {
- keep_classnames: true,
- keep_fnames: true,
- format: {
- semicolons: false
- }
- },
- rollupOptions: {
- external: (request) => {
- // If library, use externals, otherwise the Vue/ composition-api instance in Auth-web will have issues.
- if (isLibBuild && (/^@vue\/composition-api$/.test(request) || /^vue$/.test(request))) {
- return true
- }
- return false
- }
- },
- outDir: 'dist',
- minify: isLibBuild ? 'terser' : false
- },
- plugins: [
- vue({
- vueTemplateOptions: {
- transformAssetUrls: {
- img: ['src', 'data-src'],
- 'v-app-bar': ['image'],
- 'v-avatar': ['image'],
- 'v-banner': ['avatar'],
- 'v-card': ['image'],
- 'v-card-item': ['prependAvatar', 'appendAvatar'],
- 'v-chip': ['prependAvatar', 'appendAvatar'],
- 'v-img': ['src', 'lazySrc', 'srcset'],
- 'v-list-item': ['prependAvatar', 'appendAvatar'],
- 'v-navigation-bar': ['image'],
- 'v-parallax': ['src', 'lazySrc', 'srcset'],
- 'v-toolbar': ['image']
- }
- }
- }),
- EnvironmentPlugin({
- BUILD: 'web' // Fix for Vuelidate, allows process.env with Vite.
- }),
- postcssNesting,
- pluginRewriteAll(),
- {
- apply: 'build',
- enforce: 'post',
- transformIndexHtml () {
- buildSync({
- minify: true,
- bundle: true,
- entryPoints: [join(process.cwd(), 'service-worker.js')],
- outfile: join(process.cwd(), 'lib', 'service-worker.js')
- })
- }
- }
- ],
- resolve: {
- alias: {
- '@': path.resolve(__dirname, './src'),
- '~': path.resolve(__dirname, './node_modules'),
- $assets: path.resolve(__dirname, './src/assets'),
- // Fix for bcrs-shared-components unit tests fail
- '@bcrs-shared-components/mixins': path.resolve(__dirname, './node_modules/@bcrs-shared-components/mixins/index.ts'),
- '@bcrs-shared-components/enums': path.resolve(__dirname, './node_modules/@bcrs-shared-components/enums/index.ts'),
- '@bcrs-shared-components/staff-comments': path.resolve(__dirname, './node_modules/@bcrs-shared-components/staff-comments/index.ts'),
- '@bcrs-shared-components/interfaces': path.resolve(__dirname, './node_modules/@bcrs-shared-components/interfaces/index.ts')
- },
- extensions: ['.js', '.ts', '.vue', '.json', '.css', '.mjs', '.jsx', 'tsx']
- },
- server: {
- port: 8080,
- host: true
- },
- test: {
- globals: true,
- environment: 'jsdom',
- setupFiles: './tests/unit/setup.ts',
- threads: true,
- // hide Vue Devtools message
- onConsoleLog: function (log) {
- if (log.includes('Download the Vue Devtools extension')) {
- return false
- }
- },
- alias: {
- '@bcrs-shared-components/mixins': path.resolve(__dirname, './tests/unit/test-data/mock-mixins.ts')
- },
- server: {
- deps: {
- inline: [
- /@bcrs-shared-components\/.*/,
- /^@bcrs-shared-components$/,
- 'sbc-common-components'
- ]
- }
- }
- },
- optimizeDeps: {
- // This needs to be done for FAS-UI and sbc-common-components to work.
- // Otherwise FAS complains about not having Vue.use(VueCompositionAPI)
- // sbc-common-components will fail at login.
- // Remove with Vue 3 for most of these.
- exclude: ['@vue/composition-api', 'sbc-common-components']
- }
- }
-})
diff --git a/web/pay-ui/.env.example b/web/pay-ui/.env.example
new file mode 100644
index 00000000..8413d9dd
--- /dev/null
+++ b/web/pay-ui/.env.example
@@ -0,0 +1,31 @@
+# Web Urls
+NUXT_PUBLIC_BASE_URL="http://localhost:3000/"
+NUXT_PUBLIC_REGISTRY_HOME_URL="https://dev.bcregistry.gov.bc.ca/"
+NUXT_PUBLIC_AUTH_WEB_URL="https://dev.account.bcregistry.gov.bc.ca/"
+NUXT_PUBLIC_FAS_WEB_URL="https://fas-dev.apps.silver.devops.gov.bc.ca/"
+
+# API Key
+NUXT_PUBLIC_X_API_KEY=""
+
+# API Urls
+NUXT_PUBLIC_STATUS_API_URL="https://status-api-dev.apps.gold.devops.gov.bc.ca"
+NUXT_PUBLIC_STATUS_API_VERSION="/api/v1"
+NUXT_PUBLIC_AUTH_API_URL="https://test.api.connect.gov.bc.ca/auth-dev"
+NUXT_PUBLIC_AUTH_API_VERSION="/api/v1"
+NUXT_PUBLIC_PAY_API_URL="https://test.api.connect.gov.bc.ca/pay-dev"
+NUXT_PUBLIC_PAY_API_VERSION="/api/v1"
+
+# LaunchDarkly
+NUXT_PUBLIC_LD_CLIENT_ID=""
+
+# Identity Provider
+NUXT_PUBLIC_IDP_URL="https://dev.loginproxy.gov.bc.ca/auth"
+NUXT_PUBLIC_IDP_REALM="bcregistry"
+NUXT_PUBLIC_IDP_CLIENTID="fas-web"
+NUXT_PUBLIC_SITEMINDER_LOGOUT_URL="https://logontest7.gov.bc.ca/clp-cgi/logoff.cgi"
+
+# Canada Post
+NUXT_PUBLIC_ADDRESS_COMPLETE_KEY=""
+
+# For /gcbrun builds
+NUXT_PUBLIC_IS_PREVIEW_BUILD=false
diff --git a/.gcloudignore b/web/pay-ui/.gcloudignore
similarity index 100%
rename from .gcloudignore
rename to web/pay-ui/.gcloudignore
diff --git a/web/pay-ui/.gitignore b/web/pay-ui/.gitignore
new file mode 100644
index 00000000..319d3354
--- /dev/null
+++ b/web/pay-ui/.gitignore
@@ -0,0 +1,31 @@
+# Nuxt dev/build outputs
+.output
+.data
+.nuxt
+.nitro
+.cache
+dist
+
+# Node dependencies
+node_modules
+
+# Logs
+logs
+*.log
+
+# Misc
+.DS_Store
+.fleet
+.idea
+
+# Local env files
+.env
+.env.*
+!.env.example
+
+# testing
+test-results
+tests/e2e/.auth/**
+playwright-report
+blob-report
+tests/unit/coverage
\ No newline at end of file
diff --git a/web/pay-ui/.npmrc b/web/pay-ui/.npmrc
new file mode 100644
index 00000000..1cfbd6f0
--- /dev/null
+++ b/web/pay-ui/.npmrc
@@ -0,0 +1,2 @@
+shamefully-hoist=true
+strict-peer-dependencies=false
\ No newline at end of file
diff --git a/web/pay-ui/README.md b/web/pay-ui/README.md
new file mode 100644
index 00000000..25b58212
--- /dev/null
+++ b/web/pay-ui/README.md
@@ -0,0 +1,75 @@
+# Nuxt Minimal Starter
+
+Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
+
+## Setup
+
+Make sure to install dependencies:
+
+```bash
+# npm
+npm install
+
+# pnpm
+pnpm install
+
+# yarn
+yarn install
+
+# bun
+bun install
+```
+
+## Development Server
+
+Start the development server on `http://localhost:3000`:
+
+```bash
+# npm
+npm run dev
+
+# pnpm
+pnpm dev
+
+# yarn
+yarn dev
+
+# bun
+bun run dev
+```
+
+## Production
+
+Build the application for production:
+
+```bash
+# npm
+npm run build
+
+# pnpm
+pnpm build
+
+# yarn
+yarn build
+
+# bun
+bun run build
+```
+
+Locally preview production build:
+
+```bash
+# npm
+npm run preview
+
+# pnpm
+pnpm preview
+
+# yarn
+yarn preview
+
+# bun
+bun run preview
+```
+
+Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
diff --git a/web/pay-ui/app/app.config.ts b/web/pay-ui/app/app.config.ts
new file mode 100644
index 00000000..efde1c67
--- /dev/null
+++ b/web/pay-ui/app/app.config.ts
@@ -0,0 +1,75 @@
+/* eslint-disable max-len */
+export default defineAppConfig({
+ connect: {
+ header: {
+ localeSelect: false
+ },
+ login: {
+ redirect: '/home'
+ }
+ },
+ ui: {
+ container: {
+ base: 'max-w-(--container-bcGovLg) px-0 sm:px-0 lg:px-0 py-6 sm:py-10 flex flex-col gap-6 sm:gap-8'
+ },
+ inputMenu: {
+ slots: {
+ group: 'p-0',
+ item: 'py-3 px-4 data-highlighted:not-data-disabled:text-primary data-highlighted:not-data-disabled:before:bg-shade my-0.75 before:rounded-none'
+ },
+ variants: {
+ size: {
+ bcGovLg: {
+ base: 'px-2.5 pb-2 pt-6 text-base gap-1.5',
+ leading: 'ps-2.5',
+ trailing: 'pe-2.5',
+ leadingIcon: 'size-5',
+ leadingAvatarSize: '2xs',
+ trailingIcon: 'size-5'
+ }
+ },
+ variant: {
+ bcGov: 'ring-0 ring-transparent peer rounded-t-sm rounded-b-none bg-shade shadow-input focus:ring-0 focus:outline-none focus:shadow-input-focus text-neutral-highlighted aria-invalid:shadow-input-error aria-invalid:focus:shadow-input-error aria-invalid:ring-0'
+ }
+ },
+ defaultVariants: {
+ size: 'bcGovLg',
+ color: 'primary',
+ variant: 'bcGov'
+ }
+ },
+ select: {
+ slots: {
+ placeholder: 'text-neutral'
+ }
+ },
+ toast: {
+ slots: {
+ root: 'rounded',
+ title: 'text-base font-bold text-neutral-highlighted',
+ description: 'text-neutral-highlighted'
+ },
+ variants: {
+ color: {
+ error: {
+ root: 'bg-shade-warning ring-error ring-inset',
+ icon: 'text-error'
+ }
+ }
+ }
+ },
+ tooltip: {
+ slots: {
+ content: 'bg-neutral ring-neutral text-secondary p-4 text-sm'
+ }
+ },
+ button: {
+ slots: {
+ base: 'h-[44px] px-[19px] disabled:opacity-40 disabled:cursor-not-allowed'
+ },
+ default: {
+ padding: 'px-[19px]'
+ }
+ }
+ }
+})
diff --git a/web/pay-ui/app/assets/scss/basic-table.scss b/web/pay-ui/app/assets/scss/basic-table.scss
new file mode 100644
index 00000000..20877856
--- /dev/null
+++ b/web/pay-ui/app/assets/scss/basic-table.scss
@@ -0,0 +1,20 @@
+// Basic table styling for simple data tables
+
+:deep(table) {
+ width: 100%;
+ background-color: white;
+}
+
+:deep(th) {
+ padding: 12px 16px;
+ background-color: white;
+ color: #495057;
+ font-weight: 700;
+}
+
+:deep(td) {
+ padding: 12px 16px;
+ background-color: white;
+ color: #495057;
+ font-weight: 400;
+}
diff --git a/web/pay-ui/app/assets/scss/colors.scss b/web/pay-ui/app/assets/scss/colors.scss
new file mode 100644
index 00000000..9ee6ad9d
--- /dev/null
+++ b/web/pay-ui/app/assets/scss/colors.scss
@@ -0,0 +1,23 @@
+// Color definitions
+:root {
+ --color-text-secondary: #495057;
+ --color-text-primary: #212529;
+ --color-table-header-text: #212529;
+ --color-divider: #e5e7eb;
+ --color-bg-shade: #f1f3f5;
+ --color-refund-status-bg: #e2e8ee;
+
+ --color-bg-light-blue: #e0e7ed;
+ --color-text-dark-gray: #374151;
+ --color-bg-light-gray: #f1f1f1;
+ --color-gray-500: #888888;
+ --color-gray-700: #555555;
+ --color-link-blue: #1a73e8;
+ --color-border-blue: #38598a;
+ --color-white: #ffffff;
+ --color-primary-blue: #2563eb;
+ --color-primary: #1a5a96;
+ --color-caution-bg: #fffbeb;
+ --color-caution-border: #fcd34d;
+ --color-caution-icon: #d97706;
+}
diff --git a/web/pay-ui/app/assets/scss/global.scss b/web/pay-ui/app/assets/scss/global.scss
new file mode 100644
index 00000000..5107781a
--- /dev/null
+++ b/web/pay-ui/app/assets/scss/global.scss
@@ -0,0 +1,166 @@
+@use 'colors.scss' as *;
+
+// ============================================
+// Table Styles
+// ============================================
+
+// Exception for table filter input buttons
+.table-filter-input button,
+.table-filter-input .ui-button,
+.table-filter-input [class*='ui-button'],
+.table-filter-input .ui-select button {
+ padding-left: 0.75rem !important;
+ padding-right: 0.5rem !important;
+}
+
+
+
+// Table header text color
+.table-header-text {
+ color: var(--color-table-header-text) !important;
+}
+
+// Global label font size
+label,
+.ui-form-label {
+ font-size: 16px;
+}
+
+// Button font size
+.ui-button,
+button.ui-button,
+button[class*='ui-button'],
+button {
+ font-size: 16px !important;
+
+ span,
+ label,
+ .ui-button-label,
+ [class*='label'] {
+ font-size: 16px !important;
+ }
+
+ * {
+ font-size: 16px !important;
+ }
+}
+
+// Target all spans and labels inside buttons globally
+button span,
+button label,
+.ui-button span,
+.ui-button label {
+ font-size: 16px
+}
+
+// Utility class for table buttons (38px height)
+.btn-table {
+ height: 38px !important;
+ padding-left: 19px !important;
+ padding-right: 19px !important;
+ cursor: pointer;
+}
+
+// Utility class for table filter inputs (40px height)
+.table-filter-input {
+ // Target UInput components
+ .ui-input,
+ .ui-input input,
+ input {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ padding-left: 0.75rem !important;
+ color: var(--color-text-primary) !important;
+ }
+
+ input::placeholder {
+ color: var(--color-text-secondary) !important;
+ }
+
+ // Target UButton components (for DateRangeFilter)
+ .ui-button,
+ button {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ color: var(--color-text-primary) !important;
+
+ .date-range-placeholder,
+ span.date-range-placeholder {
+ color: var(--color-text-secondary) !important;
+ }
+ }
+
+ // Target USelect components
+ .ui-select,
+ .ui-select button {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ padding-left: 0.75rem !important;
+ }
+
+ .ui-select button {
+ color: var(--color-text-primary) !important;
+ }
+
+ .ui-select button:not([data-selected="true"]) {
+ color: var(--color-text-secondary) !important;
+ }
+
+ // Target status-list components
+ .ui-select-menu,
+ .ui-select-menu button {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ }
+
+ * {
+ .ui-input,
+ .ui-input input,
+ input[type="text"],
+ input[type="number"] {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ padding-left: 0.75rem !important;
+ color: var(--color-text-primary) !important;
+ }
+
+ input::placeholder {
+ color: var(--color-text-secondary) !important;
+ }
+
+ .ui-button,
+ button.ui-button {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ color: var(--color-text-primary) !important;
+ }
+
+ .ui-select,
+ .ui-select button {
+ height: 40px !important;
+ border-radius: 0.375rem 0.375rem 0 0 !important;
+ }
+
+ .ui-select button {
+ color: var(--color-text-primary) !important;
+ }
+
+ .ui-select button:not([data-selected="true"]) {
+ color: var(--color-text-secondary) !important;
+ }
+ }
+}
+
+body.table-wide-active {
+ .app-inner-container {
+ max-width: calc(100vw - 15rem) !important;
+ }
+}
+
+// ============================================
+// Modal Styles
+// ============================================
+
+[data-slot="content"] {
+ max-width: 720px !important;
+}
diff --git a/web/pay-ui/app/assets/scss/search-table.scss b/web/pay-ui/app/assets/scss/search-table.scss
new file mode 100644
index 00000000..dfd858c7
--- /dev/null
+++ b/web/pay-ui/app/assets/scss/search-table.scss
@@ -0,0 +1,349 @@
+@use '~/assets/scss/colors.scss' as *;
+
+// Common table styling for search based tables.
+
+:deep(table td) {
+ color: var(--color-text-secondary);
+}
+
+:deep(.sticky-row) {
+ position: sticky;
+ top: var(--search-sticky-header-height, 48px);
+ z-index: 19;
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+ margin: 0 !important;
+ transform: none !important;
+}
+
+:deep(.sticky-row th) {
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+ border-top: none !important;
+ border-left: none !important;
+ border-right: none !important;
+ border-bottom: 1px solid var(--color-divider) !important;
+ padding-left: 0.25rem !important;
+ padding-right: 0.25rem !important;
+ padding-top: 1rem !important;
+ padding-bottom: 1rem !important;
+ vertical-align: middle;
+}
+
+:deep(.sticky-row th:first-child) {
+ border-left: none !important;
+}
+
+:deep(.sticky-row th:last-child) {
+ border-right: none !important;
+}
+
+:deep(.sticky-row td) {
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+ opacity: 1 !important;
+}
+
+:deep(.sticky-row th *),
+:deep(.table-filter-input) {
+ &,
+ & *,
+ & input::placeholder,
+ & .placeholder::placeholder,
+ & [placeholder]::placeholder {
+ font-weight: 400 !important;
+ color: var(--color-text-secondary) !important;
+ }
+}
+
+:deep(.ui-select button) {
+ padding-left: 0.75rem !important;
+}
+
+// Set 14px font size for DateRangeFilter and StatusList - override global button font size
+:deep(.table-filter-input:is(.date, .status-list-wrapper, status-list)),
+:deep(.table-filter-input:is(.date, .status-list-wrapper, status-list) *),
+:deep(.table-filter-input :is(.date, .status-list-wrapper, status-list, .date-range-filter-button,
+ .date-range-placeholder)),
+:deep(.table-filter-input :is(.date, .status-list-wrapper, status-list, .date-range-filter-button,
+ .date-range-placeholder) *) {
+ font-size: 14px !important;
+}
+
+:deep(.overflow-x-auto) {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ background-color: var(--color-white) !important;
+ margin: 0 !important;
+ transform: none !important;
+ position: relative;
+}
+
+:deep(.overflow-x-auto > *) {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ min-height: 0;
+}
+
+.columns-to-show-btn {
+ background-color: var(--color-white) !important;
+}
+
+.columns-to-show-btn:hover,
+.columns-to-show-btn:focus,
+.columns-to-show-btn:active {
+ background-color: var(--color-white) !important;
+}
+
+:deep(.columns-to-show-btn) {
+ background-color: var(--color-white) !important;
+}
+
+:deep(.columns-to-show-btn:hover),
+:deep(.columns-to-show-btn:focus),
+:deep(.columns-to-show-btn:active) {
+ background-color: var(--color-white) !important;
+}
+
+.table-scroll {
+ max-height: 100%;
+ overflow-y: auto;
+ overflow-x: hidden;
+ position: relative;
+ height: 100%;
+}
+
+.table-scroll,
+.table-scroll * {
+ transform: none !important;
+ will-change: auto !important;
+}
+
+:deep(.sticky-table thead th) {
+ position: sticky;
+ top: 0;
+ z-index: 20;
+ background: var(--ui-bg, #ffffff);
+}
+
+:deep(.sticky-table .relative) {
+ overflow: visible !important;
+}
+
+:deep(.sticky-table table) {
+ border-collapse: separate;
+ border-spacing: 0;
+}
+
+:deep(table) {
+ border-spacing: 0;
+ margin: 0 !important;
+ padding: 0 !important;
+ transform: none !important;
+ position: relative;
+}
+
+:deep(table),
+:deep(table thead),
+:deep(table thead tr),
+:deep(table thead tr th) {
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+}
+
+:deep(table thead) {
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+ margin: 0 !important;
+ transform: none !important;
+}
+
+:deep(table tbody) {
+ margin: 0 !important;
+ padding: 0 !important;
+ transform: none !important;
+}
+
+:deep(table tbody tr) {
+ background-color: transparent;
+ margin: 0 !important;
+ transform: none !important;
+}
+
+:deep(table thead tr th) {
+ color: var(--color-text-primary);
+ padding-left: 0.25rem !important;
+ padding-right: 0.25rem !important;
+ font-weight: 700 !important;
+ background-color: var(--color-white) !important;
+ background: var(--color-white) !important;
+ border-top: 1px solid var(--color-divider) !important;
+ border-bottom: 1px solid var(--color-divider) !important;
+ border-left: none !important;
+ border-right: none !important;
+}
+
+:deep(table thead tr th::before),
+:deep(table thead tr th::after) {
+ display: none !important;
+}
+
+:deep(table thead tr th:first-child) {
+ padding-left: 1rem !important;
+}
+
+:deep(table thead tr th:last-child) {
+ padding-right: 1rem !important;
+ text-align: right !important;
+ border-right: none !important;
+ border-left: none !important;
+}
+
+:deep(table tbody tr td:first-child) {
+ padding-left: 1rem !important;
+}
+
+:deep(table tbody tr td:last-child) {
+ padding-right: 1rem !important;
+ border-right: none !important;
+ border-left: none !important;
+}
+
+:deep(table thead tr th.header-action),
+:deep(table tbody tr td:has(.btn-table)) {
+ border-right: none !important;
+ border-left: none !important;
+}
+
+:deep(table thead tr th:last-child) {
+ border-top: 1px solid var(--color-divider) !important;
+ border-bottom: 1px solid var(--color-divider) !important;
+ border-left: none !important;
+ border-right: none !important;
+}
+
+:deep(.sticky-row th:first-child) {
+ padding-left: 1rem !important;
+}
+
+:deep(.sticky-row th:last-child) {
+ padding-right: 1rem !important;
+ border-right: none !important;
+ border-bottom: 1px solid var(--color-divider) !important;
+}
+
+:deep(table tbody tr td) {
+ word-wrap: break-word !important;
+ overflow-wrap: break-word !important;
+ white-space: normal !important;
+ border-bottom: 1px solid var(--color-divider) !important;
+ border-left: none !important;
+ border-right: none !important;
+}
+
+:deep(.sticky-row) {
+ :is(.ui-select, status-list, .input-text) {
+ &, * {
+ font-weight: 400 !important;
+ }
+
+ .ui-select button {
+ padding-left: 0.75rem !important;
+ }
+ }
+
+ :is(.ui-input, input:is([type="text"], [type="number"])) {
+ &, & input {
+ padding-left: 0.75rem !important;
+ }
+ }
+}
+
+// Make table divider thicker
+:deep(tr.absolute.z-\[1\].left-0.w-full.h-px),
+:deep(tr[class*="absolute"][class*="z-[1]"][class*="h-px"]) {
+ height: 2px !important;
+}
+
+// Clear Filters button styling
+:deep(.clear-filters-th) {
+ text-align: left !important;
+}
+
+:deep(.clear-filters-th .clear-filters-btn) {
+ &, & * {
+ color: var(--color-primary, #2563eb) !important;
+ }
+ width: 100% !important;
+ padding-left: 0.75rem !important;
+ padding-right: 0.75rem !important;
+ font-size: 0.875rem !important;
+ height: 38px !important;
+ display: inline-flex !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+}
+
+:deep(.header-action) {
+ text-align: right;
+}
+
+.header {
+ .sticky {
+ background-color: var(--color-white);
+ }
+
+ .header-row-2 {
+ th > div {
+ width: 100%;
+ }
+ .date button {
+ padding: 6px 10px !important;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 250px !important;
+ background-color: var(--color-bg-shade) !important;
+ }
+ .placeholder {
+ font-weight: 400;
+ color: var(--color-text-secondary);
+ }
+ .input-text {
+ font-weight: 400 !important;
+ color: var(--color-text-secondary);
+ }
+ }
+}
+
+.wide-dropdown {
+ width: 200px !important;
+}
+
+// Override global label font size for search page
+:deep(label),
+:deep(.ui-form-label) {
+ font-size: inherit;
+}
+
+:deep(.date-range-placeholder, .date-range-result) {
+ font-size: 14px !important;
+ }
+
+// Exclude DateRangeFilter and StatusList from 16px font size
+:deep(:is(.date, .date-range-filter-button, .status-list-wrapper, .table-filter-input,
+ .table-filter-input *)) {
+ :is(label, .ui-form-label) {
+ font-size: inherit !important;
+ }
+ :is(span) {
+ font-size: 14px !important;
+ }
+}
+
+:deep(.date-range-filter-button) {
+ ::is(span) {
+ font-size: 14px !important;
+ }
+}
diff --git a/web/pay-ui/app/components/CreateRoutingSlip/Address.vue b/web/pay-ui/app/components/CreateRoutingSlip/Address.vue
new file mode 100644
index 00000000..5bccc7cb
--- /dev/null
+++ b/web/pay-ui/app/components/CreateRoutingSlip/Address.vue
@@ -0,0 +1,28 @@
+
+
+
+
+ Search Routing Slip
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
+
+
+ {{ getStatusLabel(row.original.status) ?? '-' }}
+
+
+
+
+
+ {{ row.original.businessIdentifier[0] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('text.linkedRoutingSlip') }}
+
+
+ {{ $t('text.cantLinkSinceInvoicesExistP2') }}
+
+
+
+ Refunded ({{ appendCurrencySymbol(row.original.refund?.toFixed(2) || '0.00') }})
+
+
+
+
+
+
+ {{ row.original.shortName }}
+
+
+
+ {{ getShortNameTypeDescription(row.original.shortNameType) }}
+
+
+
+ {{ row.original.accountName }}
+
+
+
+ {{ row.original.accountBranch || '' }}
+
+
+
+ {{ row.original.accountId }}
+
+
+
+ {{ CommonUtils.formatAmount(row.original.amountOwing) }}
+
+
+
+ {{ row.original.statementId || '' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ state.confirmDialogTitle }}
+
+
+ {{ t('page.eft.shortNameDetails.label.accountsLinkedTo', { shortName: shortNameDetails?.shortName }) }}
+
+
+ {{ dialogConfig.title }}
+
+
+ Linking {{ shortName?.shortName }} to an Account
+
+
+ Search by Account ID or Name to Link:
+
+
+ Payment Information
+
+
+ {{ errorDialogTitle }}
+
+
+ {{ confirmDialog.title }}
+
+
+ Short Name Payment History
+
+
+ Short Name Refund
+
+
+ Decline Refund Request?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ tableTitle }} ({{ state.totalResults }})
+
+
+
+
+
+
+ {{ formatDate(row.original.requestedDate) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Transactions
+
+
+
+
+
+
+
+
+ {{ asTransaction(row).paymentAccount?.accountName || '-' }}
+
+
+
+
+
+
+ {{ getProductDisplayName(String(asTransaction(row).product)) }}
+
+
+
+
+
+ {{ asDropdownItem(row).type }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ('routing_slip_statuses')
+ } catch {
+ return []
+ }
+}
+
+export async function useStatusList(props: StatusListProps, { emit }: StatusListEmit) {
+ const routingSlipStatusList = ref(await loadRoutingSlipStatusList())
+ const value = toRef(props, 'value')
+
+ const currentStatus = computed({
+ get: () => value.value || '',
+ set: (newValue: Code) => {
+ emit('update:modelValue', newValue.code)
+ }
+ })
+
+ function statusLabel(code: string) {
+ const statusObject = selectedStatusObject(code)
+ return statusObject?.description || ''
+ }
+
+ function selectedStatusObject(code: string): Code | undefined {
+ return routingSlipStatusList.value?.find(
+ statusList => statusList.code === code
+ )
+ }
+
+ return {
+ routingSlipStatusList,
+ currentStatus,
+ statusLabel,
+ selectedStatusObject
+ }
+}
+
+// Helper to load routing slip status list
+export async function useRoutingSlipStatusList() {
+ const list = shallowRef([])
+
+ async function load() {
+ if (list.value.length === 0) {
+ list.value = await loadRoutingSlipStatusList()
+ }
+ }
+
+ const mapFn = (item: Code): SelectItem => ({
+ label: item.description,
+ value: item.code
+ })
+
+ await load()
+
+ return {
+ list,
+ mapFn,
+ load
+ }
+}
+
+interface ChequeRefundStatusItem {
+ code: string
+ text: string
+ display: boolean
+}
+
+// Helper to get cheque refund status list
+export function useChequeRefundStatusList() {
+ const list = computed(() => ChequeRefundStatus)
+
+ const mapFn = (item: ChequeRefundStatusItem): SelectItem => ({
+ label: item.text,
+ value: item.code
+ })
+
+ return {
+ list,
+ mapFn
+ }
+}
+
+interface ShortNameTypeItem {
+ label: string
+ value: string
+}
+
+// Helper to get short name type list
+export function useShortNameTypeList() {
+ const list = computed(() => ShortNameUtils.ShortNameTypeItems)
+
+ const mapFn = (item: ShortNameTypeItem): SelectItem => ({
+ label: item.label,
+ value: item.value
+ })
+
+ return {
+ list,
+ mapFn
+ }
+}
+
+interface PaymentMethodSelectItem {
+ text: string
+ value: string
+}
+
+// Helper to get payment methods list
+export function usePaymentMethodsList() {
+ const list = computed(() => PaymentMethodSelectItems)
+ const mapFn = (item: PaymentMethodSelectItem): SelectItem => ({
+ label: item.text,
+ value: item.value
+ })
+
+ return {
+ list,
+ mapFn
+ }
+}
+
+// Helper to get invoice status list
+export function useInvoiceStatusList() {
+ const list = computed(() => PaymentStatusList)
+
+ const mapFn = (item: SelectItem): SelectItem => item
+
+ return {
+ list,
+ mapFn
+ }
+}
+
+// Helper to get product (Application Type) list
+export function useProductList() {
+ const list = computed(() =>
+ Object.entries(productDisplay).map(([value, label]) => ({ label, value }))
+ )
+
+ const mapFn = (item: SelectItem): SelectItem => item
+
+ return {
+ list,
+ mapFn
+ }
+}
diff --git a/web/pay-ui/app/composables/common/useStickyHeader.ts b/web/pay-ui/app/composables/common/useStickyHeader.ts
new file mode 100644
index 00000000..c1cc88fa
--- /dev/null
+++ b/web/pay-ui/app/composables/common/useStickyHeader.ts
@@ -0,0 +1,21 @@
+import { useResizeObserver } from '@vueuse/core'
+import type { Ref } from 'vue'
+
+export function useStickyHeader(scrollEl: Ref