From afab7a6b380826a6f6e05a5c50247ff310ad4b2a Mon Sep 17 00:00:00 2001 From: JatinderSingh Date: Thu, 4 Apr 2024 15:46:58 -0700 Subject: [PATCH] update github actions and workflow --- .../actions/build-push-container/action.yaml | 10 +- .../actions/deploy-to-environment/action.yaml | 2 +- .github/workflows/charts-release.yaml | 2 +- .github/workflows/codeql-analysis.yaml | 8 +- .github/workflows/on-pr-closed.yaml | 6 +- .github/workflows/on-pr-opened.yaml | 6 +- .github/workflows/on-push.yaml | 8 +- .github/workflows/unit-tests.yaml | 85 ++++++---- Dockerfile | 57 ++++--- app/frontend/{lcov-fix.js => lcov-fix.mjs} | 0 app/frontend/package-lock.json | 27 ++-- app/frontend/package.json | 71 ++++++++- app/frontend/src/views/merge/MergeAbout.vue | 150 ++++++++++++------ app/lcov-fix.js | 2 +- 14 files changed, 293 insertions(+), 141 deletions(-) rename app/frontend/{lcov-fix.js => lcov-fix.mjs} (100%) diff --git a/.github/actions/build-push-container/action.yaml b/.github/actions/build-push-container/action.yaml index f87609a..a753a21 100644 --- a/.github/actions/build-push-container/action.yaml +++ b/.github/actions/build-push-container/action.yaml @@ -30,7 +30,7 @@ runs: using: composite steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Parse Input Values shell: bash @@ -39,7 +39,7 @@ runs: echo "HAS_DOCKERHUB=${{ fromJson(inputs.dockerhub_username != '' && inputs.dockerhub_token != '') }}" >> $GITHUB_ENV - name: Login to Github Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ env.GH_USERNAME }} @@ -47,7 +47,7 @@ runs: - name: Login to Dockerhub Container Registry if: env.HAS_DOCKERHUB == 'true' - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: docker.io username: ${{ inputs.dockerhub_username }} @@ -55,7 +55,7 @@ runs: - name: Prepare Container Metadata tags id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: | ghcr.io/${{ env.GH_USERNAME }}/${{ inputs.image_name }} @@ -74,7 +74,7 @@ runs: - name: Build and Push to Container Registry id: builder - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: context: ${{ inputs.context }} push: true diff --git a/.github/actions/deploy-to-environment/action.yaml b/.github/actions/deploy-to-environment/action.yaml index 58422d4..19c2751 100644 --- a/.github/actions/deploy-to-environment/action.yaml +++ b/.github/actions/deploy-to-environment/action.yaml @@ -30,7 +30,7 @@ runs: using: composite steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Login to OpenShift Cluster uses: redhat-actions/oc-login@v1 diff --git a/.github/workflows/charts-release.yaml b/.github/workflows/charts-release.yaml index 62919f9..16063db 100644 --- a/.github/workflows/charts-release.yaml +++ b/.github/workflows/charts-release.yaml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 1ea8655..25226f5 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -42,11 +42,11 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -57,7 +57,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 + uses: github/codeql-action/autobuild@v3 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -71,4 +71,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/on-pr-closed.yaml b/.github/workflows/on-pr-closed.yaml index 8af073c..31dc732 100644 --- a/.github/workflows/on-pr-closed.yaml +++ b/.github/workflows/on-pr-closed.yaml @@ -27,7 +27,7 @@ jobs: timeout-minutes: 12 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Login to OpenShift Cluster uses: redhat-actions/oc-login@v1 with: @@ -41,12 +41,12 @@ jobs: helm uninstall --namespace ${{ env.NAMESPACE_PREFIX }}-dev pr-${{ github.event.number }} --timeout 10m --wait oc delete --namespace ${{ env.NAMESPACE_PREFIX }}-dev cm,secret --selector app.kubernetes.io/instance=pr-${{ github.event.number }} - name: Remove Release Comment on PR - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@v2.9.0 with: header: release delete: true - name: Remove Github Deployment Environment - uses: strumwolf/delete-deployment-environment@v2 + uses: strumwolf/delete-deployment-environment@v3 with: environment: pr onlyRemoveDeployments: true diff --git a/.github/workflows/on-pr-opened.yaml b/.github/workflows/on-pr-opened.yaml index c79745e..1b6facd 100644 --- a/.github/workflows/on-pr-opened.yaml +++ b/.github/workflows/on-pr-opened.yaml @@ -26,7 +26,7 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build & Push uses: ./.github/actions/build-push-container with: @@ -45,7 +45,7 @@ jobs: timeout-minutes: 12 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy to Dev uses: ./.github/actions/deploy-to-environment with: @@ -58,7 +58,7 @@ jobs: openshift_server: ${{ secrets.OPENSHIFT_SERVER }} openshift_token: ${{ secrets.OPENSHIFT_TOKEN }} - name: Release Comment on PR - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@v2.9.0 if: success() with: header: release diff --git a/.github/workflows/on-push.yaml b/.github/workflows/on-push.yaml index a72fe80..99f96e9 100644 --- a/.github/workflows/on-push.yaml +++ b/.github/workflows/on-push.yaml @@ -23,7 +23,7 @@ jobs: timeout-minutes: 10 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build & Push uses: ./.github/actions/build-push-container with: @@ -44,7 +44,7 @@ jobs: timeout-minutes: 12 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy to Dev uses: ./.github/actions/deploy-to-environment with: @@ -69,7 +69,7 @@ jobs: timeout-minutes: 12 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy to Test uses: ./.github/actions/deploy-to-environment with: @@ -95,7 +95,7 @@ jobs: timeout-minutes: 12 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Deploy to Prod uses: ./.github/actions/deploy-to-environment with: diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml index 95d798f..179a273 100644 --- a/.github/workflows/unit-tests.yaml +++ b/.github/workflows/unit-tests.yaml @@ -5,29 +5,34 @@ on: - pull_request jobs: test-app: + name: Unit Tests (App) runs-on: ubuntu-latest defaults: run: working-directory: app + outputs: + HAS_CC_SECRETS: ${{ steps.check-secrets.outputs.HAS_CC_SECRETS }} timeout-minutes: 10 strategy: fail-fast: true matrix: node-version: - - 14.x - 16.x - 18.x + - 20.x steps: - name: Checkout Repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 + uses: actions/checkout@v4 + - name: Check CodeClimate Secrets + id: check-secrets + run: | + echo "HAS_CC_SECRETS=${{ secrets.CC_TEST_REPORTER_ID != '' }}" >> $GITHUB_OUTPUT - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v4 id: cache-app env: cache-name: cache-node-modules @@ -46,36 +51,52 @@ jobs: env: CI: true - name: Save Coverage Results - if: matrix.node-version == '18.x' - uses: actions/upload-artifact@v2 + if: matrix.node-version == '20.x' + uses: actions/upload-artifact@v4 with: name: coverage-app path: ${{ github.workspace }}/app/coverage retention-days: 1 + - name: Monitor Coverage + if: "matrix.node-version == '20.x' && ! github.event.pull_request.head.repo.fork" + uses: slavcodev/coverage-monitor-action@v1 + with: + comment_mode: update + comment_footer: false + comment_context: Coverage Report (Application) + coverage_path: app/coverage/clover.xml + github_token: ${{ secrets.GITHUB_TOKEN }} + threshold_alert: 50 + threshold_warning: 80 test-frontend: + name: Unit Tests (Frontend) runs-on: ubuntu-latest defaults: run: working-directory: app/frontend + outputs: + HAS_CC_SECRETS: ${{ steps.check-secrets.outputs.HAS_CC_SECRETS }} timeout-minutes: 10 strategy: fail-fast: true matrix: node-version: - - 14.x - 16.x - 18.x + - 20.x steps: - name: Checkout Repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 + uses: actions/checkout@v4 + - name: Check CodeClimate Secrets + id: check-secrets + run: | + echo "HAS_CC_SECRETS=${{ secrets.CC_TEST_REPORTER_ID != '' }}" >> $GITHUB_OUTPUT - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v4 id: cache-frontend env: cache-name: cache-node-modules @@ -94,38 +115,38 @@ jobs: env: CI: true - name: Save Coverage Results - if: matrix.node-version == '18.x' - uses: actions/upload-artifact@v2 + if: matrix.node-version == '20.x' + uses: actions/upload-artifact@v4 with: name: coverage-frontend path: ${{ github.workspace }}/app/frontend/coverage retention-days: 1 + - name: Monitor Coverage + if: "matrix.node-version == '20.x' && ! github.event.pull_request.head.repo.fork" + uses: slavcodev/coverage-monitor-action@v1 + with: + comment_mode: update + comment_footer: false + comment_context: Coverage Report (Frontend) + coverage_path: app/frontend/coverage/clover.xml + github_token: ${{ secrets.GITHUB_TOKEN }} + threshold_alert: 50 + threshold_warning: 80 test-coverage: + name: Publish to Code Climate needs: - test-app - test-frontend + if: needs.test-app.outputs.HAS_CC_SECRETS == 'true' runs-on: ubuntu-latest timeout-minutes: 10 steps: - - name: Check Workflow Secrets - id: check-secrets - run: | - unset HAS_SECRETS - if [ -n "$CC_TEST_REPORTER_ID" ]; then HAS_SECRETS='true'; fi - echo ::set-output name=HAS_SECRETS::${HAS_SECRETS} - env: - CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} - name: Checkout Repository - if: steps.check-secrets.outputs.HAS_SECRETS - uses: actions/checkout@v2 - with: - fetch-depth: 0 + uses: actions/checkout@v4 - name: Restore Coverage Results - if: steps.check-secrets.outputs.HAS_SECRETS - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Publish code coverage - if: steps.check-secrets.outputs.HAS_SECRETS - uses: paambaati/codeclimate-action@v2.7.5 + uses: paambaati/codeclimate-action@v5 env: CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} with: diff --git a/Dockerfile b/Dockerfile index 94c903a..d700e3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,49 +1,62 @@ -# FROM docker.io/node:16.15.0-alpine # Last known working alpine image - -# RedHat Image Catalog references -# https://catalog.redhat.com/software/containers/ubi9/nodejs-18/62e8e7ed22d1d3c2dfe2ca01 -# https://catalog.redhat.com/software/containers/ubi8/nodejs-16/615aee9fc739c0a4123a87e1 -# https://catalog.redhat.com/software/containers/ubi9/nodejs-18-minimal/62e8e919d4f57d92a9dee838 +ARG APP_ROOT=/opt/app-root/src +ARG BASE_IMAGE=docker.io/node:20.11.1-alpine # -# Build the application +# Build the app # -FROM registry.access.redhat.com/ubi9/nodejs-18:1-48 as application +FROM ${BASE_IMAGE} as app +ARG APP_ROOT ENV NO_UPDATE_NOTIFIER=true -USER 0 -COPY --chown=1001:0 app /tmp/src/app -WORKDIR /tmp/src/app +# NPM Permission Fix +RUN mkdir -p /.npm +RUN chown -R 1001:0 /.npm + +# Build App +COPY app ${APP_ROOT} +RUN chown -R 1001:0 ${APP_ROOT} USER 1001 +WORKDIR ${APP_ROOT} RUN npm ci --omit=dev # # Build the frontend # -FROM registry.access.redhat.com/ubi8/nodejs-16:1-105.1684740145 as frontend +FROM ${BASE_IMAGE} as frontend +ARG APP_ROOT ENV NO_UPDATE_NOTIFIER=true -USER 0 -COPY --chown=1001:0 app/frontend /tmp/src/app/frontend -WORKDIR /tmp/src/app/frontend -USER 1001 +# NPM Permission Fix +RUN mkdir -p /.npm +RUN chown -R 1001:0 /.npm +# Build Frontend +COPY app/frontend ${APP_ROOT} +RUN chown -R 1001:0 ${APP_ROOT} +USER 1001 +WORKDIR ${APP_ROOT} RUN npm ci && npm run build # # Create the final container image # -FROM registry.access.redhat.com/ubi9/nodejs-18-minimal:1-51 +FROM ${BASE_IMAGE} +ARG APP_ROOT ENV APP_PORT=8080 \ NO_UPDATE_NOTIFIER=true -COPY --from=application /tmp/src/app ${HOME} -COPY --from=frontend /tmp/src/app/frontend/dist ${HOME}/frontend/dist -COPY .git ${HOME}/.git -WORKDIR ${HOME} +# NPM Permission Fix +RUN mkdir -p /.npm +RUN chown -R 1001:0 /.npm + +# Install File Structure +COPY --from=app ${APP_ROOT} ${APP_ROOT} +COPY --from=frontend ${APP_ROOT}/dist ${APP_ROOT}/frontend/dist +COPY .git ${APP_ROOT}/.git +WORKDIR ${APP_ROOT} EXPOSE ${APP_PORT} -CMD ["npm", "run", "start"] +CMD ["node", "./bin/www"] diff --git a/app/frontend/lcov-fix.js b/app/frontend/lcov-fix.mjs similarity index 100% rename from app/frontend/lcov-fix.js rename to app/frontend/lcov-fix.mjs diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json index 2efc234..436ab77 100644 --- a/app/frontend/package-lock.json +++ b/app/frontend/package-lock.json @@ -25,7 +25,7 @@ "axios": "^1.6.7", "core-js": "^3.36.0", "date-fns": "^3.6.0", - "keycloak-js": "^24.0.2", + "keycloak-js": "^20.0.1", "lodash": "^4.17.21", "nprogress": "^0.2.0", "vue": "2.7.16", @@ -7372,7 +7372,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, "funding": [ { "type": "github", @@ -15615,9 +15614,9 @@ } }, "node_modules/js-sha256": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.0.tgz", - "integrity": "sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -15807,21 +15806,13 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "engines": { - "node": ">=18" - } - }, "node_modules/keycloak-js": { - "version": "24.0.2", - "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-24.0.2.tgz", - "integrity": "sha512-V2N8cSz3NfON98XHp+DCzvrb1WW35JalL5Zphe/uoVWOxcof7v522Yz9Q2O3BqXqXP3V/H9ml6o24BwwtXUTGA==", + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-20.0.5.tgz", + "integrity": "sha512-7+M5Uni4oNlAmbjM/lDJzFHu2+PGqU6/bvmTBuQssE1fJ7ZyNeCRHgFoaVfFpIU3m6aAFwPUko4lVcn4kPXP5Q==", "dependencies": { - "js-sha256": "^0.11.0", - "jwt-decode": "^4.0.0" + "base64-js": "^1.5.1", + "js-sha256": "^0.9.0" } }, "node_modules/keyv": { diff --git a/app/frontend/package.json b/app/frontend/package.json index eb4ccd8..a929cf7 100644 --- a/app/frontend/package.json +++ b/app/frontend/package.json @@ -1 +1,70 @@ -{"name":"ches-showcase-frontend","version":"1.0.0","private":true,"license":"Apache-2.0","scripts":{"serve":"vue-cli-service serve","build":"vue-cli-service build","test":"npm run test:unit","test:unit":"vue-cli-service test:unit --verbose --verbose --forceExit --detectOpenHandles --maxWorkers=10","lint":"vue-cli-service lint","lint:fix":"vue-cli-service lint --fix","pretest":"npm run lint","clean":"rm -rf coverage dist **/e2e/videos","purge":"rm -rf node_modules","rebuild":"npm run clean && npm run build","reinstall":"npm run purge && npm install"},"dependencies":{"@bcgov/bc-sans":"^2.1.0","@ckeditor/ckeditor5-basic-styles":"^41.2.1","@ckeditor/ckeditor5-dev-utils":"^27.1.1","@ckeditor/ckeditor5-dev-webpack-plugin":"^31.1.13","@ckeditor/ckeditor5-editor-classic":"^41.2.1","@ckeditor/ckeditor5-essentials":"^41.2.1","@ckeditor/ckeditor5-link":"^41.2.1","@ckeditor/ckeditor5-paragraph":"^41.2.1","@ckeditor/ckeditor5-source-editing":"^41.2.1","@ckeditor/ckeditor5-table":"^41.2.1","@ckeditor/ckeditor5-theme-lark":"^41.2.1","@ckeditor/ckeditor5-vue2":"^3.0.1","@vue/cli-plugin-vuex":"^4.5.19","axios":"^1.6.7","core-js":"^3.36.0","date-fns":"^3.6.0","keycloak-js":"^24.0.2","lodash":"^4.17.21","nprogress":"^0.2.0","vue":"2.7.16","vue-router":"^3.6.5","vuetify":"^2.6.12","vuex":"^3.6.2","vuex-map-fields":"^1.4.1","vuex-persistedstate":"^4.1.0","xlsx":"^0.18.5"},"devDependencies":{"@babel/eslint-parser":"^7.5.4","@vue/cli-plugin-babel":"^5.0.8","@vue/cli-plugin-eslint":"^5.0.8","@vue/cli-plugin-router":"^5.0.8","@vue/cli-plugin-unit-jest":"^5.0.8","@vue/cli-plugin-vuex":"^5.0.8","@vue/cli-service":"^5.0.8","@vue/test-utils":"^1.3.6","@vue/vue2-jest":"^27.0.0","babel-eslint":"^10.1.0","eslint":"^8.57.0","eslint-plugin-prettier":"^5.1.3","eslint-plugin-vue":"^9.23.0","eslint-plugin-vuetify":"^1.0.1","prettier":"^3.2.5","sass":"< 1.33.0","sass-loader":"^14.1.1","vue-cli-plugin-vuetify":"^2.5.8","vue-template-compiler":"^2.7.16","vuetify-loader":"^1.9.2"}} +{ + "name": "ches-showcase-frontend", + "version": "1.0.0", + "private": true, + "license": "Apache-2.0", + "scripts": { + "serve": "vue-cli-service serve", + "build": "vue-cli-service build", + "test": "npm run test:unit", + "test:unit": "vue-cli-service test:unit --verbose --verbose --forceExit --detectOpenHandles --maxWorkers=10", + "lint": "vue-cli-service lint", + "lint:fix": "vue-cli-service lint --fix", + "pretest": "npm run lint", + "posttest": "node ./lcov-fix.mjs", + "clean": "rm -rf coverage dist **/e2e/videos", + "purge": "rm -rf node_modules", + "rebuild": "npm run clean && npm run build", + "reinstall": "npm run purge && npm install" + }, + "dependencies": { + "@bcgov/bc-sans": "^2.1.0", + "@ckeditor/ckeditor5-basic-styles": "^41.2.1", + "@ckeditor/ckeditor5-dev-utils": "^27.1.1", + "@ckeditor/ckeditor5-dev-webpack-plugin": "^31.1.13", + "@ckeditor/ckeditor5-editor-classic": "^41.2.1", + "@ckeditor/ckeditor5-essentials": "^41.2.1", + "@ckeditor/ckeditor5-link": "^41.2.1", + "@ckeditor/ckeditor5-paragraph": "^41.2.1", + "@ckeditor/ckeditor5-source-editing": "^41.2.1", + "@ckeditor/ckeditor5-table": "^41.2.1", + "@ckeditor/ckeditor5-theme-lark": "^41.2.1", + "@ckeditor/ckeditor5-vue2": "^3.0.1", + "@vue/cli-plugin-vuex": "^4.5.19", + "axios": "^1.6.7", + "core-js": "^3.36.0", + "date-fns": "^2.29.3", + "keycloak-js": "^20.0.1", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "vue": "2.7.16", + "vue-router": "^3.6.5", + "vuetify": "^2.6.12", + "vuex": "^3.6.2", + "vuex-map-fields": "^1.4.1", + "vuex-persistedstate": "^4.1.0", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.5.4", + "@vue/cli-plugin-babel": "^5.0.8", + "@vue/cli-plugin-eslint": "^5.0.8", + "@vue/cli-plugin-router": "^5.0.8", + "@vue/cli-plugin-unit-jest": "^5.0.8", + "@vue/cli-plugin-vuex": "^5.0.8", + "@vue/cli-service": "^5.0.8", + "@vue/test-utils": "^1.3.6", + "@vue/vue2-jest": "^27.0.0", + "babel-eslint": "^10.1.0", + "eslint": "^8.57.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-vue": "^9.23.0", + "eslint-plugin-vuetify": "^1.0.1", + "prettier": "^3.2.5", + "sass": "< 1.33.0", + "sass-loader": "^14.1.1", + "vue-cli-plugin-vuetify": "^2.5.8", + "vue-template-compiler": "^2.7.16", + "vuetify-loader": "^1.9.2" + } +} diff --git a/app/frontend/src/views/merge/MergeAbout.vue b/app/frontend/src/views/merge/MergeAbout.vue index 9026d7c..a9ef722 100644 --- a/app/frontend/src/views/merge/MergeAbout.vue +++ b/app/frontend/src/views/merge/MergeAbout.vue @@ -4,78 +4,136 @@

CHES Showcase - Mail Merge

-

The Mail Merge page demonstrates the email merge and templating capabilites of CHES.
- CHES supports sending a list of recipients (to, cc, bcc) a templated subject and body.
- This allows an application to send personalized emails in batch mode.

+

+ The Mail Merge page demonstrates the email merge and templating + capabilites of CHES.
+ CHES supports sending a list of recipients (to, cc, bcc) a templated + subject and body.
+ This allows an application to send personalized emails in batch + mode. +

-

To showcase CHES, we have added some nice features to turn an Excel spreadsheet or CVS file into a - CHES Mail Merge request. See below for some sample data and a template you can use as a guide to - creating your own data and templates. It is advised that you fix the data in your spreadsheet and not - in the JSON editor. +

+ To showcase CHES, we have added some nice features to turn an Excel + spreadsheet or CVS file into a CHES Mail Merge request. See below + for some sample data and a template you can use as a guide to + creating your own data and templates. It is advised that you fix the + data in your spreadsheet and not in the JSON editor.

- The Excel spreadsheet/CVS file parser does best guesses on dates and times, it cannot parse and understand all - formats. If you encounter difficulties with dates and times from Excel, ensure your date and time stamp columns - are formatted properly ("Short Date", "Long Date" or "Custom yyyy-mm-dd h:mm" not - "General"), or convert your sheet to CSV and format your dates to "yyyy-mm-dd" and time - stamps to "yyyy-mm-dd h:mm". + The Excel spreadsheet/CVS file parser does best guesses on dates and + times, it cannot parse and understand all formats. If you encounter + difficulties with dates and times from Excel, ensure your date and + time stamp columns are formatted properly ("Short Date", + "Long Date" or "Custom yyyy-mm-dd h:mm" not + "General"), or convert your sheet to CSV and format your + dates to "yyyy-mm-dd" and time stamps to "yyyy-mm-dd + h:mm".

Guide

  1. Download a data file and a template from the examples.
  2. -
  3. On the merge screen, drag/upload the data file into the contexts field.
  4. +
  5. + On the merge screen, drag/upload the data file into the contexts + field. +
  6. Review the contents of the table.
  7. -
  8. Click the JSON radio button to review the contents - this the context list sent to CHES.
  9. -
  10. For the body, use the html format editor.
    - Click the 'Source' button in the editor's toolbar to insert the html from the example template
  11. -
  12. For the Subject, enter "ATTN: {{scope}}!"
  13. +
  14. + Click the JSON radio button to review the contents - this the + context list sent to CHES. +
  15. +
  16. + For the body, use the html format editor.
    + Click the 'Source' button in the editor's toolbar to insert the + html from the example template +
  17. +
  18. + For the Subject, enter '{{ scope }}' +
  19. Click Preview

Notes

    -
  • Review the csv file and look over the Excel table headings. Note that MSSC has - removed "bad" characters (CHES accepts only underscore and alphanumeric characters for - context variable names). +
  • + Review the csv file and look over the Excel table headings. Note + that MSSC has removed "bad" characters (CHES accepts + only underscore and alphanumeric characters for context variable + names). +
  • +
  • + Also note the last 5 columns: to, cc, bcc, tag, and delayTs. The + naming of these columns is important (not their location in the + file). These are special fields that are part of building the + message, but are not used in the context (what populates each body + and subject template).
  • -
  • Also note the last 5 columns: to, cc, bcc, tag, and delayTs. The naming of these columns is - important (not their location in the file). These are special fields that are part of building the - message, but are not used in the context (what populates each body and subject template). +
  • + To is required. It can be a comma-separated list of email + addresses.
  • -
  • To is required. It can be a comma-separated list of email addresses.
  • -
  • Cc and Bcc are not required. They can be comma-separated lists of email addresses.
  • -
  • Tag can be used the help group messages and make it easier to search for them in CHES (for - example, to determine status) +
  • + Cc and Bcc are not required. They can be comma-separated lists of + email addresses.
  • -
  • Delay TS is a timestamp of when to deliver the message. Leave empty if you wish to deliver now. +
  • + Tag can be used the help group messages and make it easier to + search for them in CHES (for example, to determine status)
  • -
  • Any other field that contains a date, the Excel parser will translate to YYYY-MM-DD. Look in the - csv file to see various formats it can translate from CSV. Note: the last line in the CSV - has date formats that cannot be converted. +
  • + Delay TS is a timestamp of when to deliver the message. Leave + empty if you wish to deliver now.
  • -
  • If a field contains a date and time, and ends with ts (see endDateTs), MSSC will translate to - YYYY-MM-DD hh:mm. This is local time. +
  • + Any other field that contains a date, the Excel parser will + translate to YYYY-MM-DD. Look in the csv file to see various + formats it can translate from CSV. Note: the last + line in the CSV has date formats that cannot be converted.
  • -
  • Note that delayTs appears in the JSON as a number. This is the date and time as milliseconds in - UTC. This is what CHES expects. +
  • + If a field contains a date and time, and ends with ts (see + endDateTs), MSSC will translate to YYYY-MM-DD hh:mm. This is local + time.
  • -
  • Also, note down the left hand side of the body is a listing of the variables you can use in the - template. These are the CSV headings (altered if needed by MSSC) +
  • + Note that delayTs appears in the JSON as a number. This is the + date and time as milliseconds in UTC. This is what CHES expects. +
  • +
  • + Also, note down the left hand side of the body is a listing of the + variables you can use in the template. These are the CSV headings + (altered if needed by MSSC)
  • -
  • In Preview, you can navigate through all the messages that will be delivered.
  • -
  • Important: If you alter the JSON, the Excel data table will go away. This is a - one way operation (excel to JSON). +
  • + In Preview, you can navigate through all the messages that will be + delivered. +
  • +
  • + Important: If you alter the JSON, the Excel data + table will go away. This is a one way operation (excel to JSON).
@@ -87,10 +145,10 @@ diff --git a/app/lcov-fix.js b/app/lcov-fix.js index 24d0186..7c22d19 100644 --- a/app/lcov-fix.js +++ b/app/lcov-fix.js @@ -7,7 +7,7 @@ fs.readFile(file, 'utf8', (err, data) => { if (err) { return console.error(err); // eslint-disable-line no-console } - const result = data.replace(/src/g, `${process.cwd()}/src`); + const result = data.replace(/SF:/g, `SF:${process.cwd()}/`); fs.writeFile(file, result, 'utf8', err => { if (err) return console.error(err); // eslint-disable-line no-console