diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e19ace544..5871b2903 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -ARG VARIANT="18.20.3-bookworm" +ARG VARIANT="18.20.4-bookworm" FROM node:${VARIANT} # not much in here, could acheive this another way for sure... diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6ed27d686..124f8664e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "dockerfile": "Dockerfile", "context": "..", "args": { - "VARIANT": "18.20.3-bookworm" + "VARIANT": "18.20.4-bookworm" } }, diff --git a/.github/actions/build-push-container/action.yaml b/.github/actions/build-push-container/action.yaml index 7fe44f576..aa78c80aa 100644 --- a/.github/actions/build-push-container/action.yaml +++ b/.github/actions/build-push-container/action.yaml @@ -117,7 +117,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 }} @@ -125,7 +125,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 }} @@ -133,7 +133,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 }} @@ -151,7 +151,7 @@ runs: - name: Build and Push to Container Registry id: builder - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v6 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 5486e6d6c..e2bdd6ad9 100644 --- a/.github/actions/deploy-to-environment/action.yaml +++ b/.github/actions/deploy-to-environment/action.yaml @@ -38,22 +38,22 @@ inputs: ref: description: The checkout ref id required: false - default: '' + default: "" runs: using: composite steps: - name: Checkout repository from pull request - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} if: ${{ inputs.ref != '' }} - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 if: ${{ inputs.ref == '' }} - name: Login to OpenShift Cluster - uses: jasonchung1871/oc-login@v1.1.2 + uses: redhat-actions/oc-login@v1 with: openshift_server_url: ${{ inputs.openshift_server }} diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 6396bd24e..97636bf9f 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/.deploy.yaml b/.github/workflows/pr_deploy.yaml similarity index 75% rename from .github/workflows/.deploy.yaml rename to .github/workflows/pr_deploy.yaml index fe754ff01..118ec31fa 100644 --- a/.github/workflows/.deploy.yaml +++ b/.github/workflows/pr_deploy.yaml @@ -1,4 +1,4 @@ -name: Deploy PR +name: PR Deploy run-name: Deploy PR-${{ github.event.inputs.pr-number }} env: @@ -9,7 +9,7 @@ on: inputs: pr-number: description: Pull request number - required: false + required: true type: string concurrency: @@ -37,6 +37,7 @@ jobs: echo "JOB_NAME=master" >> "$GITHUB_OUTPUT" echo "ROUTE_PATH=/app" >> "$GITHUB_OUTPUT" echo "URL=https://$ACRONYM-dev.apps.silver.devops.gov.bc.ca" >> "$GITHUB_OUTPUT" + - name: Final variables id: vars env: @@ -45,17 +46,10 @@ jobs: REF=refs/pull/$PR_NUMBER/head echo REF:$REF echo "ref=$REF" >> $GITHUB_OUTPUT - if [[ "$PR_NUMBER" != '' ]]; then - echo "APP_TITLE=${{ steps.default-vars.outputs.APP_TITLE }} - PR-$PR_NUMBER" >> "$GITHUB_OUTPUT" - echo "JOB_NAME=pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" - echo "ROUTE_PATH=/pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" - echo "URL=${{ steps.default-vars.outputs.URL }}/pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" - else - echo "APP_TITLE=${{ steps.default-vars.outputs.APP_TITLE }}" >> "$GITHUB_OUTPUT" - echo "JOB_NAME=${{ steps.default-vars.outputs.JOB_NAME }}" >> "$GITHUB_OUTPUT" - echo "ROUTE_PATH=${{ steps.default-vars.outputs.ROUTE_PATH }}" >> "$GITHUB_OUTPUT" - echo "URL=${{ steps.default-vars.outputs.URL }}/app" >> "$GITHUB_OUTPUT" - fi + echo "APP_TITLE=${{ steps.default-vars.outputs.APP_TITLE }} - PR-$PR_NUMBER" >> "$GITHUB_OUTPUT" + echo "JOB_NAME=pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" + echo "ROUTE_PATH=/pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" + echo "URL=${{ steps.default-vars.outputs.URL }}/pr-$PR_NUMBER" >> "$GITHUB_OUTPUT" build: name: Build & Push @@ -67,10 +61,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ needs.set-vars.outputs.ref }} - if: ${{ needs.set-vars.outputs.ref != '' }} - - name: Checkout repository - uses: actions/checkout@v4 - if: ${{ needs.set-vars.outputs.ref == '' }} - name: Build & Push uses: ./.github/actions/build-push-container with: @@ -97,10 +87,6 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ needs.set-vars.outputs.ref }} - if: ${{ needs.set-vars.outputs.ref != '' }} - - name: Checkout repository - uses: actions/checkout@v4 - if: ${{ needs.set-vars.outputs.ref == '' }} - name: Deploy to environment uses: ./.github/actions/deploy-to-environment with: @@ -118,9 +104,11 @@ jobs: ref: ${{ needs.set-vars.outputs.ref }} - name: Release Comment on PR uses: marocchino/sticky-pull-request-comment@v2 - if: ${{ github.event.inputs.pr-number }} != '' && success() + if: success() with: header: release + hide_and_recreate: true + hide_classify: "OUTDATED" message: | Release ${{ github.sha }} deployed at number: ${{ github.event.inputs.pr-number }} diff --git a/.github/workflows/.close-pr.yaml b/.github/workflows/pr_undeploy.yaml similarity index 79% rename from .github/workflows/.close-pr.yaml rename to .github/workflows/pr_undeploy.yaml index bc0ac2d69..511127605 100644 --- a/.github/workflows/.close-pr.yaml +++ b/.github/workflows/pr_undeploy.yaml @@ -1,4 +1,5 @@ -name: Close pull request deployment +name: PR Undeploy +run-name: Undeploy PR-${{ github.event.inputs.pr-number }} env: ACRONYM: chefs @@ -7,19 +8,9 @@ on: workflow_dispatch: inputs: pr-number: - description: Pull request number, leave blank for dev/test/prod deployment - required: false - type: string - environment: - description: Environment name; choose dev for PR + description: Pull request number required: true - type: choice - options: - - dev - - test - - prod - default: dev - + type: string jobs: remove-pr-dev: diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml index e1ecef902..9e03ebfea 100644 --- a/.github/workflows/unit-tests.yaml +++ b/.github/workflows/unit-tests.yaml @@ -21,16 +21,16 @@ jobs: version: [18] steps: - name: Checkout Repository - uses: actions/checkout@v3 + 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.version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.version }} - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-app env: cache-name: cache-node-modules @@ -50,7 +50,7 @@ jobs: CI: true - name: Save Coverage Results if: matrix.version == 18 - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-app path: ${{ github.workspace }}/app/coverage @@ -81,13 +81,13 @@ jobs: version: [18] steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.version }} - name: Cache node modules - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache-frontend env: cache-name: cache-node-modules @@ -107,7 +107,7 @@ jobs: CI: true - name: Save Coverage Results if: matrix.version == 18 - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-frontend path: ${{ github.workspace }}/app/frontend/coverage @@ -133,11 +133,11 @@ jobs: timeout-minutes: 10 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Restore Coverage Results - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: Publish code coverage - uses: paambaati/codeclimate-action@v3.2.0 + uses: paambaati/codeclimate-action@v8 env: CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} with: diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index 343dc534c..000000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -nodejs 18.18.2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40bf0c032..9025a75c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,7 @@ The stability of the CHEFS application is of highest importance. - Please bring your change ideas to the team before starting work - Contributors must follow the [Code of Conduct](CODE-OF-CONDUCT.md) - Changes must include test coverage, documentation, and comments +- If changes to the code alter the functionality of CHEFS, please update the [documentation](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs) by raising a pull request in the CHEFS tech docs [repository](https://github.com/bcgov/common-hosted-form-service-techdocs). - The repository guardians review all changes and may ask for revisions ## Contributing code @@ -20,4 +21,4 @@ Government employees, public and members of the private sector are encouraged to All contributors retain the original copyright to their stuff, but by contributing to this project, you grant a world-wide, royalty-free, perpetual, irrevocable, non-exclusive, transferable license to all users **under the terms of the [license](./LICENSE) under which this project is distributed**. -To set up CHEFS on your workstation, visit the [Developer](https://github.com/bcgov/common-hosted-form-service/wiki/Developer) Wiki page. +To set up CHEFS on your workstation, visit the [developer documentation](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/Developer/). diff --git a/Dockerfile b/Dockerfile index c8497ace6..bc4883790 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/node:18.20.3-alpine3.20 +FROM docker.io/node:18.20.4-alpine3.20 ENV NO_UPDATE_NOTIFIER=true WORKDIR /opt/app-root/src/app diff --git a/README.md b/README.md index 719abfe94..2d2482d09 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # Common Hosted Form Service [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![img](https://img.shields.io/badge/Lifecycle-Stable-97ca00)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.md) +[Common Hosted Form Service](https://submit.digital.gov.bc.ca/app) is a web-based application designed for creating web forms and managing collected data. It is a free service available to all B.C. government employees and contractors with an IDIR account. For more information, visit the [CHEFS documentation](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs). + +[Watch a series of short videos](https://www.youtube.com/playlist?list=PL9CV_8JBQHirsQAShw45PZeU1CkU88Q53) to learn how to build your first form. + + ![Tests](https://github.com/bcgov/common-hosted-form-service/workflows/Tests/badge.svg) [![Maintainability](https://api.codeclimate.com/v1/badges/950b1d6c61567a1da227/maintainability)](https://codeclimate.com/github/bcgov/common-hosted-form-service/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/950b1d6c61567a1da227/test_coverage)](https://codeclimate.com/github/bcgov/common-hosted-form-service/test_coverage) -Create, edit and publish forms. - ## Directory Structure .devcontainer - Visual Studio Code devcontainer and local environment config @@ -42,12 +45,10 @@ Create, edit and publish forms. - [CHEFS Load Test Readme](tests/load/load-test/README.md) - [Devops Tools Setup](https://github.com/bcgov/nr-showcase-devops-tools) - [Security Reporting](SECURITY.md) -- [Product Roadmap](https://github.com/bcgov/common-hosted-form-service/wiki/Product-Roadmap) +- [Product Roadmap](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/Product-Roadmap/) ## Help, Problems, and Feature Requests -Visit the [CHEFS Wiki](https://github.com/bcgov/common-hosted-form-service/wiki/) for help on using CHEFS. - To report a problem with CHEFS please create a [GitHub Issue](https://github.com/bcgov/common-hosted-form-service/issues). Feature requests can be found in the [CHEFS Feedback](https://chefs-fider.apps.silver.devops.gov.bc.ca/) - vote for a feature you want in CHEFS, or add a new feature that hasn't been requested. @@ -72,4 +73,4 @@ Please note that this project is released with a [Contributor Code of Conduct](C 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. + limitations under the License. \ No newline at end of file diff --git a/app/frontend/src/components/admin/AdminAPIsTable.vue b/app/frontend/src/components/admin/AdminAPIsTable.vue index cafb69d10..4ab8ea0d6 100644 --- a/app/frontend/src/components/admin/AdminAPIsTable.vue +++ b/app/frontend/src/components/admin/AdminAPIsTable.vue @@ -5,7 +5,6 @@ import { i18n } from '~/internationalization'; import { useAdminStore } from '~/store/admin'; import { useFormStore } from '~/store/form'; -import { Ministries } from '~/utils/constants'; import BaseDialog from '~/components/base/BaseDialog.vue'; export default { @@ -35,12 +34,6 @@ export default { computed: { ...mapState(useAdminStore, ['externalAPIList', 'externalAPIStatusCodes']), ...mapState(useFormStore, ['isRTL', 'lang']), - ministryList() { - return Ministries.map((ministry) => ({ - id: ministry.id, - text: i18n.t(`trans.ministries.${ministry.id}`), - })); - }, headers() { return [ { @@ -48,20 +41,33 @@ export default { align: 'start', key: 'ministry', }, + { + title: i18n.t('trans.adminAPIsTable.ministryName'), + align: 'start', + key: 'ministryName', + // we don't want to see this (too long) + // but we need it for searching, so it needs to be in the DOM + headerProps: { + class: 'hidden', + }, + cellProps: { + class: 'hidden', + }, + }, { title: i18n.t('trans.adminAPIsTable.formName'), align: 'start', key: 'formName', }, { - title: i18n.t('trans.adminAPIsTable.name'), + title: i18n.t('trans.adminAPIsTable.formId'), align: 'start', - key: 'name', + key: 'formId', }, { - title: i18n.t('trans.adminAPIsTable.endpointUrl'), + title: i18n.t('trans.adminAPIsTable.name'), align: 'start', - key: 'endpointUrl', + key: 'name', }, { title: i18n.t('trans.adminAPIsTable.display'), @@ -77,6 +83,13 @@ export default { }, ]; }, + items() { + // add ministry name to objects so we can search on them + return this.externalAPIList.map((x) => ({ + ...x, + ministryName: this.getMinistryName(x), + })); + }, }, async mounted() { await this.getExternalAPIStatusCodes(); @@ -89,6 +102,9 @@ export default { 'updateExternalAPI', 'getExternalAPIStatusCodes', ]), + getMinistryName(item) { + return item.ministry ? i18n.t(`trans.ministries.${item.ministry}`) : ''; + }, resetEditDialog() { this.editDialog = { title: '', @@ -107,9 +123,7 @@ export default { handleEdit(item) { this.resetEditDialog(); this.editDialog.item = { ...item }; - this.editDialog.item.ministryText = this.ministryList.find( - (x) => x.id === item.ministry - )['text']; + this.editDialog.item.ministryText = this.getMinistryName(item); this.editDialog.title = i18n.t('trans.adminAPIsTable.editTitle'); this.editDialog.show = true; }, @@ -162,24 +176,27 @@ export default { hover :headers="headers" item-key="title" - :items="externalAPIList" + :items="items" :search="search" :loading="loading" :loading-text="$t('trans.adminAPIsTable.loadingText')" :lang="lang" > + + - diff --git a/app/frontend/src/components/base/BaseFilter.vue b/app/frontend/src/components/base/BaseFilter.vue index ed6519895..fedc171a4 100644 --- a/app/frontend/src/components/base/BaseFilter.vue +++ b/app/frontend/src/components/base/BaseFilter.vue @@ -62,7 +62,7 @@ const inputFilter = ref(''); const inputFilterPlaceholder = properties.inputFilterPlaceholder || t('trans.baseFilter.exampleText2'); const inputSaveButtonText = - properties.inputFilterPlaceholder || t('trans.baseFilter.filter'); + properties.inputSaveButtonText || t('trans.baseFilter.filter'); const selectedData = ref([]); const { isRTL } = storeToRefs(useFormStore()); diff --git a/app/frontend/src/components/bcgov/BCGovNavBar.vue b/app/frontend/src/components/bcgov/BCGovNavBar.vue index e9e1d7e89..1beef9785 100755 --- a/app/frontend/src/components/bcgov/BCGovNavBar.vue +++ b/app/frontend/src/components/bcgov/BCGovNavBar.vue @@ -60,7 +60,7 @@ const hasPrivileges = computed(() => {
  • {{ $t('trans.bCGovNavBar.help') }} { + document.body.removeChild(a); + URL.revokeObjectURL(a.href); + }); + } + }, + async uploadFile(file, config = {}) { + return fileService.uploadFile(file, config); + }, }, }; @@ -1086,7 +1150,18 @@ export default {