├── .codeclimate.yml
├── .devcontainer
├── Dockerfile
├── README.md
├── chefs_local
│ ├── config
│ │ ├── freshclam.conf
│ │ └── jetstream.conf
│ ├── docker-compose.yml
│ ├── local.sample.json
│ └── test.json
├── devcontainer.json
└── post-install.sh
├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
├── actions
│ ├── build-push-container
│ │ └── action.yaml
│ └── deploy-to-environment
│ │ └── action.yaml
├── pull_request_template.md
└── workflows
│ ├── clamav-image-build.yaml
│ ├── codeql-analysis.yaml
│ ├── cypress-ci.yaml
│ ├── on_push.yaml
│ ├── pr_deploy.yaml
│ ├── pr_undeploy.yaml
│ ├── reusable-owasp-zap.yaml
│ └── unit-tests.yaml
├── .gitignore
├── .vscode
├── README.md
├── launch.json
└── tasks.json
├── CNAME
├── CODE-OF-CONDUCT.md
├── COMPLIANCE.yaml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── _config.yml
├── app
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── README.md
├── app.js
├── bin
│ └── www
├── config
│ ├── custom-environment-variables.json
│ ├── default.json
│ ├── production.json
│ └── test.json
├── frontend
│ ├── .browserslistrc
│ ├── .eslintignore
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── .prettierignore
│ ├── .prettierrc
│ ├── README.md
│ ├── component-update.js
│ ├── index.html
│ ├── jsconfig.json
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── images
│ │ │ ├── drag_drop.png
│ │ │ ├── quickstart.png
│ │ │ └── team-management.png
│ │ └── index.html
│ ├── src
│ │ ├── App.vue
│ │ ├── assets
│ │ │ ├── images
│ │ │ │ ├── bc_logo.svg
│ │ │ │ ├── bc_logo_print.svg
│ │ │ │ ├── bc_logo_square.svg
│ │ │ │ └── drag-drop-demo.gif
│ │ │ └── scss
│ │ │ │ └── style.scss
│ │ ├── components
│ │ │ ├── admin
│ │ │ │ ├── AddOwner.vue
│ │ │ │ ├── AdminAPIsTable.vue
│ │ │ │ ├── AdminFormsTable.vue
│ │ │ │ ├── AdminPage.vue
│ │ │ │ ├── AdminUsersTable.vue
│ │ │ │ ├── AdminVersions.vue
│ │ │ │ ├── AdministerForm.vue
│ │ │ │ ├── AdministerUser.vue
│ │ │ │ ├── Dashboard.vue
│ │ │ │ ├── Developer.vue
│ │ │ │ └── FormComponentsProactiveHelp.vue
│ │ │ ├── base
│ │ │ │ ├── BaseAuthButton.vue
│ │ │ │ ├── BaseCopyToClipboard.vue
│ │ │ │ ├── BaseDialog.vue
│ │ │ │ ├── BaseFilter.vue
│ │ │ │ ├── BaseImagePopout.vue
│ │ │ │ ├── BaseInfoCard.vue
│ │ │ │ ├── BaseInternationalization.vue
│ │ │ │ ├── BaseNotificationBar.vue
│ │ │ │ ├── BaseNotificationContainer.vue
│ │ │ │ ├── BasePanel.vue
│ │ │ │ ├── BasePrintButton.vue
│ │ │ │ └── BaseSecure.vue
│ │ │ ├── bcgov
│ │ │ │ ├── BCGovAlertBanner.vue
│ │ │ │ ├── BCGovFooter.vue
│ │ │ │ ├── BCGovHeader.vue
│ │ │ │ └── BCGovNavBar.vue
│ │ │ ├── designer
│ │ │ │ ├── FloatButton.vue
│ │ │ │ ├── FormDesigner.vue
│ │ │ │ ├── FormDisclaimer.vue
│ │ │ │ ├── FormProfile.vue
│ │ │ │ ├── FormSettings.vue
│ │ │ │ ├── FormViewer.vue
│ │ │ │ ├── FormViewerActions.vue
│ │ │ │ ├── FormViewerMultiUpload.vue
│ │ │ │ ├── FormsTable.vue
│ │ │ │ ├── profile
│ │ │ │ │ ├── FormAPIProfile.vue
│ │ │ │ │ ├── FormDeploymentProfile.vue
│ │ │ │ │ ├── FormLabelProfile.vue
│ │ │ │ │ ├── FormMinistryProfile.vue
│ │ │ │ │ └── FormUseCaseProfile.vue
│ │ │ │ └── settings
│ │ │ │ │ ├── FormAccessSettings.vue
│ │ │ │ │ ├── FormEventStreamSettings.vue
│ │ │ │ │ ├── FormFunctionalitySettings.vue
│ │ │ │ │ ├── FormGeneralSettings.vue
│ │ │ │ │ ├── FormMetadataSettings.vue
│ │ │ │ │ ├── FormScheduleSettings.vue
│ │ │ │ │ └── FormSubmissionSettings.vue
│ │ │ ├── forms
│ │ │ │ ├── ExportSubmissions.vue
│ │ │ │ ├── FormSubmission.vue
│ │ │ │ ├── PrintOptions.vue
│ │ │ │ ├── RequestReceipt.vue
│ │ │ │ ├── SubmissionsTable.vue
│ │ │ │ ├── manage
│ │ │ │ │ ├── AddTeamMember.vue
│ │ │ │ │ ├── ApiKey.vue
│ │ │ │ │ ├── DocumentTemplate.vue
│ │ │ │ │ ├── EmailManagement.vue
│ │ │ │ │ ├── EmailTemplate.vue
│ │ │ │ │ ├── ExternalAPIs.vue
│ │ │ │ │ ├── ManageForm.vue
│ │ │ │ │ ├── ManageFormActions.vue
│ │ │ │ │ ├── ManageLayout.vue
│ │ │ │ │ ├── ManageVersions.vue
│ │ │ │ │ ├── ShareForm.vue
│ │ │ │ │ ├── Subscription.vue
│ │ │ │ │ └── TeamManagement.vue
│ │ │ │ └── submission
│ │ │ │ │ ├── AuditHistory.vue
│ │ │ │ │ ├── DeleteSubmission.vue
│ │ │ │ │ ├── ManageSubmissionUsers.vue
│ │ │ │ │ ├── MySubmissionsActions.vue
│ │ │ │ │ ├── MySubmissionsTable.vue
│ │ │ │ │ ├── NotesPanel.vue
│ │ │ │ │ ├── StatusPanel.vue
│ │ │ │ │ ├── StatusTable.vue
│ │ │ │ │ ├── UserDuplicateSubmission.vue
│ │ │ │ │ └── UserSubmission.vue
│ │ │ └── infolinks
│ │ │ │ ├── GeneralLayout.vue
│ │ │ │ ├── ProactiveHelpDialog.vue
│ │ │ │ └── ProactiveHelpPreviewDialog.vue
│ │ ├── composables
│ │ │ ├── documentTemplate.js
│ │ │ ├── form.js
│ │ │ └── printOptions.js
│ │ ├── favicon.ico
│ │ ├── filters
│ │ │ └── index.js
│ │ ├── internationalization
│ │ │ ├── index.js
│ │ │ └── trans
│ │ │ │ ├── chefs
│ │ │ │ ├── ar
│ │ │ │ │ ├── ar.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── de
│ │ │ │ │ ├── de.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── en
│ │ │ │ │ ├── en.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── es
│ │ │ │ │ ├── es.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── fa
│ │ │ │ │ ├── fa.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── fr
│ │ │ │ │ ├── fr.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── hi
│ │ │ │ │ ├── hi.json
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ ├── it
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── it.json
│ │ │ │ ├── ja
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── ja.json
│ │ │ │ ├── ko
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── ko.json
│ │ │ │ ├── pa
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── pa.json
│ │ │ │ ├── pt
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── pt.json
│ │ │ │ ├── ru
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── ru.json
│ │ │ │ ├── tl
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── tl.json
│ │ │ │ ├── uk
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── uk.json
│ │ │ │ ├── vi
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── vi.json
│ │ │ │ ├── zh
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── zh.json
│ │ │ │ └── zhTW
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── zh-TW.json
│ │ │ │ ├── formio
│ │ │ │ └── formio.json
│ │ │ │ └── vuetify
│ │ │ │ └── locale
│ │ │ │ ├── README.md
│ │ │ │ ├── hi.js
│ │ │ │ ├── pa.js
│ │ │ │ └── tl.js
│ │ ├── main.js
│ │ ├── plugins
│ │ │ ├── templateExtensions.js
│ │ │ └── vuetify.js
│ │ ├── router.js
│ │ ├── services
│ │ │ ├── adminService.js
│ │ │ ├── apiKeyService.js
│ │ │ ├── encryptionKeyService.js
│ │ │ ├── eventStreamConfigService.js
│ │ │ ├── fileService.js
│ │ │ ├── formService.js
│ │ │ ├── index.js
│ │ │ ├── interceptors.js
│ │ │ ├── rbacService.js
│ │ │ ├── roleService.js
│ │ │ ├── userService.js
│ │ │ └── utilsService.js
│ │ ├── store
│ │ │ ├── admin.js
│ │ │ ├── app.js
│ │ │ ├── auth.js
│ │ │ ├── form.js
│ │ │ ├── identityProviders.js
│ │ │ ├── index.js
│ │ │ └── notification.js
│ │ ├── utils
│ │ │ ├── constants.js
│ │ │ ├── keycloak.js
│ │ │ ├── permissionUtils.js
│ │ │ └── transformUtils.js
│ │ └── views
│ │ │ ├── About.vue
│ │ │ ├── Admin.vue
│ │ │ ├── Error.vue
│ │ │ ├── File.vue
│ │ │ ├── Form.vue
│ │ │ ├── Login.vue
│ │ │ ├── NotFound.vue
│ │ │ ├── User.vue
│ │ │ ├── admin
│ │ │ ├── Form.vue
│ │ │ ├── Root.vue
│ │ │ └── User.vue
│ │ │ ├── file
│ │ │ └── Download.vue
│ │ │ ├── form
│ │ │ ├── Create.vue
│ │ │ ├── Design.vue
│ │ │ ├── Emails.vue
│ │ │ ├── Export.vue
│ │ │ ├── Manage.vue
│ │ │ ├── Preview.vue
│ │ │ ├── PublishForm.vue
│ │ │ ├── Submissions.vue
│ │ │ ├── Submit.vue
│ │ │ ├── Success.vue
│ │ │ ├── Teams.vue
│ │ │ └── View.vue
│ │ │ └── user
│ │ │ ├── Forms.vue
│ │ │ ├── History.vue
│ │ │ ├── Root.vue
│ │ │ ├── SubmissionDraftEdit.vue
│ │ │ ├── SubmissionDuplicate.vue
│ │ │ ├── SubmissionView.vue
│ │ │ └── Submissions.vue
│ ├── tests
│ │ └── unit
│ │ │ ├── App.spec.js
│ │ │ ├── components
│ │ │ ├── admin
│ │ │ │ ├── AddOwner.spec.js
│ │ │ │ ├── AdminAPIsTable.spec.js
│ │ │ │ ├── AdminFormsTable.spec.js
│ │ │ │ ├── AdminPage.spec.js
│ │ │ │ ├── AdminUsersTable.spec.js
│ │ │ │ ├── AdminVersions.spec.js
│ │ │ │ ├── AdministerForm.spec.js
│ │ │ │ ├── AdministerUser.spec.js
│ │ │ │ ├── Dashboard.spec.js
│ │ │ │ ├── Developer.spec.js
│ │ │ │ └── FormComponentsProactiveHelp.spec.js
│ │ │ ├── base
│ │ │ │ ├── BaseAuthButton.spec.js
│ │ │ │ ├── BaseCopyToClipboard.spec.js
│ │ │ │ ├── BaseDialog.spec.js
│ │ │ │ ├── BaseFilter.spec.js
│ │ │ │ ├── BaseImagePopout.spec.js
│ │ │ │ ├── BaseInternationalization.spec.js
│ │ │ │ ├── BaseNotificationBar.spec.js
│ │ │ │ ├── BaseNotificationContainer.spec.js
│ │ │ │ ├── BasePrintButton.spec.js
│ │ │ │ └── BaseSecure.spec.js
│ │ │ ├── bcgov
│ │ │ │ ├── BCGovAlertBanner.spec.js
│ │ │ │ ├── BCGovFooter.spec.js
│ │ │ │ ├── BCGovHeader.spec.js
│ │ │ │ └── BCGovNavBar.spec.js
│ │ │ ├── designer
│ │ │ │ ├── FloatButton.spec.js
│ │ │ │ ├── FormDesigner.spec.js
│ │ │ │ ├── FormDisclaimer.spec.js
│ │ │ │ ├── FormViewer.spec.js
│ │ │ │ ├── FormViewerActions.spec.js
│ │ │ │ ├── FormViewerMultiUpload.spec.js
│ │ │ │ ├── FormsTable.spec.js
│ │ │ │ ├── profile
│ │ │ │ │ ├── FormAPIProfile.spec.js
│ │ │ │ │ ├── FormDeploymentProfile.spec.js
│ │ │ │ │ ├── FormLabelProfile.spec.js
│ │ │ │ │ └── FormUseCaseProfile.spec.js
│ │ │ │ └── settings
│ │ │ │ │ ├── FormAccessSettings.spec.js
│ │ │ │ │ ├── FormEventStreamSettings.spec.js
│ │ │ │ │ ├── FormFunctionalitySettings.spec.js
│ │ │ │ │ ├── FormMetadataSettings.spec.js
│ │ │ │ │ ├── FormScheduleSettings.spec.js
│ │ │ │ │ └── FormSubmissionSettings.spec.js
│ │ │ ├── forms
│ │ │ │ ├── ExportSubmissions.spec.js
│ │ │ │ ├── FormSubmission.spec.js
│ │ │ │ ├── PrintOptions.spec.js
│ │ │ │ ├── RequestReceipt.spec.js
│ │ │ │ ├── SubmissionsTable.spec.js
│ │ │ │ ├── manage
│ │ │ │ │ ├── AddTeamMember.spec.js
│ │ │ │ │ ├── ApiKey.spec.js
│ │ │ │ │ ├── DocumentTemplate.spec.js
│ │ │ │ │ ├── EmailTemplate.spec.js
│ │ │ │ │ ├── ManageForm.spec.js
│ │ │ │ │ ├── ManageFormActions.spec.js
│ │ │ │ │ ├── ManageLayout.spec.js
│ │ │ │ │ ├── ManageVersions.spec.js
│ │ │ │ │ ├── ShareForm.spec.js
│ │ │ │ │ ├── Subscription.spec.js
│ │ │ │ │ └── TeamManagement.spec.js
│ │ │ │ └── submission
│ │ │ │ │ ├── AuditHistory.spec.js
│ │ │ │ │ ├── DeleteSubmission.spec.js
│ │ │ │ │ ├── ManageSubmissionUsers.spec.js
│ │ │ │ │ ├── MySubmissionsActions.spec.js
│ │ │ │ │ ├── MySubmissionsTable.spec.js
│ │ │ │ │ ├── NotesPanel.spec.js
│ │ │ │ │ ├── StatusPanel.spec.js
│ │ │ │ │ ├── StatusTable.spec.js
│ │ │ │ │ ├── UserDuplicateSubmission.spec.js
│ │ │ │ │ └── UserSubmission.spec.js
│ │ │ └── infolinks
│ │ │ │ ├── GeneralLayout.spec.js
│ │ │ │ ├── ProactiveHelpDialog.spec.js
│ │ │ │ └── ProactiveHelpPreviewDialog.spec.js
│ │ │ ├── composables
│ │ │ ├── documentTemplate.spec.js
│ │ │ ├── form.spec.js
│ │ │ └── printOptions.spec.js
│ │ │ ├── filters
│ │ │ └── index.spec.js
│ │ │ ├── fixtures
│ │ │ ├── form.json
│ │ │ ├── identityProviders.json
│ │ │ ├── idir_user.json
│ │ │ ├── permissions.json
│ │ │ └── roles.json
│ │ │ ├── i18n.config.js
│ │ │ ├── router.spec.js
│ │ │ ├── services
│ │ │ ├── adminService.spec.js
│ │ │ ├── apiKeyService.spec.js
│ │ │ ├── encryptionKeyService.spec.js
│ │ │ ├── eventStreamConfigService.spec.js
│ │ │ ├── formService.spec.js
│ │ │ ├── rbacService.spec.js
│ │ │ ├── roleService.spec.js
│ │ │ └── userService.spec.js
│ │ │ ├── setup.js
│ │ │ ├── store
│ │ │ └── modules
│ │ │ │ ├── admin.actions.spec.js
│ │ │ │ ├── auth.actions.spec.js
│ │ │ │ ├── auth.getters.spec.js
│ │ │ │ ├── form.actions.spec.js
│ │ │ │ └── notifications.actions.spec.js
│ │ │ ├── stubs.js
│ │ │ ├── utils
│ │ │ ├── constants.spec.js
│ │ │ ├── permissionUtils.spec.js
│ │ │ └── transformUtils.spec.js
│ │ │ ├── views
│ │ │ ├── About.spec.js
│ │ │ ├── Admin.spec.js
│ │ │ ├── Error.spec.js
│ │ │ ├── Form.spec.js
│ │ │ ├── Login.spec.js
│ │ │ ├── NotFound.spec.js
│ │ │ ├── User.spec.js
│ │ │ ├── admin
│ │ │ │ ├── Form.spec.js
│ │ │ │ ├── Root.spec.js
│ │ │ │ └── User.spec.js
│ │ │ ├── file
│ │ │ │ └── Download.spec.js
│ │ │ ├── form
│ │ │ │ ├── Create.spec.js
│ │ │ │ ├── Design.spec.js
│ │ │ │ ├── Export.spec.js
│ │ │ │ ├── Manage.spec.js
│ │ │ │ ├── Preview.spec.js
│ │ │ │ ├── Submissions.spec.js
│ │ │ │ ├── Submit.spec.js
│ │ │ │ ├── Success.spec.js
│ │ │ │ ├── Teams.spec.js
│ │ │ │ └── View.spec.js
│ │ │ └── user
│ │ │ │ ├── Forms.spec.js
│ │ │ │ ├── History.spec.js
│ │ │ │ ├── Root.spec.js
│ │ │ │ ├── SubmissionDraftEdit.spec.js
│ │ │ │ ├── SubmissionDuplicate.spec.js
│ │ │ │ ├── SubmissionView.spec.js
│ │ │ │ └── Submissions.spec.js
│ │ │ └── vuetify.config.js
│ └── vite.config.mjs
├── jest.config.js
├── knexfile.js
├── lcov-fix.js
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│ ├── README.md
│ ├── components
│ │ ├── cdogsService.js
│ │ ├── chesService.js
│ │ ├── clamAvScanner.js
│ │ ├── clientConnection.js
│ │ ├── encryptionService.js
│ │ ├── errorToProblem.js
│ │ ├── eventStreamService.js
│ │ ├── geoAddressService.js
│ │ ├── idpService.js
│ │ ├── jwtService.js
│ │ └── log.js
│ ├── db
│ │ ├── .editorconfig
│ │ ├── dataConnection.js
│ │ ├── migrations
│ │ │ ├── 20200807133615_000-init.js
│ │ │ ├── 20200825155537_001-views.js
│ │ │ ├── 20200825155537_002-idp_role_permission_data.js
│ │ │ ├── 20200925103025_003-submission-users.js
│ │ │ ├── 20201007112921_005-submissions-data-vw.js
│ │ │ ├── 20201007113516_004-alter-form-view.js
│ │ │ ├── 20201008142046_006-version-drafts.js
│ │ │ ├── 20201019100738_007-public-submission-data-vw.js
│ │ │ ├── 20201029141347_008-form-settings-notifications.js
│ │ │ ├── 20201105120909_009-file-upload.js
│ │ │ ├── 20210100113516_010-alter-form-view.js
│ │ │ ├── 20210129120337_012-submission-status.js
│ │ │ ├── 20210408120337_013-role-permission-for-owner.js
│ │ │ ├── 20210426141115_014-form-submission-audit.js
│ │ │ ├── 20210519170000_015-alter-submission-data-vw.js
│ │ │ ├── 20210528134214_016-submission-submitters-vw copy.js
│ │ │ ├── 20210614134214_017-alter-submission-submitters-add-form.js
│ │ │ ├── 20210716000000_018-alter-submission-submitters-add-updatedAt.js
│ │ │ ├── 20210721210234_019-api-key-models.js
│ │ │ ├── 20210816000000_020-user-form-preferences.js
│ │ │ ├── 20210830170000_021-alter-submissions-vw.js
│ │ │ ├── 20210928000000_022-add-bceid-idps.js
│ │ │ ├── 20211006000000_023-add-user-idps.js
│ │ │ ├── 20211027000000_024-add-revising.js
│ │ │ ├── 20221205215308_025-add-idp-guids.js
│ │ │ ├── 20221208001614_026-remove-keycloak-id.js
│ │ │ ├── 20230110063945_027-form_components_proactive_help.js
│ │ │ ├── 20230110063945_028-alter-form-table-to-add-reminder-schedule-copy-col.js
│ │ │ ├── 20230412141347_029-form-settings-uploadfile.js
│ │ │ ├── 20230412181347_030-form-settings-uploadfile-form-view.js
│ │ │ ├── 20230517012741_alter-user-form-access-view.js
│ │ │ ├── 20230517012755_32-add-update-col-alter-submissions-vw.js
│ │ │ ├── 20230618063952_033-form-subscribe.js
│ │ │ ├── 20230705190020_change_file_storage_constrains.js
│ │ │ ├── 20230818010845_add_modify_submissions_vw.js
│ │ │ ├── 20230830164525_036-form-email-template.js
│ │ │ ├── 20231017192656_037-user-form-permissions.js
│ │ │ ├── 20231019153505_038-view-simplification.js
│ │ │ ├── 20231121220415_039-form-profiling-data.js
│ │ │ ├── 20231123172822_send-team-notification-email.js
│ │ │ ├── 20240115201832_files-api-access.js
│ │ │ ├── 20240312164557_remove-confirmationid-constraint.js
│ │ │ ├── 20240321170550_wide-form-layout.js
│ │ │ ├── 20240403192833_044-document-templates.js
│ │ │ ├── 20240421000000_identity_provider_permissions.js
│ │ │ ├── 20240423183912_045-add-approver-role.js
│ │ │ ├── 20240521210143_046_external_api.js
│ │ │ ├── 20240806171846_update_identity_provider_extra.js
│ │ │ ├── 20240904140843_047-extend-submitter-role.js
│ │ │ ├── 20240916104713_048-email-recipients.js
│ │ │ ├── 20241010164117_049-update-idp-extra-length.js
│ │ │ ├── 20241016164117__050-form-metadata.js
│ │ │ ├── 20241016164117__051_modify_submissions_data_vw.js
│ │ │ ├── 20241031164117_060_event_stream_service.js
│ │ │ ├── 20241031164117_061_event_flags.js
│ │ │ ├── 20241218233455_062_update_external_api_vw.js
│ │ │ ├── 20241227201927_fix_identity_provider_extra.js
│ │ │ ├── 20250213174458_idp_bcservicescard.js
│ │ │ ├── 20250219000331_ess_allowlist.js
│ │ │ ├── 20250319062555_alter-form-table-to-enable_team_member_draft_share.js
│ │ │ ├── 20250407174410_idp_sort_order.js
│ │ │ ├── 20250502163949_enable-bcsc-idp.js
│ │ │ ├── 20250513152242_assigned_user_to_submissions_vw.js
│ │ │ ├── 20250527190932_fix-username-idp-assignment-views.js
│ │ │ ├── 20250528160202_assignee_to_submissions_data_vw.js
│ │ │ └── 20250529210801_add-assignee-column-display-setting.js
│ │ ├── seeds
│ │ │ └── 999-dev-seed-data.js
│ │ └── stamps.js
│ ├── docs
│ │ ├── .editorconfig
│ │ ├── CHEFS_API_Documentation.postman_collection.json
│ │ ├── docs.js
│ │ └── v1.api-spec.yaml
│ ├── forms
│ │ ├── admin
│ │ │ ├── controller.js
│ │ │ ├── fileService.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── auth
│ │ │ ├── middleware
│ │ │ │ ├── apiAccess.js
│ │ │ │ └── userAccess.js
│ │ │ └── service.js
│ │ ├── bcgeoaddress
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── common
│ │ │ ├── constants.js
│ │ │ ├── middleware
│ │ │ │ ├── errorHandler.js
│ │ │ │ ├── index.js
│ │ │ │ ├── rateLimiter.js
│ │ │ │ └── validateParameter.js
│ │ │ ├── models
│ │ │ │ ├── index.js
│ │ │ │ ├── jsonSchema.js
│ │ │ │ ├── mixins.js
│ │ │ │ ├── tables
│ │ │ │ │ ├── documentTemplate.js
│ │ │ │ │ ├── essAllowlist.js
│ │ │ │ │ ├── externalAPI.js
│ │ │ │ │ ├── externalAPIStatusCode.js
│ │ │ │ │ ├── fileStorage.js
│ │ │ │ │ ├── form.js
│ │ │ │ │ ├── formApiKey.js
│ │ │ │ │ ├── formComponentsProactiveHelp.js
│ │ │ │ │ ├── formEmailTemplate.js
│ │ │ │ │ ├── formEncryptionKey.js
│ │ │ │ │ ├── formEventStreamConfig.js
│ │ │ │ │ ├── formIdentityProvider.js
│ │ │ │ │ ├── formMetadata.js
│ │ │ │ │ ├── formRoleUser.js
│ │ │ │ │ ├── formStatusCode.js
│ │ │ │ │ ├── formSubmission.js
│ │ │ │ │ ├── formSubmissionStatus.js
│ │ │ │ │ ├── formSubmissionUser.js
│ │ │ │ │ ├── formSubscription.js
│ │ │ │ │ ├── formVersion.js
│ │ │ │ │ ├── formVersionDraft.js
│ │ │ │ │ ├── identityProvider.js
│ │ │ │ │ ├── label.js
│ │ │ │ │ ├── note.js
│ │ │ │ │ ├── permission.js
│ │ │ │ │ ├── role.js
│ │ │ │ │ ├── statusCode.js
│ │ │ │ │ ├── submissionAudit.js
│ │ │ │ │ ├── user.js
│ │ │ │ │ └── userFormPreferences.js
│ │ │ │ ├── utils.js
│ │ │ │ └── views
│ │ │ │ │ ├── adminExternalAPI.js
│ │ │ │ │ ├── formSubmissionUserPermissions.js
│ │ │ │ │ ├── publicFormAccess.js
│ │ │ │ │ ├── submissionData.js
│ │ │ │ │ ├── submissionMetadata.js
│ │ │ │ │ ├── userFormAccess.js
│ │ │ │ │ └── userSubmissions.js
│ │ │ ├── scheduleService.js
│ │ │ └── utils.js
│ │ ├── email
│ │ │ ├── assets
│ │ │ │ ├── bodies
│ │ │ │ │ ├── file-download-ready.html
│ │ │ │ │ ├── reminder-form-not-fill.html
│ │ │ │ │ ├── reminder-form-open.html
│ │ │ │ │ ├── reminder-form-will-close.html
│ │ │ │ │ ├── send-status-assigned-email-body.html
│ │ │ │ │ ├── send-status-revising-email-body.html
│ │ │ │ │ ├── submission-assigned.html
│ │ │ │ │ ├── submission-completed.html
│ │ │ │ │ ├── submission-confirmation.html
│ │ │ │ │ ├── submission-received-confirmation-login.html
│ │ │ │ │ ├── submission-received-confirmation-public.html
│ │ │ │ │ └── submission-unassigned.html
│ │ │ │ └── triggered-notification-email-template.html
│ │ │ ├── emailService.js
│ │ │ └── reminderService.js
│ │ ├── event
│ │ │ └── eventService.js
│ │ ├── file
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── middleware
│ │ │ │ ├── filePermissions.js
│ │ │ │ ├── upload.js
│ │ │ │ └── virusScan.js
│ │ │ ├── routes.js
│ │ │ ├── service.js
│ │ │ └── storage
│ │ │ │ ├── localStorageService.js
│ │ │ │ ├── objectStorageService.js
│ │ │ │ └── storageService.js
│ │ ├── form
│ │ │ ├── controller.js
│ │ │ ├── encryptionKey
│ │ │ │ ├── controller.js
│ │ │ │ ├── routes.js
│ │ │ │ └── service.js
│ │ │ ├── eventStreamConfig
│ │ │ │ ├── controller.js
│ │ │ │ ├── routes.js
│ │ │ │ └── service.js
│ │ │ ├── exportService.js
│ │ │ ├── externalApi
│ │ │ │ ├── controller.js
│ │ │ │ ├── index.js
│ │ │ │ ├── routes.js
│ │ │ │ └── service.js
│ │ │ ├── formMetadata
│ │ │ │ └── service.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── permission
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── proxy
│ │ │ ├── controller.js
│ │ │ ├── error.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── public
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── middleware
│ │ │ │ └── apiAccess.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── rbac
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── role
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── submission
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ ├── user
│ │ │ ├── controller.js
│ │ │ ├── index.js
│ │ │ ├── routes.js
│ │ │ └── service.js
│ │ └── utils
│ │ │ ├── index.js
│ │ │ └── routes.js
│ └── routes
│ │ └── v1.js
└── tests
│ ├── common
│ ├── dbHelper.js
│ └── helper.js
│ ├── fixtures
│ ├── form
│ │ ├── Kitchen_sink_form_schema_datagrid.json
│ │ ├── advanced_schema.json
│ │ ├── fields
│ │ │ └── extractedFields.json
│ │ ├── identity_providers.json
│ │ ├── kitchen_sink_form_schema_multiple_component_test.json
│ │ └── kitchen_sink_schema.json
│ └── submission
│ │ ├── advanced_submission.json
│ │ ├── advanced_submissions_export.json
│ │ ├── kitchen_sink_submission.json
│ │ ├── kitchen_sink_submission_data_export_datagrid.json
│ │ ├── kitchen_sink_submission_data_export_datagrid_fields_selection.json
│ │ ├── kitchen_sink_submission_data_multiple_component_test.json
│ │ ├── kitchen_sink_submission_extract_field_csv_export.json
│ │ ├── kitchen_sink_submission_pagination.json
│ │ └── kitchen_sink_submissions_export.json
│ └── unit
│ ├── README.md
│ ├── components
│ ├── cdogsService.spec.js
│ ├── clamAvScanner.spec.js
│ ├── encryptionService.spec.js
│ ├── errorToProblem.spec.js
│ ├── eventStreamService.spec.js
│ ├── idpService.spec.js
│ ├── jwtService.spec.js
│ └── log.spec.js
│ ├── forms
│ ├── admin
│ │ ├── controller.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── auth
│ │ ├── authService.spec.js
│ │ └── middleware
│ │ │ ├── apiAccess.spec.js
│ │ │ └── userAccess.spec.js
│ ├── bcgeoaddress
│ │ ├── controller.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── common
│ │ ├── middleware
│ │ │ ├── errorHandler.spec.js
│ │ │ ├── rateLimiter.spec.js
│ │ │ └── validateParameter.spec.js
│ │ ├── models
│ │ │ └── utils.spec.js
│ │ ├── scheduleService.spec.js
│ │ └── utils.spec.js
│ ├── email
│ │ ├── emailService.spec.js
│ │ └── reminderService.spec.js
│ ├── file
│ │ ├── controller.spec.js
│ │ ├── middleware
│ │ │ ├── filePermissions.spec.js
│ │ │ ├── upload.spec.js
│ │ │ └── virusScan.spec.js
│ │ └── routes.spec.js
│ ├── form
│ │ ├── controller.spec.js
│ │ ├── encryptionKey
│ │ │ ├── controller.spec.js
│ │ │ ├── routes.spec.js
│ │ │ └── service.spec.js
│ │ ├── eventStreamConfig
│ │ │ ├── controller.spec.js
│ │ │ ├── routes.spec.js
│ │ │ └── service.spec.js
│ │ ├── exportService.spec.js
│ │ ├── externalApi
│ │ │ ├── controller.spec.js
│ │ │ ├── routes.spec.js
│ │ │ └── service.spec.js
│ │ ├── formMetadata
│ │ │ └── service.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── permission
│ │ └── routes.spec.js
│ ├── proxy
│ │ ├── controller.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── public
│ │ ├── middleware
│ │ │ └── apiAccess.spec.js
│ │ └── routes.spec.js
│ ├── rbac
│ │ ├── controller.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── role
│ │ └── routes.spec.js
│ ├── submission
│ │ ├── controller.spec.js
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ ├── user
│ │ ├── routes.spec.js
│ │ └── service.spec.js
│ └── utils
│ │ └── routes.spec.js
│ └── routes
│ ├── v1.spec.js
│ └── v1
│ ├── admin.spec.js
│ ├── form.spec.js
│ ├── permission.spec.js
│ ├── rbac.spec.js
│ ├── role.spec.js
│ ├── submission.spec.js
│ └── user.spec.js
├── clamav
├── .dockerignore
├── Dockerfile
├── README.md
├── charts
│ └── clamav
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── README.md
│ │ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── configmap.yaml
│ │ ├── deployment.yaml
│ │ ├── nsp.yaml
│ │ ├── pdb.yaml
│ │ └── service.yaml
│ │ ├── values-dev.yaml
│ │ ├── values-test.yaml
│ │ └── values.yaml
├── clamdcheck.sh
└── config
│ ├── clamd.conf
│ └── freshclam.conf
├── components
├── .codeclimate.yml
├── .gitignore
├── .prettierrc
├── README.md
├── gulpfile.js
├── package-lock.json
├── package.json
├── src
│ ├── components
│ │ ├── BCAddress
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Address.edit.provider.ts
│ │ ├── Common
│ │ │ ├── Advanced.edit.api.ts
│ │ │ ├── Advanced.edit.conditional.ts
│ │ │ ├── Advanced.edit.data.ts
│ │ │ ├── Advanced.edit.display.ts
│ │ │ ├── Advanced.edit.layout.ts
│ │ │ ├── Advanced.edit.logic.ts
│ │ │ ├── Advanced.edit.validation.ts
│ │ │ ├── Constants.ts
│ │ │ ├── Evaluator.ts
│ │ │ ├── Simple.edit.api.ts
│ │ │ ├── Simple.edit.conditional.ts
│ │ │ ├── Simple.edit.data.ts
│ │ │ ├── Simple.edit.display.ts
│ │ │ ├── Simple.edit.validation.ts
│ │ │ ├── UseForCopy.ts
│ │ │ ├── function.ts
│ │ │ └── utils.ts
│ │ ├── Map
│ │ │ ├── Common
│ │ │ │ ├── Constants.d.ts
│ │ │ │ ├── Constants.js
│ │ │ │ ├── MapConstants.ts
│ │ │ │ └── marker-icon.png
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ ├── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ │ └── services
│ │ │ │ ├── BCGeocoderProvider.ts
│ │ │ │ └── MapService.ts
│ │ ├── OrgBook
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Orgbook.edit.data.ts
│ │ │ │ ├── Orgbook.edit.display.ts
│ │ │ │ └── Orgbook.edit.validation.ts
│ │ ├── SimpleAddressAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleBCAddress
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Address.edit.provider.ts
│ │ ├── SimpleButtonAdvanced
│ │ │ ├── Component.form.ts
│ │ │ └── Component.ts
│ │ ├── SimpleButtonReset
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleButtonSubmit
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleCheckbox
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleCheckboxAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleCheckboxes
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleColumns2
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleColumns3
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleColumns4
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleContent
│ │ │ ├── Component.form.ts
│ │ │ └── Component.ts
│ │ ├── SimpleCurrencyAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleDateTime
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.date.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.time.ts
│ │ ├── SimpleDateTimeAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleDay
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.day.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ ├── Component.edit.month.ts
│ │ │ │ ├── Component.edit.validation.ts
│ │ │ │ └── Component.edit.year.ts
│ │ ├── SimpleDayAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleEmail
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleEmailAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleFieldSet
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleFile
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.file.ts
│ │ ├── SimpleHeading
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleNumber
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleNumberAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimplePanel
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleParagraph
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimplePasswordAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimplePhoneNumber
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimplePhoneNumberAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleRadioAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleRadios
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleSelect
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleSelectAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleSelectBoxesAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleSignatureAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleSurveyAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTabs
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleTagsAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTextArea
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTextAreaAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTextField
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTextFieldAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.display.ts
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleTime
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ ├── Component.edit.data.ts
│ │ │ │ └── Component.edit.display.ts
│ │ ├── SimpleTimeAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ ├── SimpleUrlAdvanced
│ │ │ ├── Component.form.ts
│ │ │ ├── Component.ts
│ │ │ └── editForm
│ │ │ │ └── Component.edit.validation.ts
│ │ └── index.ts
│ ├── ejs.d.ts
│ ├── index.ts
│ ├── overrides
│ │ └── editform
│ │ │ └── utils.ts
│ ├── sass
│ │ └── contrib.scss
│ └── use.ts
├── tsconfig.json
├── tslint.json
├── webpack.config.js
├── webpack.prod.js
└── webpack.use.js
├── openshift
├── README.md
├── allow-from-openshift-ingress.np.yaml
├── app.cm.yaml
├── app.cronjob.yaml
├── app.deployment.yaml
├── app.dev.param
├── app.prod.param
├── app.secret.yaml
├── app.test.param
├── clamav.cm.yaml
├── clamav.dev.param
├── clamav.prod.param
├── clamav.test.param
├── crunchydb
│ ├── README.md
│ └── charts
│ │ ├── crunchy-postgres
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── README.md
│ │ ├── templates
│ │ │ ├── PostgresCluster.yaml
│ │ │ ├── _helpers.tpl
│ │ │ ├── _s3.tpl
│ │ │ └── s3Secret.yaml
│ │ └── values.yaml
│ │ └── tools
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── README.md
│ │ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployer
│ │ │ ├── deployerRole.yaml
│ │ │ ├── deployerRoleBinding.yaml
│ │ │ └── deployerServiceAccount.yaml
│ │ ├── linter
│ │ │ ├── linterRole.yaml
│ │ │ ├── linterRoleBinding.yaml
│ │ │ └── linterServiceAccount.yaml
│ │ ├── networking
│ │ │ ├── networkPolicy.yaml
│ │ │ ├── podNetworkPolicy.yaml
│ │ │ └── route.yaml
│ │ └── provisioner
│ │ │ ├── provisionerRole.yaml
│ │ │ ├── provisionerRoleBinding.yaml
│ │ │ └── provisionerServiceAccount.yaml
│ │ └── values.yaml
├── ess.cm.yaml
├── ess.dev.param
├── ess.prod.param
├── ess.test.param
├── patroni-ephemeral.dc.yaml
├── patroni.dc.yaml
├── patroni.dev.param
├── patroni.prod.param
├── patroni.secret.yaml
├── patroni.test.param
└── redash
│ ├── README.md
│ ├── backup-cronjob-verify.yaml
│ ├── crunchydb-postgres-values-no-limits.yaml
│ ├── crunchydb-postgres-values.yaml
│ ├── crunchydb-tools-values.yaml
│ ├── patroni.networkpolicy.yaml
│ ├── postgresql.deploy.yaml
│ ├── redash.route.yaml
│ ├── redis.deploy.yaml
│ └── secrets.yaml
└── tests
├── functional
└── cypress
│ ├── .eslintrc.js
│ ├── README.md
│ ├── cypress.config.js
│ ├── e2e
│ ├── about.cy.js
│ ├── form-apikey-cdogs.cy.js
│ ├── form-design-advanceddata.cy.js
│ ├── form-design-advancedfield.cy.js
│ ├── form-design-basicfields.cy.js
│ ├── form-design-basiclayout-advanced-layout.cy.js
│ ├── form-design-export-import-design.cy.js
│ ├── form-design-map-point-circle-markers.cy.js
│ ├── form-design-map-polygon-marker.cy.js
│ ├── form-draft-submission-management.cy.js
│ ├── form-edit-submission-data.cy.js
│ ├── form-manage-form.cy.js
│ ├── form-simple-form-publish.cy.js
│ ├── form-submission-assign-revise-status.cy.js
│ ├── form-submission-assign-status.cy.js
│ ├── form-submission-export.cy.js
│ ├── form-submission-public-no-status-assign.cy.js
│ ├── form-submission-public-status-assign.cy.js
│ ├── form-team-email-management.cy.js
│ └── kitchen-sink.cy.js
│ ├── fixtures
│ ├── SamplePPTx.pptx
│ ├── Testing_files.txt
│ ├── add1.png
│ ├── file_example_XLSX_50.xlsx
│ ├── formInitialBuilder
│ │ ├── add1.png
│ │ ├── ccHelpLinkInfoList.json
│ │ └── formBuilderOptions.json
│ ├── formModules
│ │ ├── activeFormModules.json
│ │ └── formModuleVersion.json
│ ├── forms
│ │ ├── current-forms.json
│ │ ├── empty-array.json
│ │ ├── form-field.json
│ │ ├── form-submission-deleted.json
│ │ ├── form-submission.json
│ │ ├── form.json
│ │ ├── griddata.json
│ │ └── submission-restore.json
│ ├── kitchensink
│ │ ├── formModuleVersions.json
│ │ ├── formOptions.json
│ │ ├── formVersion.json
│ │ ├── submission.json
│ │ └── submissionOptions.json
│ ├── test.docx
│ ├── test_schema.json
│ └── users
│ │ └── user.json
│ ├── package-lock.json
│ ├── package.json
│ ├── plugins
│ └── index.js
│ └── support
│ ├── commands.js
│ ├── component.js
│ ├── e2e.js
│ ├── index.js
│ └── login.js
└── performance
├── .sample-env
├── README.md
├── backend.js
├── common
├── auth.js
└── params.js
├── fixtures
├── forms
│ ├── 01_kitchen_sink_advanced.json
│ └── 02_kitchen_sink_no_sig.json
├── schemas
│ ├── 01_kitchen_sink_advanced.json
│ └── 02_kitchen_sink_no_sig.json
└── submissions
│ ├── 01_kitchen_sink_advanced.json
│ └── 02_kitchen_sink_no_sig.json
└── tests
└── backend
└── forms.js
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG VARIANT="20.18.3-bookworm"
2 | FROM node:${VARIANT}
3 |
4 | # Install some extras such as vim for interactive rebases. Also some
5 | # Cypress prerequisites for running in Debian containers:
6 | # https://docs.cypress.io/app/get-started/install-cypress#UbuntuDebian
7 | # and we set up k6 for performance testing
8 | RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 && \
9 | echo "deb https://dl.k6.io/deb stable main" | tee /etc/apt/sources.list.d/k6.list && \
10 | apt-get update && \
11 | DEBIAN_FRONTEND=noninteractive apt-get install -y \
12 | k6 \
13 | libasound2 \
14 | libgbm-dev \
15 | libgtk-3-0 \
16 | libgtk2.0-0 \
17 | libnotify-dev \
18 | libnss3 \
19 | libxss1 \
20 | libxtst6 \
21 | vim \
22 | xauth \
23 | xvfb \
24 | && apt-get clean
25 |
--------------------------------------------------------------------------------
/.devcontainer/README.md:
--------------------------------------------------------------------------------
1 | # CHEFS Development with Dev Container
2 |
3 | Please refer to the online [CHEFS Techdocs](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/):
4 |
5 | - [CHEFS Development with Dev Container](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/Developer/Contributors/CHEFS-Development-with-Dev-Container/)
6 | - [Local Setup](https://developer.gov.bc.ca/docs/default/component/chefs-techdocs/Developer/Contributors/Local-Setup/)
7 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Editor directories and files
2 | .DS_Store
3 | .gradle
4 | .nyc_output
5 | .scannerwork
6 | build
7 | coverage
8 | dist
9 | files
10 | **/e2e/videos
11 | node_modules
12 | # Ignore only top-level package-lock.json
13 | /package-lock.json
14 |
15 | # Ignore Helm subcharts
16 | charts/**/charts
17 | Chart.lock
18 |
19 | # local env files
20 | local.*
21 | local-*.*
22 | .env.local
23 | .env.*.local
24 |
25 | # Log files
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 | # Editor directories and files
31 | .idea
32 | .vscode
33 | *.iml
34 | *.suo
35 | *.ntvs*
36 | *.njsproj
37 | *.sln
38 | *.sw?
39 | *.mp4
40 |
41 | # temp office files
42 | ~$*
43 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 |
9 | [*.html]
10 | indent_style = space
11 | indent_size = 2
12 |
13 | [*.{css,js,json,jsx,scss,ts,tsx,vue}]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [.{babelrc,eslintrc}]
18 | indent_style = space
19 | indent_size = 2
20 |
21 | # ignore patterns
22 | [*.{gif,ico}]
23 | end_of_line = unset
24 | insert_final_newline = unset
25 | trim_trailing_whitespace = unset
26 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Autodetect text files and forces unix eols, so Windows does not break them
2 | * text=auto eol=lf
3 |
4 | # Force images/fonts to be handled as binaries
5 | *.jpg binary
6 | *.jpeg binary
7 | *.gif binary
8 | *.png binary
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | #### Is your feature request related to a problem? Please describe
11 |
12 |
13 |
14 | #### Describe the solution you'd like
15 |
16 |
17 |
18 | #### Describe alternatives you've considered
19 |
20 |
21 |
22 | #### Additional context
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.github/workflows/reusable-owasp-zap.yaml:
--------------------------------------------------------------------------------
1 | #
2 | # Reusable workflow to run the OWASP ZAP (Open Worldwide Application Security
3 | # Project - Zed Attack Proxy) Scan against a deployed application.
4 | #
5 | name: OWASP ZAP Scan
6 | on:
7 | workflow_call:
8 | inputs:
9 | url:
10 | required: true
11 | type: string
12 |
13 | jobs:
14 | owasp-zap:
15 | name: OWASP ZAP Scan
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - name: Run Scan
20 | uses: zaproxy/action-full-scan@v0.12.0
21 | with:
22 | # Do not create GitHub Issues
23 | allow_issue_writing: false
24 |
25 | artifact_name: OWASP ZAP Scan
26 |
27 | # -a: include the alpha passive scan rules as well
28 | # -d: show debug messages
29 | cmd_options: "-a -d"
30 |
31 | target: ${{ inputs.url }}
32 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | bcgov-citz-ccft.github.ca
--------------------------------------------------------------------------------
/COMPLIANCE.yaml:
--------------------------------------------------------------------------------
1 | name: compliance
2 | description: |
3 | This document is used to track a projects PIA and STRA
4 | compliance.
5 | spec:
6 | - name: PIA
7 | status: COMPLETED
8 | last-updated: "2023-03-17T00:00:00.000Z"
9 | - name: STRA
10 | status: COMPLETED
11 | last-updated: "2023-08-04T00:00:00.000Z"
12 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM docker.io/node:20.18.3-alpine3.21
2 | ENV NO_UPDATE_NOTIFIER=true
3 | WORKDIR /opt/app-root/src/app
4 | COPY . /opt/app-root/src
5 |
6 | # Run the npm tasks to set up the various parts of the application. Then create
7 | # the /.npm directory and grant access to group 0 to allow npm v9 to work
8 | # See: https://docs.openshift.com/container-platform/4.11/openshift_images/create-images.html#use-uid_create-images
9 |
10 | RUN npm run all:ci \
11 | && npm run all:build \
12 | && npm run frontend:purge \
13 | && npm run components:clean \
14 | && npm run components:purge \
15 | && mkdir /.npm \
16 | && chgrp -R 0 /.npm \
17 | && chmod -R g=u /.npm
18 |
19 | EXPOSE 8000
20 |
21 | CMD ["npm", "run", "start"]
22 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
2 |
--------------------------------------------------------------------------------
/app/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 |
9 | [*.html]
10 | indent_style = space
11 | indent_size = 2
12 |
13 | [*.{css,js,json,jsx,scss,ts,tsx,vue}]
14 | indent_style = space
15 | indent_size = 2
16 |
17 | [.{babelrc,eslintrc}]
18 | indent_style = space
19 | indent_size = 2
20 |
--------------------------------------------------------------------------------
/app/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | frontend
3 | node_modules
4 | public/js
5 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | myfiles
2 | myfiles/*
3 |
--------------------------------------------------------------------------------
/app/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | frontend
3 | node_modules
4 | public/js
5 | src/db/*
--------------------------------------------------------------------------------
/app/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "printWidth": 180,
5 | "tabWidth": 2
6 | }
7 |
--------------------------------------------------------------------------------
/app/config/production.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/app/frontend/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/app/frontend/.eslintignore:
--------------------------------------------------------------------------------
1 | coverage
2 | dist
3 | node_modules
4 | public/js
5 | src/formio
6 | tests
--------------------------------------------------------------------------------
/app/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
25 | .env
26 | .env.development
27 | .env.production
28 | .env*
29 | .vscode
--------------------------------------------------------------------------------
/app/frontend/.prettierignore:
--------------------------------------------------------------------------------
1 | tests
--------------------------------------------------------------------------------
/app/frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true,
4 | "printWidth": 80
5 | }
6 |
--------------------------------------------------------------------------------
/app/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Common Hosted Forms Service
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/frontend/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "allowJs": true
3 | }
4 |
--------------------------------------------------------------------------------
/app/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/app/frontend/public/images/drag_drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/public/images/drag_drop.png
--------------------------------------------------------------------------------
/app/frontend/public/images/quickstart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/public/images/quickstart.png
--------------------------------------------------------------------------------
/app/frontend/public/images/team-management.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/public/images/team-management.png
--------------------------------------------------------------------------------
/app/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | <%= process.env.VUE_APP_TITLE %>
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/frontend/src/assets/images/drag-drop-demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/src/assets/images/drag-drop-demo.gif
--------------------------------------------------------------------------------
/app/frontend/src/components/admin/AdministerUser.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
27 |
28 |
{{ user.fullName }}
29 |
{{ $t('trans.administerUser.userDetails') }}
30 |
{{ user }}
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/frontend/src/components/admin/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/frontend/src/components/base/BaseInfoCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
33 |
--------------------------------------------------------------------------------
/app/frontend/src/components/base/BaseNotificationContainer.vue:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/app/frontend/src/components/base/BasePanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
30 |
--------------------------------------------------------------------------------
/app/frontend/src/components/base/BasePrintButton.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/frontend/src/composables/printOptions.js:
--------------------------------------------------------------------------------
1 | export function createDownload(blob, filename = undefined) {
2 | const url = window.URL.createObjectURL(blob);
3 | const a = document.createElement('a');
4 | a.style.display = 'none';
5 | a.href = url;
6 | a.download = filename;
7 | a.click();
8 | window.URL.revokeObjectURL(url);
9 | a.remove();
10 | }
11 |
--------------------------------------------------------------------------------
/app/frontend/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/frontend/src/favicon.ico
--------------------------------------------------------------------------------
/app/frontend/src/filters/index.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment';
2 |
3 | //
4 | // Date format Filters {{ expression | filter }}
5 | //
6 |
7 | /**
8 | * @function formatDate
9 | * Converts a date to an 'MMMM D YYYY' formatted string
10 | * @param {Date} value A date object
11 | * @returns {String} A string representation of `value`
12 | */
13 | export function formatDate(value) {
14 | if (value) {
15 | return moment(String(value)).format('MMMM D YYYY');
16 | }
17 | }
18 |
19 | /**
20 | * @function formatDateLong
21 | * Converts a date to a 'YYYY-MM-DD hh:mm:ss a' formatted string
22 | * @param {Date} value A date object
23 | * @returns {String} A string representation of `value`
24 | */
25 | export function formatDateLong(value) {
26 | if (value) {
27 | return moment(String(value)).format('YYYY-MM-DD hh:mm:ss a');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/ar/index.js:
--------------------------------------------------------------------------------
1 | import ar from '~/internationalization/trans/chefs/ar/ar.json';
2 | export default {
3 | trans: ar,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/de/index.js:
--------------------------------------------------------------------------------
1 | import de from '~/internationalization/trans/chefs/de/de.json';
2 | export default {
3 | trans: de,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/en/index.js:
--------------------------------------------------------------------------------
1 | import en from '~/internationalization/trans/chefs/en/en.json';
2 | export default {
3 | trans: en,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/es/index.js:
--------------------------------------------------------------------------------
1 | import es from '~/internationalization/trans/chefs/es/es.json';
2 | export default {
3 | trans: es,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/fa/index.js:
--------------------------------------------------------------------------------
1 | import fa from '~/internationalization/trans/chefs/fa/fa.json';
2 | export default {
3 | trans: fa,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/fr/index.js:
--------------------------------------------------------------------------------
1 | import fr from '~/internationalization/trans/chefs/fr/fr.json';
2 | export default {
3 | trans: fr,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/hi/index.js:
--------------------------------------------------------------------------------
1 | import hi from '~/internationalization/trans/chefs/hi/hi.json';
2 | export default {
3 | trans: hi,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/it/index.js:
--------------------------------------------------------------------------------
1 | import it from '~/internationalization/trans/chefs/it/it.json';
2 | export default {
3 | trans: it,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/ja/index.js:
--------------------------------------------------------------------------------
1 | import ja from '~/internationalization/trans/chefs/ja/ja.json';
2 | export default {
3 | trans: ja,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/ko/index.js:
--------------------------------------------------------------------------------
1 | import ko from '~/internationalization/trans/chefs/ko/ko.json';
2 | export default {
3 | trans: ko,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/pa/index.js:
--------------------------------------------------------------------------------
1 | import pa from '~/internationalization/trans/chefs/pa/pa.json';
2 | export default {
3 | trans: pa,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/pt/index.js:
--------------------------------------------------------------------------------
1 | import pt from '~/internationalization/trans/chefs/pt/pt.json';
2 | export default {
3 | trans: pt,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/ru/index.js:
--------------------------------------------------------------------------------
1 | import ru from '~/internationalization/trans/chefs/ru/ru.json';
2 | export default {
3 | trans: ru,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/tl/index.js:
--------------------------------------------------------------------------------
1 | import tl from '~/internationalization/trans/chefs/tl/tl.json';
2 | export default {
3 | trans: tl,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/uk/index.js:
--------------------------------------------------------------------------------
1 | import uk from '~/internationalization/trans/chefs/uk/uk.json';
2 | export default {
3 | trans: uk,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/vi/index.js:
--------------------------------------------------------------------------------
1 | import vi from '~/internationalization/trans/chefs/vi/vi.json';
2 | export default {
3 | trans: vi,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/zh/index.js:
--------------------------------------------------------------------------------
1 | import zh from '~/internationalization/trans/chefs/zh/zh.json';
2 | export default {
3 | trans: zh,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/chefs/zhTW/index.js:
--------------------------------------------------------------------------------
1 | import zhTW from '~/internationalization/trans/chefs/zhTW/zh-TW.json';
2 | export default {
3 | trans: zhTW,
4 | };
5 |
--------------------------------------------------------------------------------
/app/frontend/src/internationalization/trans/vuetify/locale/README.md:
--------------------------------------------------------------------------------
1 | This directory contains the translation files for languages that are supported
2 | by CHEFS, but not supported by Vuetify.
3 |
--------------------------------------------------------------------------------
/app/frontend/src/services/eventStreamConfigService.js:
--------------------------------------------------------------------------------
1 | import { appAxios } from '~/services/interceptors';
2 | import { ApiRoutes } from '~/utils/constants';
3 |
4 | export default {
5 | /**
6 | * @function getEventStreamConfig
7 | * Get the event stream configuration
8 | * @param {string} formId The form uuid
9 | * @param {Object} [params={}] The query parameters
10 | * @returns {Promise} An axios response
11 | */
12 | getEventStreamConfig(formId, params = {}) {
13 | return appAxios().get(
14 | `${ApiRoutes.FORMS}/${formId}${ApiRoutes.EVENT_STREAM_CONFIG}`,
15 | { params }
16 | );
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/app/frontend/src/services/fileService.js:
--------------------------------------------------------------------------------
1 | import { appAxios } from '~/services/interceptors';
2 | import { ApiRoutes } from '~/utils/constants';
3 |
4 | export default {
5 | async deleteFile(fileId) {
6 | return appAxios().delete(`${ApiRoutes.FILES}/${fileId}`);
7 | },
8 | async deleteFiles(fileIds) {
9 | return appAxios().delete(`${ApiRoutes.FILES}/`, { data: { fileIds } });
10 | },
11 | async getFile(fileId, options = {}) {
12 | return appAxios().get(`${ApiRoutes.FILES}/${fileId}`, options);
13 | },
14 | async uploadFile(file, config = {}) {
15 | return appAxios().post(`${ApiRoutes.FILES}`, file, config);
16 | },
17 | async cloneFile(fileId) {
18 | return appAxios().get(`${ApiRoutes.FILES}/${fileId}/clone`);
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/app/frontend/src/services/index.js:
--------------------------------------------------------------------------------
1 | export { default as adminService } from './adminService';
2 | export { default as apiKeyService } from './apiKeyService';
3 | export { default as formService } from './formService';
4 | export { default as rbacService } from './rbacService';
5 | export { default as roleService } from './roleService';
6 | export { default as userService } from './userService';
7 | export { default as fileService } from './fileService';
8 | export { default as utilsService } from './utilsService';
9 | export { default as encryptionKeyService } from './encryptionKeyService';
10 | export { default as eventStreamConfigService } from './eventStreamConfigService';
11 |
--------------------------------------------------------------------------------
/app/frontend/src/services/roleService.js:
--------------------------------------------------------------------------------
1 | import { appAxios } from '~/services/interceptors';
2 | import { ApiRoutes } from '~/utils/constants';
3 |
4 | export default {
5 | //
6 | // Role Management calls
7 | //
8 |
9 | /**
10 | * @function list
11 | * List roles in the system
12 | * @returns {Promise} An axios response
13 | */
14 | list() {
15 | return appAxios().get(`${ApiRoutes.ROLES}`);
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/app/frontend/src/services/utilsService.js:
--------------------------------------------------------------------------------
1 | import { appAxios } from '~/services/interceptors';
2 | import { ApiRoutes } from '~/utils/constants';
3 |
4 | export default {
5 | //
6 | // Util calls
7 | //
8 |
9 | /**
10 | * @function draftDocGen
11 | * Upload a template and submission data to generate PDF from CDOGS API
12 | * @param {Object} body The request body containing the template and submission data
13 | * @returns {Promise} An axios response
14 | */
15 | draftDocGen(body) {
16 | return appAxios().post(`${ApiRoutes.UTILS}/template/render`, body, {
17 | responseType: 'arraybuffer', // Needed for binaries unless you want pain
18 | timeout: 30000, // Override default timeout as this call could take a while
19 | });
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/app/frontend/src/store/app.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia';
2 |
3 | export const useAppStore = defineStore('app', {
4 | state: () => ({
5 | config: null,
6 | }),
7 | getters: {},
8 | actions: {},
9 | });
10 |
--------------------------------------------------------------------------------
/app/frontend/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createPinia } from 'pinia';
2 |
3 | export default createPinia();
4 |
--------------------------------------------------------------------------------
/app/frontend/src/views/Admin.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/frontend/src/views/File.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/frontend/src/views/Form.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/frontend/src/views/NotFound.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 | {{ $t('trans.notFound.pageNotFound') }}
10 |
11 |
17 |
18 | {{ $t('trans.notFound.about') }}
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/frontend/src/views/User.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/frontend/src/views/admin/Form.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 | {{ $t('trans.admin.form.administerForm') }}
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/frontend/src/views/admin/Root.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 | {{ $t('trans.admin.root.admin') }}
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/app/frontend/src/views/admin/User.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 | {{ $t('trans.admin.user.administerUser') }}
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Emails.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Export.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Manage.vue:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Submissions.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Submit.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/Teams.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/src/views/form/View.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/Forms.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/History.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | {{ $t('trans.history.submissnHistory') }}
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/Root.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
16 | {{ $t('trans.user.root.myForms') }}
17 | {{ $t('trans.user.root.myForms') }}
18 |
19 |
26 | {{ $t('trans.user.root.history') }}
27 |
28 |
29 | {{ $t('trans.user.root.user') }}
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/SubmissionDraftEdit.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/SubmissionDuplicate.vue:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
26 |
27 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/SubmissionView.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/frontend/src/views/user/Submissions.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/components/admin/Dashboard.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { expect } from 'vitest';
3 |
4 | import Dashboard from '~/components/admin/Dashboard.vue';
5 |
6 | describe('Dashboard.vue', () => {
7 | const URL = 'http://somewhere.com';
8 |
9 | it('renders', async () => {
10 | const wrapper = mount(Dashboard, {
11 | props: {
12 | url: URL,
13 | },
14 | global: {
15 | plugins: [],
16 | },
17 | });
18 |
19 | expect(wrapper.html()).toContain(URL);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/components/base/BaseImagePopout.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import BaseImagePopout from '~/components/base/BaseImagePopout.vue';
5 |
6 | describe('BaseImagePopout.vue', () => {
7 | it('renders', async () => {
8 | const wrapper = mount(BaseImagePopout, {
9 | props: {
10 | src: 'test',
11 | },
12 | global: {
13 | stubs: ['v-dialog', 'v-hover'],
14 | },
15 | });
16 | expect(wrapper.html()).toMatch('v-hover');
17 | expect(wrapper.html()).toMatch('v-dialog');
18 | });
19 | });
20 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/components/base/BaseNotificationContainer.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { describe, expect, it } from 'vitest';
4 |
5 | import BaseNotificationContainer from '~/components/base/BaseNotificationContainer.vue';
6 |
7 | describe('BaseNotificationContainer.vue', () => {
8 | it('renders', async () => {
9 | const wrapper = mount(BaseNotificationContainer, {
10 | global: {
11 | stubs: ['BaseNotificationBar'],
12 | plugins: [createTestingPinia()],
13 | },
14 | });
15 |
16 | expect(wrapper.html()).toMatch('notification-container');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/components/base/BasePrintButton.spec.js:
--------------------------------------------------------------------------------
1 | // @vitest-environment happy-dom
2 | // happy-dom is required to access window.location
3 |
4 | import { mount } from '@vue/test-utils';
5 | import { beforeEach, expect, vi } from 'vitest';
6 |
7 | import BasePrintButton from '~/components/base/BasePrintButton.vue';
8 |
9 | describe('BasePrintButton.vue', () => {
10 | const printSpy = vi.spyOn(window, 'print');
11 | beforeEach(() => {
12 | printSpy.mockReset();
13 | printSpy.mockImplementation(() => {});
14 | });
15 |
16 | afterAll(() => {
17 | printSpy.mockRestore();
18 | });
19 |
20 | it('renders nothing if authenticated, user', async () => {
21 | const wrapper = mount(BasePrintButton);
22 |
23 | wrapper.vm.printSubmission();
24 |
25 | expect(wrapper.html()).toContain('print');
26 | expect(printSpy).toHaveBeenCalledTimes(1);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/composables/form.spec.js:
--------------------------------------------------------------------------------
1 | // @vitest-environment happy-dom
2 | // happy-dom is required to access window.URL
3 | import * as formComposables from '~/composables/form';
4 |
5 | describe('form.js', () => {
6 | describe('exportFormSchema', () => {
7 | it('should export some schema and return a snek', () => {
8 | const { snek } = formComposables.exportFormSchema(
9 | 'this is a form name',
10 | {
11 | id: '1',
12 | projectId: '123',
13 | },
14 | null
15 | );
16 |
17 | // it should transform the form name
18 | expect(snek).toEqual(
19 | 'this is a form name'
20 | .replace(/\s+/g, '_')
21 | .replace(/[^-_0-9a-z]/gi, '')
22 | .toLowerCase()
23 | );
24 | });
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/composables/printOptions.spec.js:
--------------------------------------------------------------------------------
1 | // @vitest-environment happy-dom
2 | // happy-dom is required to access window.URL
3 | import { vi } from 'vitest';
4 | import * as printOptionsComposables from '~/composables/printOptions';
5 |
6 | describe('printOptions.js', () => {
7 | it('createDownload should createObjectURL, click the url then revokeObjectURL', () => {
8 | let createObjectURLSpy = vi.spyOn(window.URL, 'createObjectURL');
9 | createObjectURLSpy.mockImplementation((data) => data);
10 | let revokeObjectURLSpy = vi.spyOn(window.URL, 'revokeObjectURL');
11 | revokeObjectURLSpy.mockImplementation((data) => data);
12 | printOptionsComposables.createDownload();
13 | expect(createObjectURLSpy).toHaveBeenCalledTimes(1);
14 | expect(revokeObjectURLSpy).toHaveBeenCalledTimes(1);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/fixtures/permissions.json:
--------------------------------------------------------------------------------
1 | [
2 | "design_create",
3 | "design_delete",
4 | "design_read",
5 | "design_update",
6 | "document_template_create",
7 | "document_template_delete",
8 | "document_template_read",
9 | "email_template_read",
10 | "email_template_update",
11 | "form_api_create",
12 | "form_api_delete",
13 | "form_api_read",
14 | "form_api_update",
15 | "form_delete",
16 | "form_read",
17 | "form_update",
18 | "submission_create",
19 | "submission_delete",
20 | "submission_read",
21 | "submission_review",
22 | "submission_update",
23 | "team_read",
24 | "team_update"
25 | ]
--------------------------------------------------------------------------------
/app/frontend/tests/unit/services/roleService.spec.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import MockAdapter from 'axios-mock-adapter';
3 | import { beforeEach, describe, expect, it, vi } from 'vitest';
4 |
5 | import roleService from '~/services/roleService';
6 | import { ApiRoutes } from '~/utils/constants';
7 |
8 | const mockInstance = axios.create();
9 | const mockAxios = new MockAdapter(mockInstance);
10 |
11 | vi.mock('~/services/interceptors', () => {
12 | return {
13 | appAxios: () => mockInstance,
14 | };
15 | });
16 |
17 | describe('Role Service', () => {
18 | const endpoint = `${ApiRoutes.ROLES}`;
19 |
20 | beforeEach(() => {
21 | mockAxios.reset();
22 | });
23 |
24 | it('calls get on roles/ endpoint', async () => {
25 | mockAxios.onGet(endpoint).reply(200);
26 |
27 | const result = await roleService.list();
28 | expect(result).toBeTruthy();
29 | expect(mockAxios.history.get).toHaveLength(1);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/setup.js:
--------------------------------------------------------------------------------
1 | import 'vitest-canvas-mock';
2 |
3 | class ResizeObserverStub {
4 | observe() {}
5 | unobserve() {}
6 | disconnect() {}
7 | }
8 |
9 | window.ResizeObserver = window.ResizeObserver || ResizeObserverStub;
10 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/Form.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Form from '~/views/Form.vue';
5 |
6 | describe('Form.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Form, {
9 | global: {
10 | stubs: {
11 | RouterView: true,
12 | },
13 | },
14 | });
15 |
16 | expect(wrapper.html()).toMatch('router-view');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/NotFound.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { setActivePinia } from 'pinia';
4 | import { describe, expect, it } from 'vitest';
5 |
6 | import NotFound from '~/views/NotFound.vue';
7 |
8 | describe('NotFound.vue', () => {
9 | const pinia = createTestingPinia();
10 | setActivePinia(pinia);
11 |
12 | it('renders', () => {
13 | const wrapper = mount(NotFound, {
14 | global: {
15 | stubs: {
16 | RouterLink: true,
17 | },
18 | plugins: [pinia],
19 | },
20 | });
21 |
22 | expect(wrapper.text()).toMatch('trans.notFound.pageNotFound');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/User.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import User from '~/views/User.vue';
5 |
6 | describe('User.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(User, {
9 | global: {
10 | stubs: {
11 | RouterView: true,
12 | },
13 | },
14 | });
15 |
16 | expect(wrapper.html()).toMatch('router-view');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/admin/Form.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { setActivePinia } from 'pinia';
4 | import { describe, expect, it } from 'vitest';
5 |
6 | import Form from '~/views/admin/Form.vue';
7 |
8 | describe('Form.vue', () => {
9 | const pinia = createTestingPinia();
10 | setActivePinia(pinia);
11 |
12 | it('renders', () => {
13 | const wrapper = mount(Form, {
14 | props: {
15 | f: 'f',
16 | },
17 | global: {
18 | stubs: {
19 | AdministerForm: true,
20 | },
21 | plugins: [pinia],
22 | },
23 | });
24 |
25 | expect(wrapper.text()).toMatch('trans.admin.form.administerForm');
26 | expect(wrapper.html()).toMatch('administer-form');
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/admin/Root.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { setActivePinia } from 'pinia';
4 | import { describe, expect, it } from 'vitest';
5 |
6 | import Root from '~/views/admin/Root.vue';
7 |
8 | describe('Root.vue', () => {
9 | const pinia = createTestingPinia();
10 | setActivePinia(pinia);
11 |
12 | it('renders', () => {
13 | const wrapper = mount(Root, {
14 | props: {
15 | f: 'f',
16 | },
17 | global: {
18 | stubs: {
19 | AdminPage: true,
20 | },
21 | plugins: [pinia],
22 | },
23 | });
24 |
25 | expect(wrapper.text()).toMatch('trans.admin.root.admin');
26 | expect(wrapper.html()).toMatch('admin-page');
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/admin/User.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { setActivePinia } from 'pinia';
4 | import { describe, expect, it } from 'vitest';
5 |
6 | import User from '~/views/admin/User.vue';
7 |
8 | describe('User.vue', () => {
9 | const pinia = createTestingPinia();
10 | setActivePinia(pinia);
11 |
12 | it('renders', () => {
13 | const wrapper = mount(User, {
14 | props: {
15 | u: 'u',
16 | },
17 | global: {
18 | stubs: {
19 | AdministerUser: true,
20 | },
21 | plugins: [pinia],
22 | },
23 | });
24 |
25 | expect(wrapper.text()).toMatch('trans.admin.user.administerUser');
26 | expect(wrapper.html()).toMatch('administer-user');
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Export.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Export from '~/views/form/Export.vue';
5 |
6 | describe('Export.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Export, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | ExportSubmissions: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('export-submissions');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Manage.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Manage from '~/views/form/Manage.vue';
5 |
6 | describe('Manage.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Manage, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | ManageLayout: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('manage-layout');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Submissions.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Submissions from '~/views/form/Submissions.vue';
5 |
6 | describe('Submissions.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Submissions, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | SubmissionsTable: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('submissions-table');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Submit.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Submit from '~/views/form/Submit.vue';
5 |
6 | describe('Submit.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Submit, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | FormViewer: true,
15 | },
16 | },
17 | });
18 |
19 | expect(wrapper.html()).toMatch('form-viewer');
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Success.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { setActivePinia, createPinia } from 'pinia';
3 | import { describe, expect, it } from 'vitest';
4 | import { nextTick } from 'vue';
5 |
6 | import Success from '~/views/form/Success.vue';
7 |
8 | describe('Success.vue', () => {
9 | const pinia = createPinia();
10 | setActivePinia(pinia);
11 | it('renders', async () => {
12 | const wrapper = mount(Success, {
13 | props: {
14 | s: 's',
15 | f: 'f',
16 | },
17 | global: {
18 | plugins: [pinia],
19 | stubs: {
20 | FormViewer: true,
21 | RequestReceipt: true,
22 | },
23 | },
24 | });
25 |
26 | await nextTick();
27 |
28 | expect(wrapper.html()).toMatch('form-viewer');
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/Teams.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Teams from '~/views/form/Teams.vue';
5 |
6 | describe('Teams.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Teams, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | TeamManagement: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('team-management');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/form/View.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import View from '~/views/form/View.vue';
5 |
6 | describe('View.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(View, {
9 | props: {
10 | s: 's',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | FormSubmission: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('form-submission');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/Forms.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Forms from '~/views/user/Forms.vue';
5 |
6 | describe('Forms.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Forms, {
9 | global: {
10 | stubs: {
11 | FormsTable: true,
12 | },
13 | },
14 | });
15 |
16 | expect(wrapper.html()).toMatch('forms-table');
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/History.spec.js:
--------------------------------------------------------------------------------
1 | import { createTestingPinia } from '@pinia/testing';
2 | import { mount } from '@vue/test-utils';
3 | import { setActivePinia } from 'pinia';
4 | import { describe, expect, it } from 'vitest';
5 |
6 | import History from '~/views/user/History.vue';
7 |
8 | describe('History.vue', () => {
9 | const pinia = createTestingPinia();
10 | setActivePinia(pinia);
11 |
12 | it('renders', () => {
13 | const wrapper = mount(History, {
14 | global: {
15 | stubs: {
16 | BaseSecure: {
17 | name: 'BaseSecure',
18 | template: '
',
19 | },
20 | },
21 | plugins: [pinia],
22 | },
23 | });
24 |
25 | expect(wrapper.text()).toMatch('trans.history.submissnHistory');
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/SubmissionDraftEdit.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import SubmissionDraftEdit from '~/views/user/SubmissionDraftEdit.vue';
5 |
6 | describe('SubmissionDraftEdit.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(SubmissionDraftEdit, {
9 | props: {
10 | s: 's',
11 | },
12 | global: {
13 | stubs: {
14 | UserSubmission: true,
15 | },
16 | },
17 | });
18 |
19 | expect(wrapper.html()).toMatch('user-submission');
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/SubmissionDuplicate.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import SubmissionDuplicate from '~/views/user/SubmissionDuplicate.vue';
5 |
6 | describe('SubmissionDuplicate.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(SubmissionDuplicate, {
9 | props: {
10 | s: 's',
11 | f: 'f',
12 | },
13 | global: {
14 | stubs: {
15 | UserDuplicateSubmission: true,
16 | },
17 | },
18 | });
19 |
20 | expect(wrapper.html()).toMatch('user-duplicate-submission');
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/SubmissionView.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import SubmissionView from '~/views/user/SubmissionView.vue';
5 |
6 | describe('SubmissionView.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(SubmissionView, {
9 | props: {
10 | s: 's',
11 | },
12 | global: {
13 | stubs: {
14 | FormSubmission: true,
15 | },
16 | },
17 | });
18 |
19 | expect(wrapper.html()).toMatch('form-submission');
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/app/frontend/tests/unit/views/user/Submissions.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils';
2 | import { describe, expect, it } from 'vitest';
3 |
4 | import Submissions from '~/views/user/Submissions.vue';
5 |
6 | describe('Submissions.vue', () => {
7 | it('renders', () => {
8 | const wrapper = mount(Submissions, {
9 | props: {
10 | f: 'f',
11 | },
12 | global: {
13 | stubs: {
14 | BaseSecure: {
15 | name: 'BaseSecure',
16 | template: '
',
17 | },
18 | MySubmissionsTable: true,
19 | },
20 | },
21 | });
22 |
23 | expect(wrapper.html()).toMatch('base-secure');
24 | expect(wrapper.html()).toMatch('my-submissions-table');
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/app/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | clearMocks: true,
3 | collectCoverage: true,
4 | collectCoverageFrom: ['src/**/*.js', '!src/db/migrations/*.js', '!src/db/seeds/*.js', '!src/forms/common/models/(tables|views)/*.js', '!frontend/**/*.*'],
5 | moduleFileExtensions: ['js', 'json'],
6 | moduleNameMapper: {
7 | '^~/(.*)$': '/src/$1',
8 | },
9 | testMatch: ['**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'],
10 | testPathIgnorePatterns: ['frontend'],
11 | testEnvironmentOptions: {
12 | url: 'http://localhost/',
13 | },
14 | transformIgnorePatterns: ['/node_modules/(?!@json2csv|@streamparser)'],
15 | };
16 |
--------------------------------------------------------------------------------
/app/lcov-fix.js:
--------------------------------------------------------------------------------
1 | // Jest 25.x onwards emits coverage reports on a different source path
2 | // https://stackoverflow.com/q/60323177
3 | const fs = require('fs');
4 | const file = './coverage/lcov.info';
5 |
6 | fs.readFile(file, 'utf8', (err, data) => {
7 | if (err) {
8 | return console.error(err); // eslint-disable-line no-console
9 | }
10 | const result = data.replace(/src/g, `${process.cwd()}/src`);
11 |
12 | fs.writeFile(file, result, 'utf8', (err) => {
13 | if (err) return console.error(err); // eslint-disable-line no-console
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/app/nodemon.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": [
3 | "frontend/node_modules",
4 | "frontend/src",
5 | "frontend/tests",
6 | "node_modules/**/node_modules",
7 | "tests"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/db/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.js]
2 | indent_size = unset
3 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20201007112921_005-submissions-data-vw.js:
--------------------------------------------------------------------------------
1 |
2 | exports.up = function(knex) {
3 | return Promise.resolve()
4 | .then(() => knex.schema.raw(`create or replace view submissions_data_vw as
5 | select s."confirmationId", s."formName", s.version, s."createdAt",
6 | u."fullName", u.username, u.email,
7 | fs.submission -> 'data' AS "submission", s.deleted, s.draft,
8 | s."submissionId", s."formId", s."formVersionId", u.id as "userId", u."keycloakId", u."firstName", u."lastName"
9 | from submissions_vw s
10 | inner join form_submission fs on s."submissionId" = fs.id
11 | inner join form_submission_user fsu on s."submissionId" = fsu."formSubmissionId" and fsu.permission = 'submission_create'
12 | inner join "user" u on fsu."userId" = u.id
13 | order by s."createdAt", s."formName", s.version`));
14 | };
15 |
16 | exports.down = function(knex) {
17 | return Promise.resolve()
18 | .then(() => knex.schema.raw('DROP VIEW IF EXISTS submissions_data_vw'));
19 | };
20 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20201029141347_008-form-settings-notifications.js:
--------------------------------------------------------------------------------
1 |
2 | exports.up = function (knex) {
3 | return Promise.resolve()
4 | .then(() => knex.schema.alterTable('form', table => {
5 | table.boolean('showSubmissionConfirmation').notNullable().defaultTo(true).comment('Show (when true) confirmation/receipt information to the submitter on success');
6 | table.specificType('submissionReceivedEmails', 'text ARRAY').comment('Array of email addresses to deliver notifications after a submission is received.');
7 | }));
8 | };
9 |
10 | exports.down = function (knex) {
11 | return Promise.resolve()
12 | .then(() => knex.schema.alterTable('form', table => {
13 | table.dropColumn('showSubmissionConfirmation');
14 | table.dropColumn('submissionReceivedEmails');
15 | }));
16 | };
17 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20201105120909_009-file-upload.js:
--------------------------------------------------------------------------------
1 | const stamps = require('../stamps');
2 |
3 | exports.up = function (knex) {
4 | return Promise.resolve().then(() =>
5 | knex.schema.createTable('file_storage', (table) => {
6 | table.uuid('id').primary();
7 | table.string('originalName', 1024).notNullable();
8 | table.string('mimeType').notNullable();
9 | table.integer('size').notNullable();
10 | table.enu('storage', ['uploads', 'localStorage', 'objectStorage']).notNullable().defaultTo('uploads');
11 | table.string('path', 1024).notNullable();
12 | table.uuid('formSubmissionId').references('id').inTable('form_submission').nullable().index();
13 | stamps(knex, table);
14 | })
15 | );
16 | };
17 |
18 | exports.down = function (knex) {
19 | return Promise.resolve().then(() => knex.schema.dropTableIfExists('file_storage'));
20 | };
21 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20210528134214_016-submission-submitters-vw copy.js:
--------------------------------------------------------------------------------
1 | exports.up = function(knex) {
2 | return Promise.resolve()
3 | .then(() => knex.schema.raw(`create or replace view submissions_submitters_vw as
4 | SELECT
5 | fsu.*,
6 | fv."formId",
7 | fv."version",
8 | sub."id",
9 | sub."confirmationId",
10 | sub."createdAt",
11 | sub."draft",
12 | sub."deleted"
13 | FROM
14 | form_submission_users_vw fsu
15 | INNER JOIN form_submission sub ON
16 | sub."id" = fsu."formSubmissionId"
17 | INNER JOIN form_version fv ON
18 | fv."id" = sub."formVersionId"`));
19 | };
20 |
21 | exports.down = function(knex) {
22 | return Promise.resolve()
23 | .then(() => knex.schema.raw('DROP VIEW IF EXISTS submissions_submitters_vw'));
24 | };
25 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20210816000000_020-user-form-preferences.js:
--------------------------------------------------------------------------------
1 | const stamps = require('../stamps');
2 |
3 | exports.up = function (knex) {
4 | return Promise.resolve()
5 | .then(() => knex.schema.createTable('user_form_preferences', table => {
6 | table.primary(['userId', 'formId']);
7 | table.uuid('userId').references('id').inTable('user').notNullable();
8 | table.uuid('formId').references('id').inTable('form').notNullable();
9 | table.jsonb('preferences');
10 | stamps(knex, table);
11 | }));
12 | };
13 |
14 | exports.down = function (knex) {
15 | return Promise.resolve()
16 | .then(() => knex.schema.dropTableIfExists('user_form_preferences'));
17 | };
18 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20210928000000_022-add-bceid-idps.js:
--------------------------------------------------------------------------------
1 | const CREATED_BY = 'migration-022';
2 |
3 | exports.up = function(knex) {
4 | return Promise.resolve()
5 | .then(() => {
6 | return knex('identity_provider').insert([
7 | {
8 | createdBy: CREATED_BY,
9 | code: 'bceid-basic',
10 | display: 'Basic BCeID',
11 | active: true,
12 | idp: 'bceid-basic'
13 | },
14 | {
15 | createdBy: CREATED_BY,
16 | code: 'bceid-business',
17 | display: 'Business BCeID',
18 | active: true,
19 | idp: 'bceid-business'
20 | }
21 | ]);
22 | });
23 | };
24 |
25 | exports.down = function(knex) {
26 | return Promise.resolve()
27 | .then(() => {
28 | return knex('identity_provider').where('createdBy', CREATED_BY).del();
29 | });
30 | };
31 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20211006000000_023-add-user-idps.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve()
3 | // Add optional idpCode foreign key column
4 | .then(() => knex.schema.alterTable('user', table => {
5 | table.string('idpCode').references('code').inTable('identity_provider').comment('The associated identity provider');
6 | }))
7 | // Set idpCode to 'idir'
8 | .then(() => knex('user').update({ idpCode: 'idir' }));
9 | };
10 |
11 | exports.down = function (knex) {
12 | return Promise.resolve()
13 | .then(() => knex.schema.alterTable('user', table => {
14 | table.dropColumn('idpCode');
15 | }));
16 | };
17 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20221205215308_025-add-idp-guids.js:
--------------------------------------------------------------------------------
1 | exports.up = function(knex) {
2 | return Promise.resolve()
3 | .then(() => knex.schema.alterTable('user', table => {
4 | table.string('idpUserId').comment('The unique identifier provided by the identity provider');
5 | }));
6 | };
7 |
8 | exports.down = function(knex) {
9 | return Promise.resolve()
10 | .then(() => knex.schema.alterTable('user', table => {
11 | table.dropColumn('idpUserId');
12 | }));
13 | };
14 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20230110063945_027-form_components_proactive_help.js:
--------------------------------------------------------------------------------
1 | const stamps = require('../stamps');
2 |
3 | exports.up = function (knex) {
4 | return Promise.resolve().then(() =>
5 | knex.schema.createTable('form_components_proactive_help', (table) => {
6 | table.uuid('id').primary();
7 | table.string('componentName').notNullable();
8 | table.string('externalLink');
9 | table.binary('image');
10 | table.string('imageType');
11 | table.string('componentImageName');
12 | table.string('groupName').notNullable();
13 | table.text('description');
14 | table.boolean('isLinkEnabled').defaultTo(false);
15 | table.boolean('publishStatus').defaultTo(false);
16 | stamps(knex, table);
17 | })
18 | );
19 | };
20 |
21 | exports.down = function (knex) {
22 | return Promise.resolve().then(() => knex.schema.dropTableIfExists('form_components_proactive_help'));
23 | };
24 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20230110063945_028-alter-form-table-to-add-reminder-schedule-copy-col.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve().then(() =>
3 | knex.schema.alterTable('form', (table) => {
4 | table.jsonb('schedule').comment('Form level Schedule settings.');
5 | table.boolean('reminder_enabled').comment('Form level reminder settings.');
6 | table.boolean('enableCopyExistingSubmission').notNullable().defaultTo(false).comment('Form level feature settings.');
7 | })
8 | );
9 | };
10 |
11 | exports.down = function (knex) {
12 | return Promise.resolve().then(() =>
13 | knex.schema.alterTable('form', (table) => {
14 | table.dropColumn('schedule');
15 | table.dropColumn('reminder_enabled');
16 | table.dropColumn('enableCopyExistingSubmission');
17 | })
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20230412141347_029-form-settings-uploadfile.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve().then(() =>
3 | knex.schema.alterTable('form', (table) => {
4 | table.boolean('allowSubmitterToUploadFile').notNullable().defaultTo(false).comment('This parameter allow submitter to load data from json file');
5 | })
6 | );
7 | };
8 |
9 | exports.down = function (knex) {
10 | return Promise.resolve().then(() =>
11 | knex.schema.alterTable('form', (table) => {
12 | table.dropColumn('allowSubmitterToUploadFile');
13 | })
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20230705190020_change_file_storage_constrains.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve()
3 | .then(() => knex.schema.raw(`ALTER TABLE file_storage DROP CONSTRAINT file_storage_storage_check`))
4 | .then(() =>
5 | knex.schema.raw(`ALTER TABLE file_storage ADD CONSTRAINT
6 | file_storage_storage_check CHECK
7 | ((storage = ANY (ARRAY['uploads'::text, 'localStorage'::text, 'objectStorage'::text, 'exports'::text])))`)
8 | );
9 | };
10 |
11 | exports.down = function (knex) {
12 | return Promise.resolve()
13 | .then(() => knex.schema.raw(`ALTER TABLE file_storage DROP CONSTRAINT file_storage_storage_check`))
14 | .then(() =>
15 | knex.schema.raw(`ALTER TABLE file_storage ADD CONSTRAINT
16 | file_storage_storage_check CHECK
17 | ((storage = ANY (ARRAY['uploads'::text, 'localStorage'::text, 'objectStorage'::text, 'exports'::text])))`)
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20231123172822_send-team-notification-email.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve()
3 | .then(() => knex.schema.alterTable('form', table => {
4 | table.boolean('sendSubmissionReceivedEmail').defaultTo(true).comment('Keeps track of if forms should send a notification email');
5 | }));
6 | };
7 |
8 | exports.down = function (knex) {
9 | return Promise.resolve()
10 | .then(() => knex.schema.alterTable('form', table => {
11 | table.dropColumn('sendSubmissionReceivedEmail');
12 | }));
13 | };
14 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20240115201832_files-api-access.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { import("knex").Knex } knex
3 | * @returns { Promise }
4 | */
5 | exports.up = function(knex) {
6 | return Promise.resolve()
7 | .then(() => knex.schema.alterTable('form_api_key', table => {
8 | table.boolean('filesApiAccess').defaultTo(false).comment('Keeps track of whether files can be accessed using the API key');
9 | }));
10 | };
11 |
12 | /**
13 | * @param { import("knex").Knex } knex
14 | * @returns { Promise }
15 | */
16 | exports.down = function(knex) {
17 | return Promise.resolve()
18 | .then(() => knex.schema.alterTable('form_api_key', table => {
19 | table.dropColumn('filesApiAccess');
20 | }));
21 | };
22 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20240312164557_remove-confirmationid-constraint.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { import("knex").Knex } knex
3 | * @returns { Promise }
4 | */
5 | exports.up = function (knex) {
6 | return Promise.resolve().then(() =>
7 | knex.schema.alterTable('form_submission', (table) => {
8 | table.dropUnique('confirmationId');
9 | })
10 | );
11 | };
12 |
13 | /**
14 | * @param { import("knex").Knex } knex
15 | * @returns { Promise }
16 | */
17 | exports.down = function (knex) {
18 | return Promise.resolve().then(() =>
19 | knex.schema.alterTable('form_submission', (table) => {
20 | table.unique('confirmationId');
21 | })
22 | );
23 | };
24 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20240321170550_wide-form-layout.js:
--------------------------------------------------------------------------------
1 | exports.up = function (knex) {
2 | return Promise.resolve()
3 | .then(() => knex.schema.alterTable('form', table => {
4 | table.boolean('wideFormLayout').defaultTo(false).comment('Tracks if the form should be displayed in a wide layout');
5 | }));
6 | };
7 |
8 | exports.down = function (knex) {
9 | return Promise.resolve()
10 | .then(() => knex.schema.alterTable('form', table => {
11 | table.dropColumn('wideFormLayout');
12 | }));
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20240916104713_048-email-recipients.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { import("knex").Knex } knex
3 | * @returns { Promise }
4 | */
5 | exports.up = function(knex) {
6 | return Promise.resolve()
7 | .then(() => knex.schema.alterTable('form_submission_status', table => {
8 | table.specificType('emailRecipients', 'text ARRAY').comment('Array of email addresses (form submitters) to deliver notifications when the status is set to revising.');
9 | }));
10 | };
11 |
12 | /**
13 | * @param { import("knex").Knex } knex
14 | * @returns { Promise }
15 | */
16 | exports.down = function(knex) {
17 | return Promise.resolve()
18 | .then(() => knex.schema.alterTable('form_submission_status', table => {
19 | table.dropColumn('emailRecipients');
20 | }));
21 | };
22 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20241016164117__050-form-metadata.js:
--------------------------------------------------------------------------------
1 | const stamps = require('../stamps');
2 |
3 | /**
4 | * @param { import("knex").Knex } knex
5 | * @returns { Promise }
6 | */
7 |
8 | exports.up = function (knex) {
9 | return Promise.resolve().then(() =>
10 | knex.schema.createTable('form_metadata', (table) => {
11 | table.uuid('id').primary();
12 | table.uuid('formId').references('id').inTable('form').notNullable().index();
13 | table.jsonb('metadata');
14 | stamps(knex, table);
15 | })
16 | );
17 | };
18 |
19 | /**
20 | * @param { import("knex").Knex } knex
21 | * @returns { Promise }
22 | */
23 | exports.down = function (knex) {
24 | return Promise.resolve().then(() => knex.schema.dropTableIfExists('form_metadata'));
25 | };
26 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20250319062555_alter-form-table-to-enable_team_member_draft_share.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param { import("knex").Knex } knex
3 | * @returns { Promise }
4 | */
5 | exports.up = function (knex) {
6 | return Promise.resolve().then(() =>
7 | knex.schema.alterTable('form', (table) => {
8 | table.boolean('enableTeamMemberDraftShare').notNullable().defaultTo(false);
9 | })
10 | );
11 | };
12 |
13 | exports.down = function (knex) {
14 | return Promise.resolve().then(() =>
15 | knex.schema.alterTable('form', (table) => {
16 | table.dropColumn('enableTeamMemberDraftShare');
17 | })
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/app/src/db/migrations/20250502163949_enable-bcsc-idp.js:
--------------------------------------------------------------------------------
1 | const UPDATED_BY = 'enable-bcsc-idp-migration';
2 |
3 | /**
4 | * @param { import("knex").Knex } knex
5 | * @returns { Promise }
6 | */
7 | exports.up = function (knex) {
8 | return knex('identity_provider').where({ code: 'bcservicescard' }).update({
9 | active: true,
10 | updatedBy: UPDATED_BY,
11 | updatedAt: knex.fn.now(),
12 | });
13 | };
14 |
15 | /**
16 | * @param { import("knex").Knex } knex
17 | * @returns { Promise }
18 | */
19 | exports.down = function (knex) {
20 | return knex('identity_provider')
21 | .where({ code: 'bcservicescard' })
22 | .update({
23 | active: false,
24 | updatedBy: `${UPDATED_BY}-rollback`,
25 | updatedAt: knex.fn.now(),
26 | });
27 | };
28 |
--------------------------------------------------------------------------------
/app/src/db/stamps.js:
--------------------------------------------------------------------------------
1 | module.exports = (knex, table) => {
2 | table.string('createdBy').defaultTo('public');
3 | table.timestamp('createdAt', { useTz: true }).defaultTo(knex.fn.now());
4 | table.string('updatedBy');
5 | table.timestamp('updatedAt', { useTz: true }).defaultTo(knex.fn.now());
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/docs/.editorconfig:
--------------------------------------------------------------------------------
1 | [*postman_collection.json]
2 | indent_style = unset
3 | indent_size = unset
4 |
--------------------------------------------------------------------------------
/app/src/docs/docs.js:
--------------------------------------------------------------------------------
1 | const config = require('config');
2 |
3 | const docs = {
4 | getDocHTML: (version) => `
5 |
6 |
7 | Common Hosted Form Service - Documentation ${version}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 | `,
23 | };
24 |
25 | module.exports = docs;
26 |
--------------------------------------------------------------------------------
/app/src/forms/admin/fileService.js:
--------------------------------------------------------------------------------
1 | const storageService = require('../file/storage/storageService');
2 |
3 | const fileService = {
4 | create: async (imageData) => {
5 | return await storageService.uploadImage(imageData);
6 | },
7 |
8 | signedUrl: async (param) => {
9 | return await storageService.readSignedUrl(param.imageName);
10 | },
11 | };
12 |
13 | module.exports = fileService;
14 |
--------------------------------------------------------------------------------
/app/src/forms/admin/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('admin', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/bcgeoaddress/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 |
3 | module.exports = {
4 | searchBCGeoAddress: async (req, res, next) => {
5 | try {
6 | const { query } = req;
7 | const response = await service.searchBCGeoAddress(query);
8 | res.status(200).json(response);
9 | } catch (error) {
10 | next(error);
11 | }
12 | },
13 | advanceSearchBCGeoAddress: async (req, res, next) => {
14 | try {
15 | const { query } = req;
16 | const response = await service.advanceSearchBCGeoAddress(query);
17 | res.status(200).json(response);
18 | } catch (error) {
19 | next(error);
20 | }
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/app/src/forms/bcgeoaddress/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('bcgeoaddress', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/bcgeoaddress/routes.js:
--------------------------------------------------------------------------------
1 | const cors = require('cors');
2 | const routes = require('express').Router();
3 | const { Development } = require('../common/constants');
4 |
5 | const controller = require('./controller');
6 |
7 | // need to allow cors for OPTIONS call (localhost only)
8 | // formio component will call OPTIONS pre-flight
9 | routes.options('/advance/address', cors({ origin: Development.LOCALHOST_ORIGIN }));
10 |
11 | routes.get('/address', async (req, res, next) => {
12 | await controller.searchBCGeoAddress(req, res, next);
13 | });
14 |
15 | routes.get('/advance/address', cors({ origin: Development.LOCALHOST_ORIGIN }), async (req, res, next) => {
16 | await controller.advanceSearchBCGeoAddress(req, res, next);
17 | });
18 |
19 | module.exports = routes;
20 |
--------------------------------------------------------------------------------
/app/src/forms/bcgeoaddress/service.js:
--------------------------------------------------------------------------------
1 | const geoAddressService = require('../../components/geoAddressService');
2 |
3 | const service = {
4 | searchBCGeoAddress: async (query) => {
5 | let addresses = { features: [] };
6 |
7 | let searchAddresses = await geoAddressService.addressQuerySearch(query);
8 |
9 | if (searchAddresses?.features && Array.isArray(searchAddresses.features)) {
10 | searchAddresses.features.forEach((element) => {
11 | if (element?.properties?.fullAddress) {
12 | addresses.features.push({ geometry: { coordinates: element.geometry.coordinates }, properties: { fullAddress: element.properties.fullAddress } });
13 | }
14 | });
15 | }
16 | return addresses;
17 | },
18 |
19 | advanceSearchBCGeoAddress: async (query) => {
20 | return await geoAddressService.addressQuerySearch(query);
21 | },
22 | };
23 |
24 | module.exports = service;
25 |
--------------------------------------------------------------------------------
/app/src/forms/common/middleware/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | ...require('./errorHandler'),
3 | ...require('./rateLimiter'),
4 | };
5 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/jsonSchema.js:
--------------------------------------------------------------------------------
1 | module.exports.stamps = {
2 | createdBy: { type: ['string', 'null'] },
3 | createdAt: { type: ['string', 'null'] },
4 | updatedBy: { type: ['string', 'null'] },
5 | updatedAt: { type: ['string', 'null'] },
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/essAllowlist.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const stamps = require('../jsonSchema').stamps;
4 |
5 | class EssAllowlist extends Timestamps(Model) {
6 | static get tableName() {
7 | return 'ess_allowlist';
8 | }
9 |
10 | static get modifiers() {
11 | return {
12 | findByAccountName(query, accountName) {
13 | if (accountName !== undefined) {
14 | query.where('accountName', accountName);
15 | }
16 | },
17 | };
18 | }
19 | static get jsonSchema() {
20 | return {
21 | type: 'object',
22 | required: ['accountName'],
23 | properties: {
24 | accountName: { type: 'string' },
25 | notes: { type: 'object' },
26 | ...stamps,
27 | },
28 | additionalProperties: false,
29 | };
30 | }
31 | }
32 |
33 | module.exports = EssAllowlist;
34 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/externalAPIStatusCode.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const stamps = require('../jsonSchema').stamps;
4 |
5 | class ExternalAPIStatusCode extends Timestamps(Model) {
6 | static get tableName() {
7 | return 'external_api_status_code';
8 | }
9 |
10 | static get jsonSchema() {
11 | return {
12 | type: 'object',
13 | required: ['code'],
14 | properties: {
15 | code: { type: 'string' },
16 | display: { type: 'string' },
17 | ...stamps,
18 | },
19 | additionalProperties: false,
20 | };
21 | }
22 | }
23 |
24 | module.exports = ExternalAPIStatusCode;
25 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/formIdentityProvider.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const { Regex } = require('../../constants');
4 | const stamps = require('../jsonSchema').stamps;
5 |
6 | class FormIdentityProvider extends Timestamps(Model) {
7 | static get tableName() {
8 | return 'form_identity_provider';
9 | }
10 |
11 | static get jsonSchema() {
12 | return {
13 | type: 'object',
14 | required: ['formId'],
15 | properties: {
16 | id: { type: 'string', pattern: Regex.UUID },
17 | formId: { type: 'string', pattern: Regex.UUID },
18 | code: { type: 'string', maxLength: 255 },
19 | ...stamps,
20 | },
21 | additionalProperties: false,
22 | };
23 | }
24 | }
25 |
26 | module.exports = FormIdentityProvider;
27 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/label.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const { Regex } = require('../../constants');
4 | const stamps = require('../jsonSchema').stamps;
5 |
6 | class Label extends Timestamps(Model) {
7 | static get tableName() {
8 | return 'label';
9 | }
10 |
11 | static get jsonSchema() {
12 | return {
13 | type: 'object',
14 | required: ['userId'],
15 | properties: {
16 | id: { type: 'string', pattern: Regex.UUID },
17 | userId: { type: 'string', pattern: Regex.UUID },
18 | labelText: { type: 'string', minLength: 1, maxLength: 25 },
19 | ...stamps,
20 | },
21 | additionalProperties: false,
22 | };
23 | }
24 | }
25 |
26 | module.exports = Label;
27 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/statusCode.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const { Regex } = require('../../constants');
4 | const stamps = require('../jsonSchema').stamps;
5 |
6 | class StatusCode extends Timestamps(Model) {
7 | static get tableName() {
8 | return 'status_code';
9 | }
10 |
11 | static get jsonSchema() {
12 | return {
13 | type: 'object',
14 | required: ['code'],
15 | properties: {
16 | code: { type: 'string' },
17 | display: { type: 'string' },
18 | nextCodes: { type: ['array', 'null'], items: { type: 'string', pattern: Regex.EMAIL } },
19 | ...stamps,
20 | },
21 | additionalProperties: false,
22 | };
23 | }
24 | }
25 |
26 | module.exports = StatusCode;
27 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/tables/userFormPreferences.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 | const { Timestamps } = require('../mixins');
3 | const { Regex } = require('../../constants');
4 | const stamps = require('../jsonSchema').stamps;
5 |
6 | class UserFormPreferences extends Timestamps(Model) {
7 | static get tableName() {
8 | return 'user_form_preferences';
9 | }
10 |
11 | // This is a composite key - order of attributes is important
12 | static get idColumn() {
13 | return ['userId', 'formId'];
14 | }
15 |
16 | static get jsonSchema() {
17 | return {
18 | type: 'object',
19 | required: ['formId', 'userId'],
20 | properties: {
21 | userId: { type: 'string', pattern: Regex.UUID },
22 | formId: { type: 'string', pattern: Regex.UUID },
23 | preferences: { type: 'object' },
24 | ...stamps,
25 | },
26 | additionalProperties: false,
27 | };
28 | }
29 | }
30 |
31 | module.exports = UserFormPreferences;
32 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/utils.js:
--------------------------------------------------------------------------------
1 | const toArray = (values) => {
2 | if (values) {
3 | return Array.isArray(values) ? values.filter((p) => p && p.trim().length > 0) : [values].filter((p) => p && p.trim().length > 0);
4 | }
5 | return [];
6 | };
7 | const inArrayClause = (column, values) => {
8 | return values.map((p) => `'${p}' = ANY("${column}")`).join(' or ');
9 | };
10 |
11 | const inArrayFilter = (column, values) => {
12 | const clause = inArrayClause(column, values);
13 | return `(array_length("${column}", 1) > 0 and (${clause}))`;
14 | };
15 |
16 | const tableNames = (models) => {
17 | return Object.values(models).map((model) => model.tableName);
18 | };
19 |
20 | module.exports = {
21 | toArray,
22 | inArrayClause,
23 | inArrayFilter,
24 | tableNames,
25 | };
26 |
--------------------------------------------------------------------------------
/app/src/forms/common/models/views/publicFormAccess.js:
--------------------------------------------------------------------------------
1 | const { Model } = require('objection');
2 |
3 | class PublicFormAccess extends Model {
4 | static get tableName() {
5 | return 'public_form_access_vw';
6 | }
7 |
8 | static get modifiers() {
9 | return {
10 | filterActive(query, value) {
11 | if (value !== undefined) {
12 | query.where('active', value);
13 | }
14 | },
15 | filterFormId(query, value) {
16 | if (value) {
17 | query.where('formId', value);
18 | }
19 | },
20 | orderDefault(builder) {
21 | builder.orderByRaw('lower("formName")');
22 | },
23 | };
24 | }
25 | }
26 |
27 | module.exports = PublicFormAccess;
28 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/file-download-ready.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 | |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/reminder-form-not-fill.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
25 | |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/reminder-form-open.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 | |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/reminder-form-will-close.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
23 | |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/submission-assigned.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
28 | |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/forms/email/assets/bodies/submission-unassigned.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 | {{ messageLinkText }}
16 |
17 |
18 | |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/forms/file/index.js:
--------------------------------------------------------------------------------
1 | const config = require('config');
2 | const setupMount = require('../common/utils').setupMount;
3 | const routes = require('./routes');
4 |
5 | const _PATH = config.get('files.uploads.path') || 'files';
6 |
7 | const fileUpload = require('./middleware/upload').fileUpload;
8 |
9 | fileUpload.init({
10 | dir: config.has('files.uploads.dir') ? config.get('files.uploads.dir') : undefined,
11 | fieldName: config.has('files.uploads.fileKey') ? config.get('files.uploads.fileKey') : undefined,
12 | maxFileCount: config.has('files.uploads.fileCount') ? config.get('files.uploads.fileCount') : undefined,
13 | maxFileSize: config.has('files.uploads.fileMaxSize') ? config.get('files.uploads.fileMaxSize') : undefined,
14 | });
15 |
16 | module.exports.mount = (app) => {
17 | return setupMount(_PATH, app, routes);
18 | };
19 |
--------------------------------------------------------------------------------
/app/src/forms/form/encryptionKey/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 |
3 | module.exports = {
4 | listEncryptionAlgorithms: async (req, res, next) => {
5 | try {
6 | const response = await service.listEncryptionAlgorithms();
7 | res.status(200).json(response);
8 | } catch (error) {
9 | next(error);
10 | }
11 | },
12 | readEncryptionKey: async (req, res, next) => {
13 | try {
14 | const response = await service.readEncryptionKey(req.params.formId, req.params.formEncryptionKeyId);
15 | res.status(200).json(response);
16 | } catch (error) {
17 | next(error);
18 | }
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/app/src/forms/form/encryptionKey/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 | const { currentUser, hasFormPermissions } = require('../../auth/middleware/userAccess');
3 | const validateParameter = require('../../common/middleware/validateParameter');
4 | const P = require('../../common/constants').Permissions;
5 |
6 | const controller = require('./controller');
7 |
8 | routes.use(currentUser);
9 |
10 | routes.param('formId', validateParameter.validateFormId);
11 | routes.param('formEncryptionKeyId', validateParameter.validateFormEncryptionKeyId);
12 |
13 | routes.get('/encryptionKey/algorithms', async (req, res, next) => {
14 | await controller.listEncryptionAlgorithms(req, res, next);
15 | });
16 |
17 | routes.get('/:formId/encryptionKey/:formEncryptionKeyId', hasFormPermissions([P.FORM_READ, P.FORM_UPDATE]), async (req, res, next) => {
18 | await controller.readEncryptionKey(req, res, next);
19 | });
20 |
21 | module.exports = routes;
22 |
--------------------------------------------------------------------------------
/app/src/forms/form/eventStreamConfig/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 |
3 | module.exports = {
4 | readEventStreamConfig: async (req, res, next) => {
5 | try {
6 | const response = await service.readEventStreamConfig(req.params.formId);
7 | res.status(200).json(response);
8 | } catch (error) {
9 | next(error);
10 | }
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/app/src/forms/form/eventStreamConfig/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 | const { currentUser, hasFormPermissions } = require('../../auth/middleware/userAccess');
3 | const validateParameter = require('../../common/middleware/validateParameter');
4 | const P = require('../../common/constants').Permissions;
5 |
6 | const controller = require('./controller');
7 |
8 | routes.use(currentUser);
9 |
10 | routes.param('formId', validateParameter.validateFormId);
11 |
12 | routes.get('/:formId/eventStreamConfig', hasFormPermissions([P.FORM_READ, P.FORM_UPDATE]), async (req, res, next) => {
13 | await controller.readEventStreamConfig(req, res, next);
14 | });
15 |
16 | module.exports = routes;
17 |
--------------------------------------------------------------------------------
/app/src/forms/form/externalApi/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/app/src/forms/form/externalApi/index.js
--------------------------------------------------------------------------------
/app/src/forms/form/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | const encryptionKeyRoutes = require('./encryptionKey/routes');
5 | const eventStreamConfigRoutes = require('./eventStreamConfig/routes');
6 | const externalApiRoutes = require('./externalApi/routes');
7 |
8 | module.exports.mount = (app) => {
9 | const p = setupMount('forms', app, [routes, encryptionKeyRoutes, eventStreamConfigRoutes, externalApiRoutes]);
10 | return p;
11 | };
12 |
--------------------------------------------------------------------------------
/app/src/forms/permission/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 |
3 | module.exports = {
4 | list: async (req, res, next) => {
5 | try {
6 | const response = await service.list();
7 | res.status(200).json(response);
8 | } catch (error) {
9 | next(error);
10 | }
11 | },
12 |
13 | read: async (req, res, next) => {
14 | try {
15 | const response = await service.read(req.params.code);
16 | res.status(200).json(response);
17 | } catch (error) {
18 | next(error);
19 | }
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/app/src/forms/permission/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('permissions', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/permission/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 |
3 | const jwtService = require('../../components/jwtService');
4 | const currentUser = require('../auth/middleware/userAccess').currentUser;
5 | const validateParameter = require('../common/middleware/validateParameter');
6 | const controller = require('./controller');
7 |
8 | routes.use(jwtService.protect('admin'));
9 | routes.use(currentUser);
10 |
11 | routes.param('code', validateParameter.validatePermissionCode);
12 |
13 | routes.get('/', async (req, res, next) => {
14 | await controller.list(req, res, next);
15 | });
16 |
17 | routes.get('/:code', async (req, res, next) => {
18 | await controller.read(req, res, next);
19 | });
20 |
21 | module.exports = routes;
22 |
--------------------------------------------------------------------------------
/app/src/forms/proxy/error.js:
--------------------------------------------------------------------------------
1 | class ProxyServiceError extends Error {
2 | constructor(message) {
3 | super(message);
4 | this.name = 'ProxyServiceError';
5 | }
6 | }
7 |
8 | module.exports = ProxyServiceError;
9 |
--------------------------------------------------------------------------------
/app/src/forms/proxy/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('proxy', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/proxy/routes.js:
--------------------------------------------------------------------------------
1 | const cors = require('cors');
2 | const routes = require('express').Router();
3 | const { Development } = require('../common/constants');
4 |
5 | const { currentUser } = require('../auth/middleware/userAccess');
6 | const controller = require('./controller');
7 |
8 | // need to allow cors for OPTIONS call (localhost only)
9 | // formio component will call OPTIONS pre-flight
10 | routes.options('/external', cors({ origin: Development.LOCALHOST_ORIGIN }));
11 |
12 | // called with encrypted headers, no current user!!!
13 | routes.get('/external', cors({ origin: Development.LOCALHOST_ORIGIN }), async (req, res, next) => {
14 | await controller.callExternalApi(req, res, next);
15 | });
16 |
17 | routes.post('/headers', currentUser, async (req, res, next) => {
18 | await controller.generateProxyHeaders(req, res, next);
19 | });
20 |
21 | module.exports = routes;
22 |
--------------------------------------------------------------------------------
/app/src/forms/public/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 | module.exports = {
3 | sendReminderToSubmitter: async (req, res, next) => {
4 | try {
5 | const response = await service.sendReminderToSubmitter();
6 | res.status(200).json(response);
7 | } catch (error) {
8 | next(error);
9 | }
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/app/src/forms/public/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('public', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/public/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 |
3 | const apiAccess = require('./middleware/apiAccess');
4 | const controller = require('./controller');
5 |
6 | routes.get('/reminder', apiAccess.checkApiKey, async (req, res, next) => {
7 | await controller.sendReminderToSubmitter(req, res, next);
8 | });
9 |
10 | module.exports = routes;
11 |
--------------------------------------------------------------------------------
/app/src/forms/public/service.js:
--------------------------------------------------------------------------------
1 | const reminderService = require('../email/reminderService');
2 | const service = {
3 | sendReminderToSubmitter: async () => {
4 | return await reminderService._init();
5 | },
6 | };
7 |
8 | module.exports = service;
9 |
--------------------------------------------------------------------------------
/app/src/forms/rbac/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('rbac', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/role/controller.js:
--------------------------------------------------------------------------------
1 | const service = require('./service');
2 |
3 | module.exports = {
4 | list: async (req, res, next) => {
5 | try {
6 | const response = await service.list();
7 | res.status(200).json(response);
8 | } catch (error) {
9 | next(error);
10 | }
11 | },
12 |
13 | read: async (req, res, next) => {
14 | try {
15 | const response = await service.read(req.params.code);
16 | res.status(200).json(response);
17 | } catch (error) {
18 | next(error);
19 | }
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/app/src/forms/role/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('roles', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/role/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 |
3 | const jwtService = require('../../components/jwtService');
4 | const currentUser = require('../auth/middleware/userAccess').currentUser;
5 | const validateParameter = require('../common/middleware/validateParameter');
6 | const controller = require('./controller');
7 |
8 | jwtService.protect();
9 | routes.use(currentUser);
10 |
11 | routes.param('code', validateParameter.validateRoleCode);
12 |
13 | routes.get('/', async (req, res, next) => {
14 | await controller.list(req, res, next);
15 | });
16 |
17 | routes.get('/:code', async (req, res, next) => {
18 | await controller.read(req, res, next);
19 | });
20 |
21 | module.exports = routes;
22 |
--------------------------------------------------------------------------------
/app/src/forms/role/service.js:
--------------------------------------------------------------------------------
1 | const { Role } = require('../common/models');
2 |
3 | const service = {
4 | list: async () => {
5 | return Role.query().allowGraph('[permissions]').withGraphFetched('permissions(orderDefault)').modify('orderDefault');
6 | },
7 |
8 | read: async (code) => {
9 | return Role.query().findOne('code', code).allowGraph('[permissions]').withGraphFetched('permissions(orderDefault)').throwIfNotFound();
10 | },
11 | };
12 |
13 | module.exports = service;
14 |
--------------------------------------------------------------------------------
/app/src/forms/submission/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('submissions', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/user/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('users', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/utils/index.js:
--------------------------------------------------------------------------------
1 | const routes = require('./routes');
2 | const setupMount = require('../common/utils').setupMount;
3 |
4 | module.exports.mount = (app) => {
5 | return setupMount('utils', app, routes);
6 | };
7 |
--------------------------------------------------------------------------------
/app/src/forms/utils/routes.js:
--------------------------------------------------------------------------------
1 | const routes = require('express').Router();
2 |
3 | const { currentUser } = require('../auth/middleware/userAccess');
4 | const controller = require('../submission/controller');
5 |
6 | routes.use(currentUser);
7 |
8 | routes.post('/template/render', async (req, res, next) => {
9 | await controller.draftTemplateUploadAndRender(req, res, next);
10 | });
11 |
12 | module.exports = routes;
13 |
--------------------------------------------------------------------------------
/app/tests/fixtures/submission/kitchen_sink_submission_data_export_datagrid_fields_selection.json:
--------------------------------------------------------------------------------
1 | [
2 | "form.confirmationId",
3 | "form.formName",
4 | "form.version",
5 | "form.createdAt",
6 | "form.fullName",
7 | "form.username",
8 | "form.email",
9 | "fishermansName",
10 | "email",
11 | "forWhichBcLakeRegionAreYouCompletingTheseQuestions",
12 | "didYouFishAnyBcLakesThisYear",
13 | "oneRowPerLake.0.lakeName",
14 | "oneRowPerLake.0.closestTown",
15 | "oneRowPerLake.0.numberOfDays",
16 | "oneRowPerLake.0.dataGrid.0.fishType",
17 | "oneRowPerLake.0.dataGrid.1.fishType",
18 | "oneRowPerLake.0.dataGrid.0.numberCaught",
19 | "oneRowPerLake.0.dataGrid.1.numberCaught",
20 | "oneRowPerLake.0.dataGrid.0.numberKept",
21 | "oneRowPerLake.0.dataGrid.1.numberKept"
22 | ]
23 |
--------------------------------------------------------------------------------
/app/tests/unit/components/errorToProblem.spec.js:
--------------------------------------------------------------------------------
1 | const errorToProblem = require('../../../src/components/errorToProblem');
2 |
3 | const SERVICE = 'TESTSERVICE';
4 |
5 | describe('errorToProblem', () => {
6 | it('should throw a 404', () => {
7 | const error = {
8 | response: {
9 | data: { detail: 'detail' },
10 | status: 404,
11 | },
12 | };
13 |
14 | expect(() => errorToProblem(SERVICE, error)).toThrow('404');
15 | });
16 |
17 | it('should throw a 422', () => {
18 | const error = {
19 | response: {
20 | data: { detail: 'detail' },
21 | status: 422,
22 | },
23 | };
24 |
25 | expect(() => errorToProblem(SERVICE, error)).toThrow('422');
26 | });
27 |
28 | it('should throw a 502', () => {
29 | const error = {
30 | message: 'msg',
31 | };
32 |
33 | expect(() => errorToProblem(SERVICE, error)).toThrow('502');
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/clamav/.dockerignore:
--------------------------------------------------------------------------------
1 | charts/
--------------------------------------------------------------------------------
/clamav/charts/clamav/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 | clamav.yaml
25 |
--------------------------------------------------------------------------------
/clamav/charts/clamav/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: clamav
3 | description: Chart for deploying a Clam AV on kubernetes
4 | type: application
5 | version: 1.0.0
6 | appVersion: 1.0.5
7 | keywords:
8 | - clamav
9 | maintainers:
10 | - name: BC Gov
11 | url: https://github.com/bcgov/clamav
12 | kubeVersion: ">= 1.18.0"
13 |
--------------------------------------------------------------------------------
/clamav/charts/clamav/templates/nsp.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: networking.k8s.io/v1
2 | kind: NetworkPolicy
3 | metadata:
4 | name: {{ include "clamav.fullname" . }}-network-policy
5 | namespace: {{ .Release.Namespace }}
6 | labels:
7 | {{- include "clamav.labels" . | nindent 4 }}
8 | spec:
9 | podSelector:
10 | matchLabels:
11 | {{- include "clamav.selectorLabels" . | nindent 6 }}
12 | ingress:
13 | - from:
14 | - podSelector:
15 | matchLabels:
16 | role: {{ .Values.nsp.role }}
17 | namespaceSelector:
18 | matchLabels:
19 | environment: {{ .Values.nsp.environment }}
20 | name: {{ .Values.nsp.name }}
21 | policyTypes:
22 | - Ingress
--------------------------------------------------------------------------------
/clamav/charts/clamav/templates/pdb.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.pdb.create }}
2 | apiVersion: policy/v1
3 | kind: PodDisruptionBudget
4 | metadata:
5 | name: {{ include "clamav.fullname" . }}
6 | namespace: {{ .Release.Namespace }}
7 | labels: {{- include "clamav.labels" . | nindent 4 }}
8 | spec:
9 | {{- if .Values.pdb.minAvailable }}
10 | minAvailable: {{ .Values.pdb.minAvailable }}
11 | {{- end }}
12 | {{- if .Values.pdb.maxUnavailable }}
13 | maxUnavailable: {{ .Values.pdb.maxUnavailable }}
14 | {{- end }}
15 | selector:
16 | matchLabels: {{- include "clamav.selectorLabels" . | nindent 6 }}
17 | {{- end }}
18 |
--------------------------------------------------------------------------------
/clamav/charts/clamav/templates/service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ include "clamav.fullname" . }}
5 | namespace: {{ .Release.Namespace }}
6 | labels:
7 | {{- include "clamav.labels" . | nindent 4 }}
8 | spec:
9 | ports:
10 | - port: {{ .Values.service.port }}
11 | targetPort: 3310
12 | protocol: TCP
13 | name: clamav
14 | selector:
15 | {{- include "clamav.selectorLabels" . | nindent 4 }}
16 |
--------------------------------------------------------------------------------
/clamav/charts/clamav/values-dev.yaml:
--------------------------------------------------------------------------------
1 | nsp:
2 | environment: dev
3 |
--------------------------------------------------------------------------------
/clamav/charts/clamav/values-test.yaml:
--------------------------------------------------------------------------------
1 | nsp:
2 | environment: test
3 |
--------------------------------------------------------------------------------
/clamav/clamdcheck.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -eu
4 |
5 | if [ "${CLAMAV_NO_CLAMD:-}" != "false" ]; then
6 | if [ "$(echo "PING" | nc localhost 3310)" != "PONG" ]; then
7 | echo "ERROR: Unable to contact server"
8 | exit 1
9 | fi
10 |
11 | echo "Clamd is up"
12 | fi
13 |
14 | exit 0
--------------------------------------------------------------------------------
/components/.gitignore:
--------------------------------------------------------------------------------
1 | # Editor directories and files
2 | .DS_Store
3 | lib
4 | dist
5 | node_modules
6 |
7 | # Editor directories and files
8 | .idea
9 | .vscode
10 | *.iml
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 | *.sw?
16 | *.mp4
17 |
18 |
--------------------------------------------------------------------------------
/components/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/components/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const gulp = require('gulp');
3 | const insert = require('gulp-insert');
4 | const rename = require('gulp-rename');
5 | const template = require('gulp-template');
6 |
7 | // Compile all *.ejs files to pre-compiled templates and append *.js to the filename.
8 | gulp.task('templates', () =>
9 | gulp.src('./src/**/*.ejs')
10 | .pipe(template.precompile({
11 | evaluate: /\{%([\s\S]+?)%\}/g,
12 | interpolate: /\{\{([\s\S]+?)\}\}/g,
13 | escape: /\{\{\{([\s\S]+?)\}\}\}/g,
14 | variable: 'ctx'
15 | }))
16 | .pipe(insert.prepend('Object.defineProperty(exports, "__esModule", {\n' +
17 | ' value: true\n' +
18 | '});\n' +
19 | 'exports.default='))
20 | .pipe(rename({
21 | extname: '.ejs.js'
22 | }))
23 | .pipe(gulp.dest('lib'))
24 | );
25 |
--------------------------------------------------------------------------------
/components/src/components/BCAddress/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/_classes/component/Component.form';
2 | import AddressEditProvider from './editForm/Address.edit.provider';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | label: 'Provider',
8 | key: 'provider',
9 | weight: 150,
10 | components: AddressEditProvider,
11 | },
12 | ], ...extend);
13 | }
14 |
--------------------------------------------------------------------------------
/components/src/components/Common/Advanced.edit.api.ts:
--------------------------------------------------------------------------------
1 | import ComponentEditApi from 'formiojs/components/_classes/component/editForm/Component.edit.api';
2 | export default [
3 | ...ComponentEditApi
4 | ];
--------------------------------------------------------------------------------
/components/src/components/Common/Advanced.edit.conditional.ts:
--------------------------------------------------------------------------------
1 | import ComponentEditConditional from 'formiojs/components/_classes/component/editForm/Component.edit.conditional';
2 | export default [
3 | ...ComponentEditConditional
4 | ];
--------------------------------------------------------------------------------
/components/src/components/Common/Advanced.edit.data.ts:
--------------------------------------------------------------------------------
1 | import ComponentEditData from 'formiojs/components/_classes/component/editForm/Component.edit.data';
2 | import TextFieldEditData from 'formiojs/components/textfield/editForm/TextField.edit.data';
3 | export default [...ComponentEditData, ...TextFieldEditData];
--------------------------------------------------------------------------------
/components/src/components/Common/Advanced.edit.layout.ts:
--------------------------------------------------------------------------------
1 | import ComponentEditLayout from 'formiojs/components/_classes/component/editForm/Component.edit.layout';
2 | export default [
3 | ...ComponentEditLayout
4 | ];
--------------------------------------------------------------------------------
/components/src/components/Common/Advanced.edit.logic.ts:
--------------------------------------------------------------------------------
1 | import ComponentEditLogic from 'formiojs/components/_classes/component/editForm/Component.edit.logic';
2 | export default [
3 | ...ComponentEditLogic
4 | ];
--------------------------------------------------------------------------------
/components/src/components/Common/Constants.ts:
--------------------------------------------------------------------------------
1 | export abstract class Constants {
2 | static readonly DEFAULT_HELP_LINK: string =
3 | 'https://developer.gov.bc.ca/docs/default/component/chefs-techdocs';
4 | static readonly ADV: string = '';
5 | }
6 |
--------------------------------------------------------------------------------
/components/src/components/Common/Evaluator.ts:
--------------------------------------------------------------------------------
1 | const Evaluator = {
2 | noeval: false,
3 | protectedEval: false, // This property can be customized only by plugins
4 | };
5 |
6 | export default Evaluator;
7 |
--------------------------------------------------------------------------------
/components/src/components/Common/Simple.edit.api.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | weight: 0,
4 | type: 'textfield',
5 | input: true,
6 | key: 'key',
7 | label: 'Property Name',
8 | tooltip: 'The name of this field in the API endpoint.',
9 | validate: {
10 | pattern: '(\\w|\\w[\\w-.]*\\w)',
11 | patternMessage: 'The property name must only contain alphanumeric characters, underscores, dots and dashes and should not be ended by dash or dot.'
12 | }
13 | },
14 | ];
15 |
--------------------------------------------------------------------------------
/components/src/components/Common/Simple.edit.data.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable max-len */
2 | export default [
3 | {
4 | weight: 0,
5 | type: 'checkbox',
6 | label: 'Multiple Values',
7 | tooltip: 'Allows multiple values to be entered for this field.',
8 | key: 'multiple',
9 | input: true
10 | },
11 | {
12 | type: 'textfield',
13 | label: 'Default Value',
14 | key: 'defaultValue',
15 | weight: 5,
16 | placeholder: 'Default Value',
17 | tooltip: 'The will be the value for this field, before user interaction. Having a default value will override the placeholder text.',
18 | input: true
19 | },
20 | ];
21 | /* eslint-enable max-len */
22 |
--------------------------------------------------------------------------------
/components/src/components/Common/Simple.edit.display.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | key: 'tableView',
4 | ignore: true
5 | },
6 | {
7 | key: 'hidden',
8 | ignore: true
9 | },
10 | {
11 | key: 'autofocus',
12 | ignore: true
13 | },
14 | {
15 | key: 'tabindex',
16 | ignore: true
17 | },
18 | {
19 | key: 'modalEdit',
20 | ignore: true
21 | },
22 | {
23 | key: 'customClass',
24 | ignore: true
25 | },
26 | ];
27 |
--------------------------------------------------------------------------------
/components/src/components/Common/Simple.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import UseForCopy from './UseForCopy';
2 | /* eslint-disable quotes, max-len */
3 | export default [
4 | UseForCopy,
5 | {
6 | weight: 10,
7 | type: 'checkbox',
8 | label: 'Required',
9 | tooltip: 'A required field must be filled in before the form can be submitted.',
10 | key: 'validate.required',
11 | input: true
12 | },
13 | {
14 | weight: 200,
15 | key: 'validate.customMessage',
16 | label: 'Custom Error Message',
17 | placeholder: 'Custom Error Message',
18 | type: 'textfield',
19 | tooltip: 'Error message displayed if any error occurred.',
20 | input: true
21 | }
22 | ];
23 | /* eslint-enable quotes, max-len */
24 |
--------------------------------------------------------------------------------
/components/src/components/Common/UseForCopy.ts:
--------------------------------------------------------------------------------
1 | const UseForCopy = {
2 | weight: 10,
3 | type: 'checkbox',
4 | defaultValue: false,
5 | label: 'Allow value propagation',
6 | tooltip: 'Enabling this checkbox will allow this field to be duplicated in new submission.',
7 | key: 'validate.isUseForCopy',
8 | input: true
9 | };
10 |
11 | export default UseForCopy;
12 |
--------------------------------------------------------------------------------
/components/src/components/Common/function.ts:
--------------------------------------------------------------------------------
1 | export function reArrangeComponents(neededposition=[], components=[]) {
2 | const newPosition = [];
3 | // tslint:disable-next-line: no-unused-expression
4 | neededposition.length && neededposition.map((posKey) => {
5 | components.findIndex((comp) => {
6 | if(comp.key === posKey){
7 | newPosition.push(comp);
8 | }
9 | });
10 | });
11 |
12 | return Array.from(new Set(newPosition.map(a => a.key)))
13 | .map(key => {
14 | return newPosition.find(a => a.key === key)
15 | });
16 | }
--------------------------------------------------------------------------------
/components/src/components/Map/Common/Constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare abstract class Constants {
2 | static readonly DEFAULT_HELP_LINK: string;
3 | static readonly ADV: string;
4 | }
5 |
--------------------------------------------------------------------------------
/components/src/components/Map/Common/Constants.js:
--------------------------------------------------------------------------------
1 | export class Constants {
2 | static DEFAULT_HELP_LINK = 'https://github.com/bcgov/common-hosted-form-service/wiki';
3 | static ADV = '';
4 | }
5 |
--------------------------------------------------------------------------------
/components/src/components/Map/Common/marker-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/components/src/components/Map/Common/marker-icon.png
--------------------------------------------------------------------------------
/components/src/components/Map/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | const customValidation = [
2 | {
3 | weight: 3,
4 | type: 'checkbox',
5 | label: 'Required',
6 | tooltip:
7 | 'A required field must be filled in before the form can be submitted.',
8 | key: 'validate.required',
9 | input: true,
10 | },
11 | {
12 | weight: 200,
13 | key: 'validate.customMessage',
14 | label: 'Custom Error Message',
15 | placeholder: 'Custom Error Message',
16 | type: 'textfield',
17 | tooltip: 'Error message displayed if any error occurred.',
18 | input: true,
19 | },
20 | ];
21 | export default {
22 | key: 'customValidation',
23 | label: 'Validation',
24 | weight: 10,
25 | components: customValidation,
26 | };
27 |
--------------------------------------------------------------------------------
/components/src/components/OrgBook/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/_classes/component/Component.form';
2 |
3 | import EditData from './editForm/Orgbook.edit.data';
4 | import EditDisplay from './editForm/Orgbook.edit.display';
5 | import EditValidation from './editForm/Orgbook.edit.validation';
6 |
7 | export default function(...extend) {
8 | return baseEditForm([
9 | {
10 | key: 'display',
11 | components: EditDisplay
12 | },
13 | {
14 | key: 'data',
15 | components: EditData
16 | },
17 | {
18 | key: 'validation',
19 | components: EditValidation
20 | }
21 | ], ...extend);
22 | }
23 |
--------------------------------------------------------------------------------
/components/src/components/OrgBook/editForm/Orgbook.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default [
3 | ...common,
4 | ];
5 |
--------------------------------------------------------------------------------
/components/src/components/OrgBook/editForm/Orgbook.edit.validation.ts:
--------------------------------------------------------------------------------
1 | export default [];
2 |
--------------------------------------------------------------------------------
/components/src/components/SimpleAddressAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/address/Address.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | },
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleAddressAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validate.required',
7 | 'unique',
8 | 'validateOn',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors',
14 | ];
15 |
16 | const newPosition = reArrangeComponents(neededposition,common);
17 |
18 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleBCAddress/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/_classes/component/Component.form';
2 | import AddressEditProvider from './editForm/Address.edit.provider';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | label: 'Provider',
8 | key: 'provider',
9 | weight: 150,
10 | components: AddressEditProvider,
11 | },
12 | ], ...extend);
13 | }
14 |
--------------------------------------------------------------------------------
/components/src/components/SimpleButtonAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/button/Button.form';
2 |
3 | export default baseEditForm;
4 |
--------------------------------------------------------------------------------
/components/src/components/SimpleButtonReset/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components: [
5 | ...common,
6 | {
7 | key: 'refreshOnChange',
8 | ignore: true
9 | },
10 | {
11 | key: 'className',
12 | ignore: true,
13 | },
14 | {
15 | key: 'labelPosition',
16 | ignore: true,
17 | },
18 | {
19 | key: 'placeholder',
20 | ignore: true,
21 | },
22 | {
23 | key: 'hideLabel',
24 | ignore: true,
25 | },
26 | {
27 | type: 'checkbox',
28 | key: 'block',
29 | label: 'Block Button',
30 | input: true,
31 | weight: 155,
32 | tooltip: 'This control should span the full width of the bounding container.',
33 | },
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCheckbox/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default [
3 | ...common,
4 | {
5 | key: 'refreshOnChange',
6 | ignore: true
7 | },
8 | {
9 | key: 'className',
10 | ignore: true,
11 | },
12 | {
13 | key: 'prefix',
14 | ignore: true
15 | },
16 | {
17 | key: 'suffix',
18 | ignore: true
19 | },
20 | {
21 | key: 'labelPosition',
22 | ignore: true,
23 | },
24 | {
25 | key: 'placeholder',
26 | ignore: true,
27 | },
28 | ];
29 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCheckbox/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.validation';
2 | export default [
3 | ...common,
4 | ];
5 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCheckboxAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/checkbox/Checkbox.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCheckboxAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import validationComponents from 'formiojs/components/checkbox/editForm/Checkbox.edit.validation';
3 | import {reArrangeComponents} from '../../Common/function';
4 |
5 | const neededposition = [
6 | 'validate.isUseForCopy',
7 | 'validate.required',
8 | 'errorLabel',
9 | 'validate.customMessage',
10 | 'custom-validation-js',
11 | 'json-validation-json',
12 | 'errors',
13 | ];
14 |
15 | const newPosition = reArrangeComponents(neededposition,[...validationComponents,...common]);
16 |
17 |
18 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleCheckboxes/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components:
5 | [
6 | ...common,
7 | {
8 | key: 'refreshOnChange',
9 | ignore: true
10 | },
11 | {
12 | key: 'className',
13 | ignore: true,
14 | },
15 | {
16 | key: 'attrs',
17 | ignore: true
18 | },
19 | {
20 | key: 'widget',
21 | ignore: true
22 | },
23 | {
24 | key: 'uniqueOptions',
25 | ignore: true
26 | },
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/components/src/components/SimpleContent/Component.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable */
2 | import { Components } from 'formiojs';
3 | const ParentComponent = (Components as any).components.content;
4 | import editForm from './Component.form';
5 |
6 | import { Constants } from '../Common/Constants';
7 |
8 | const ID = 'simplecontent';
9 | const DISPLAY = 'Text/Images';
10 |
11 | export default class Component extends (ParentComponent as any) {
12 | static schema(...extend) {
13 | return ParentComponent.schema({
14 | type: ID,
15 | label: DISPLAY,
16 | key: ID,
17 | input: false,
18 | html: ''
19 | }, ...extend);
20 | }
21 |
22 | public static editForm = editForm;
23 |
24 | static get builderInfo() {
25 | return {
26 | title: DISPLAY,
27 | group: 'simple',
28 | icon: 'pencil-square-o',
29 | weight: 40,
30 | documentation: Constants.DEFAULT_HELP_LINK,
31 | schema: Component.schema()
32 | };
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCurrencyAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/currency/Currency.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleCurrencyAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors',
14 | ];
15 |
16 | const newPosition = reArrangeComponents(neededposition,[...common]);
17 |
18 |
19 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleDateTime/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.data';
2 | export default [
3 | ...common,
4 | ];
5 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDateTime/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default [
3 | ...common,
4 | {
5 | key: 'refreshOnChange',
6 | ignore: true
7 | },
8 | {
9 | key: 'className',
10 | ignore: true,
11 | },
12 | {
13 | key: 'prefix',
14 | ignore: true
15 | },
16 | {
17 | key: 'suffix',
18 | ignore: true
19 | },
20 | {
21 | key: 'inputMask',
22 | ignore: true
23 | },
24 | {
25 | key: 'allowMultipleMasks',
26 | ignore: true
27 | },
28 | {
29 | key: 'showWordCount',
30 | ignore: true,
31 | },
32 | {
33 | key: 'showCharCount',
34 | ignore: true,
35 | },
36 | ];
37 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDateTimeAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/datetime/DateTime.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDateTimeAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import validationComponents from 'formiojs/components/datetime/editForm/DateTime.edit.validation';
3 | import {reArrangeComponents} from '../../Common/function';
4 |
5 | const neededposition = [
6 | 'validate.isUseForCopy',
7 | 'validateOn',
8 | 'validate.required',
9 | 'enableMinDateInput',
10 | 'datePicker.minDate',
11 | 'enableMaxDateInput',
12 | 'datePicker.maxDate',
13 | 'unique',
14 | 'errorLabel',
15 | 'validate.customMessage',
16 | 'custom-validation-js',
17 | 'json-validation-json',
18 | 'errors',
19 | ];
20 |
21 | const newPosition = reArrangeComponents(neededposition,[...validationComponents,...common]);
22 |
23 |
24 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleDay/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | type: 'textfield',
4 | label: 'Default Value',
5 | key: 'defaultValue',
6 | weight: 5,
7 | placeholder: 'Default Value',
8 | tooltip: 'The will be the value for this field, before user interaction. Having a default value will override the placeholder text.',
9 | input: true
10 | },
11 | ];
12 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDay/editForm/Component.edit.month.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | wieght: 200,
4 | type: 'select',
5 | datasrc: 'values',
6 | key: 'fields.month.type',
7 | label: 'Type of input',
8 | data: {
9 | values: [
10 | {
11 | label: 'Number',
12 | value: 'number'
13 | },
14 | {
15 | label: 'Select',
16 | value: 'select'
17 | },
18 | ]
19 | }
20 | },
21 | {
22 | weight: 210,
23 | type: 'textfield',
24 | input: true,
25 | key: 'fields.month.placeholder',
26 | label: 'Placeholder',
27 | placeholder: 'Month Placeholder',
28 | tooltip: 'The placeholder text that will appear when Month field is empty.'
29 | },
30 | {
31 | weight: 215,
32 | type: 'checkbox',
33 | label: 'Hidden',
34 | tooltip: 'Hide the Month part of the component.',
35 | key: 'fields.month.hide',
36 | input: true
37 | },
38 | ];
39 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDayAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/day/Day.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDayAdvanced/Component.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable */
2 | import { Components } from 'formiojs';
3 | const ParentComponent = (Components as any).components.day;
4 | import editForm from './Component.form';
5 |
6 | import { Constants } from '../Common/Constants';
7 |
8 | const ID = 'simpledayadvanced';
9 | const DISPLAY = 'Day';
10 | export default class Component extends (ParentComponent as any) {
11 | static schema(...extend) {
12 | return ParentComponent.schema({
13 | type: ID,
14 | label: DISPLAY,
15 | key: ID,
16 | }, ...extend);
17 | }
18 |
19 | public static editForm = editForm;
20 |
21 | static get builderInfo() {
22 | return {
23 | title: DISPLAY,
24 | group: 'advanced',
25 | icon: 'calendar',
26 | weight: 790,
27 | documentation: Constants.DEFAULT_HELP_LINK,
28 | schema: Component.schema()
29 | };
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/components/src/components/SimpleDayAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import validationComponents from 'formiojs/components/day/editForm/Day.edit.validation';
3 | import {reArrangeComponents} from '../../Common/function';
4 |
5 | const neededposition = [
6 | 'validate.isUseForCopy',
7 | 'validateOn',
8 | 'fields.day.required',
9 | 'fields.month.required',
10 | 'fields.year.required',
11 | 'maxDate',
12 | 'minDate',
13 | 'unique',
14 | 'errorLabel',
15 | 'validate.customMessage',
16 | 'custom-validation-js',
17 | 'json-validation-json',
18 | 'errors',
19 | ];
20 |
21 | const newPosition = reArrangeComponents(neededposition,[...validationComponents,...common]);
22 |
23 |
24 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleEmail/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.data';
2 | export default [
3 | ...common,
4 | {
5 | weight: 200,
6 | type: 'radio',
7 | label: 'Text Case',
8 | key: 'case',
9 | tooltip: 'When data is entered, you can change the case of the value.',
10 | input: true,
11 | values: [
12 | {
13 | value: 'mixed',
14 | label: 'Mixed (Allow upper and lower case)'
15 | },
16 | {
17 | value: 'uppercase',
18 | label: 'Uppercase'
19 | },
20 | {
21 | value: 'lowercase',
22 | label: 'Lowercase'
23 | }
24 | ]
25 | }
26 | ];
27 |
--------------------------------------------------------------------------------
/components/src/components/SimpleEmail/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components: [
5 | ...common,
6 | {
7 | key: 'refreshOnChange',
8 | ignore: true
9 | },
10 | {
11 | key: 'className',
12 | ignore: true,
13 | },
14 | {
15 | key: 'prefix',
16 | ignore: true
17 | },
18 | {
19 | key: 'suffix',
20 | ignore: true
21 | },
22 | {
23 | key: 'inputMask',
24 | ignore: true
25 | },
26 | {
27 | key: 'allowMultipleMasks',
28 | ignore: true
29 | },
30 | {
31 | key: 'showWordCount',
32 | ignore: true,
33 | },
34 | {
35 | key: 'showCharCount',
36 | ignore: true,
37 | },
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/components/src/components/SimpleEmailAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/email/Email.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 20,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleEmailAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'kickbox',
10 | 'validate.minLength',
11 | 'validate.maxLength',
12 | 'validate.pattern',
13 | 'errorLabel',
14 | 'validate.customMessage',
15 | 'errors',
16 | 'custom-validation-js',
17 | 'json-validation-json'
18 | ];
19 |
20 | const newPosition = reArrangeComponents(neededposition,common);
21 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleFile/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | weight: 0,
4 | type: 'checkbox',
5 | label: 'Multiple Values',
6 | tooltip: 'Allows multiple values to be entered for this field.',
7 | key: 'multiple',
8 | input: true
9 | },
10 | ];
11 |
--------------------------------------------------------------------------------
/components/src/components/SimpleFile/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default [
3 | ...common,
4 | {
5 | key: 'placeholder',
6 | ignore: true
7 | },
8 | {
9 | key: 'refreshOnChange',
10 | ignore: true
11 | },
12 | {
13 | key: 'className',
14 | ignore: true,
15 | },
16 | {
17 | key: 'prefix',
18 | ignore: true
19 | },
20 | {
21 | key: 'suffix',
22 | ignore: true
23 | },
24 | {
25 | key: 'inputMask',
26 | ignore: true
27 | },
28 | {
29 | key: 'allowMultipleMasks',
30 | ignore: true
31 | },
32 | {
33 | key: 'showWordCount',
34 | ignore: true,
35 | },
36 | {
37 | key: 'showCharCount',
38 | ignore: true,
39 | },
40 | ];
41 |
--------------------------------------------------------------------------------
/components/src/components/SimpleHeading/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/_classes/component/Component.form';
2 |
3 | import EditDisplay from './editForm/Component.edit.display';
4 |
5 | export default function(...extend) {
6 | return baseEditForm([
7 | {
8 | key: 'display',
9 | components: EditDisplay
10 |
11 | },
12 | {
13 | key: 'data',
14 | ignore: true
15 | },
16 | {
17 | key: 'validation',
18 | ignore: true
19 | },
20 | {
21 | key: 'api',
22 | ignore: true
23 | },
24 | {
25 | key: 'conditional',
26 | ignore: true
27 | },
28 | {
29 | key: 'layout',
30 | ignore: true
31 | }
32 | ], ...extend);
33 | }
34 |
--------------------------------------------------------------------------------
/components/src/components/SimpleNumber/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.data';
2 | export default [
3 | ...common,
4 | {
5 | type: 'checkbox',
6 | input: true,
7 | weight: 70,
8 | key: 'delimiter',
9 | label: 'Use Thousands Separator',
10 | tooltip: 'Separate thousands by local delimiter.'
11 | },
12 | {
13 | type: 'number',
14 | input: true,
15 | weight: 80,
16 | key: 'decimalLimit',
17 | label: 'Decimal Places',
18 | tooltip: 'The maximum number of decimal places.'
19 | },
20 | {
21 | type: 'checkbox',
22 | input: true,
23 | weight: 90,
24 | key: 'requireDecimal',
25 | label: 'Require Decimal',
26 | tooltip: 'Always show decimals, even if trailing zeros.'
27 | },
28 | ];
29 |
--------------------------------------------------------------------------------
/components/src/components/SimpleNumber/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components: [
5 | ...common,
6 | {
7 | key: 'refreshOnChange',
8 | ignore: true
9 | },
10 | {
11 | key: 'className',
12 | ignore: true,
13 | },
14 | {
15 | key: 'prefix',
16 | ignore: true
17 | },
18 | {
19 | key: 'suffix',
20 | ignore: true
21 | },
22 | {
23 | key: 'inputMask',
24 | ignore: true
25 | },
26 | {
27 | key: 'allowMultipleMasks',
28 | ignore: true
29 | },
30 | {
31 | key: 'showWordCount',
32 | ignore: true,
33 | },
34 | {
35 | key: 'showCharCount',
36 | ignore: true,
37 | },
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/components/src/components/SimpleNumber/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.validation';
2 | export default [
3 | ...common,
4 | {
5 | type: 'number',
6 | label: 'Minimum Value',
7 | key: 'validate.min',
8 | input: true,
9 | placeholder: 'Minimum Value',
10 | tooltip: 'The minimum value this field must have before the form can be submitted.',
11 | weight: 150
12 | },
13 | {
14 | type: 'number',
15 | label: 'Maximum Value',
16 | key: 'validate.max',
17 | input: true,
18 | placeholder: 'Maximum Value',
19 | tooltip: 'The maximum value this field can have before the form can be submitted.',
20 | weight: 160
21 | }
22 | ];
23 |
--------------------------------------------------------------------------------
/components/src/components/SimpleNumberAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/number/Number.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleNumberAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import NumberEditValidation from 'formiojs/components/number/editForm/Number.edit.validation';
3 | import {reArrangeComponents} from '../../Common/function';
4 |
5 | const neededposition = [
6 | 'validate.isUseForCopy',
7 | 'validateOn',
8 | 'validate.required',
9 | 'validate.min',
10 | 'validate.max',
11 | 'errorLabel',
12 | 'validate.customMessage',
13 | 'errors',
14 | 'custom-validation-js',
15 | 'json-validation-json'
16 | ];
17 |
18 | const newPosition = reArrangeComponents(neededposition,[...NumberEditValidation, ...common]);
19 |
20 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleParagraph/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/_classes/component/Component.form';
2 |
3 | import EditDisplay from './editForm/Component.edit.display';
4 |
5 | export default function(...extend) {
6 | return baseEditForm([
7 | {
8 | key: 'display',
9 | components: EditDisplay
10 |
11 | },
12 | {
13 | key: 'data',
14 | ignore: true
15 | },
16 | {
17 | key: 'validation',
18 | ignore: true
19 | },
20 | {
21 | key: 'api',
22 | ignore: true
23 | },
24 | {
25 | key: 'conditional',
26 | ignore: true
27 | },
28 | {
29 | key: 'layout',
30 | ignore: true
31 | }
32 | ], ...extend);
33 | }
34 |
--------------------------------------------------------------------------------
/components/src/components/SimplePasswordAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/password/Password.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 20,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimplePasswordAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'validate.minLength',
9 | 'validate.maxLength',
10 | 'validate.pattern',
11 | 'errorLabel',
12 | 'validate.customMessage',
13 | 'custom-validation-js',
14 | 'json-validation-json',
15 | 'errors',
16 | ];
17 |
18 | const newPosition = reArrangeComponents(neededposition,common);
19 |
20 | export default newPosition;
21 |
--------------------------------------------------------------------------------
/components/src/components/SimplePhoneNumber/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.data';
2 | export default [
3 | ...common,
4 | ];
5 |
--------------------------------------------------------------------------------
/components/src/components/SimplePhoneNumberAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/phonenumber/PhoneNumber.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimplePhoneNumberAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors'
14 | ];
15 |
16 | const newPosition = reArrangeComponents(neededposition,common);
17 |
18 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleRadioAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/radio/Radio.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleRadioAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 | import validationComponents from 'formiojs/components/radio/editForm/Radio.edit.validation';
4 |
5 | const neededposition = [
6 | 'validate.isUseForCopy',
7 | 'validate.required',
8 | 'validate.onlyAvailableItems',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors',
14 | ];
15 |
16 |
17 | const newPosition = reArrangeComponents(neededposition,[...validationComponents,...common]);
18 |
19 |
20 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleRadios/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components: [
5 | ...common,
6 | {
7 | key: 'refreshOnChange',
8 | ignore: true
9 | },
10 | {
11 | key: 'className',
12 | ignore: true,
13 | },
14 | {
15 | key: 'attrs',
16 | ignore: true
17 | },
18 | {
19 | key: 'widget',
20 | ignore: true
21 | },
22 | {
23 | key: 'uniqueOptions',
24 | ignore: true
25 | },
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/components/src/components/SimpleRadios/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.validation';
2 |
3 | export default [
4 | ...common
5 | ];
6 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSelect/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.display';
2 | export default {
3 | key: 'display',
4 | components: [
5 | ...common,
6 | {
7 | key: 'refreshOnChange',
8 | ignore: true
9 | },
10 | {
11 | key: 'className',
12 | ignore: true,
13 | },
14 | {
15 | key: 'attrs',
16 | ignore: true
17 | },
18 | {
19 | key: 'widget',
20 | ignore: true
21 | },
22 | {
23 | key: 'uniqueOptions',
24 | ignore: true
25 | },
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSelect/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.validation';
2 | export default [
3 | ...common,
4 | ];
5 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSelectAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/select/Select.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSelectBoxesAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/selectboxes/SelectBoxes.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSignatureAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/signature/Signature.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSignatureAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validate.required',
7 | 'errorLabel',
8 | 'validate.customMessage',
9 | 'custom-validation-js',
10 | 'json-validation-json',
11 | 'errors',
12 | ];
13 |
14 |
15 | const newPosition = reArrangeComponents(neededposition,[...common]);
16 |
17 |
18 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleSurveyAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/survey/Survey.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleSurveyAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validate.required',
7 | 'unique',
8 | 'errorLabel',
9 | 'validate.customMessage',
10 | 'custom-validation-js',
11 | 'json-validation-json',
12 | 'errors',
13 | ];
14 |
15 |
16 | const newPosition = reArrangeComponents(neededposition,[...common]);
17 |
18 |
19 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleTagsAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/tags/Tags.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTagsAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validate.required',
7 | 'unique',
8 | 'validateOn',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors',
14 | ];
15 |
16 | const newPosition = reArrangeComponents(neededposition,common);
17 |
18 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleTextAreaAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/textarea/TextArea.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 20,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTextAreaAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'validate.minLength',
10 | 'validate.maxLength',
11 | 'validate.minWords',
12 | 'validate.maxWords',
13 | 'validate.pattern',
14 | 'errorLabel',
15 | 'validate.customMessage',
16 | 'errors',
17 | 'custom-validation-js',
18 | 'json-validation-json'
19 | ];
20 |
21 | const newPosition = reArrangeComponents(neededposition,common);
22 |
23 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleTextField/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.data';
2 | export default [
3 | ...common,
4 | {
5 | weight: 200,
6 | type: 'radio',
7 | label: 'Text Case',
8 | key: 'case',
9 | tooltip: 'When data is entered, you can change the case of the value.',
10 | input: true,
11 | values: [
12 | {
13 | value: 'mixed',
14 | label: 'Mixed (Allow upper and lower case)'
15 | },
16 | {
17 | value: 'uppercase',
18 | label: 'Uppercase'
19 | },{
20 | value: 'lowercase',
21 | label: 'Lowercase'
22 | }
23 | ]
24 | }
25 | ];
26 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTextField/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Simple.edit.validation';
2 | export default [
3 | ...common,
4 | {
5 | weight: 110,
6 | key: 'validate.minLength',
7 | label: 'Minimum Length',
8 | placeholder: 'Minimum Length',
9 | type: 'number',
10 | tooltip: 'The minimum length requirement this field must meet.',
11 | input: true
12 | },
13 | {
14 | weight: 120,
15 | key: 'validate.maxLength',
16 | label: 'Maximum Length',
17 | placeholder: 'Maximum Length',
18 | type: 'number',
19 | tooltip: 'The maximum length requirement this field must meet.',
20 | input: true
21 | }
22 | ];
23 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTextFieldAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/textfield/TextField.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 | import EditDisplay from './editForm/Component.edit.display';
4 |
5 | export default function(...extend) {
6 | return baseEditForm([
7 | {
8 | key: 'display',
9 | ignore: true
10 | },
11 | {
12 | key: 'validation',
13 | ignore: true
14 | },
15 | {
16 | label: 'Display',
17 | key: 'customDisplay',
18 | weight: 5,
19 | components: EditDisplay
20 | },
21 | {
22 | label: 'Validation',
23 | key: 'customValidation',
24 | weight: 15,
25 | components: EditValidation
26 | }
27 | ], ...extend);
28 | }
29 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTextFieldAdvanced/editForm/Component.edit.display.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.display';
2 |
3 | import {reArrangeComponents} from '../../Common/function';
4 |
5 | const neededposition = [
6 | 'label',
7 | 'labelPosition',
8 | 'labelWidth',
9 | 'labelMargin',
10 | 'placeholder',
11 | 'description',
12 | 'tooltip',
13 | 'prefix',
14 | 'suffix',
15 | 'widget.type',
16 | 'widget',
17 | 'inputMask',
18 | 'displayMask',
19 | 'inputMaskPlaceholderChar',
20 | 'allowMultipleMasks',
21 | 'customClass',
22 | 'tabindex',
23 | 'autocomplete',
24 | 'hidden',
25 | 'hideLabel',
26 | 'showWordCount',
27 | 'showCharCount',
28 | 'mask',
29 | 'autofocus',
30 | 'spellcheck',
31 | 'disabled',
32 | 'tableView',
33 | 'modalEdit'
34 | ];
35 |
36 | const newPosition = reArrangeComponents(neededposition,common);
37 |
38 | export default newPosition;
39 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTextFieldAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'validate.minLength',
10 | 'validate.maxLength',
11 | 'validate.minWords',
12 | 'validate.maxWords',
13 | 'validate.pattern',
14 | 'errorLabel',
15 | 'validate.customMessage',
16 | 'errors',
17 | 'custom-validation-js',
18 | 'json-validation-json'
19 | ];
20 |
21 | const newPosition = reArrangeComponents(neededposition,common);
22 |
23 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleTime/editForm/Component.edit.data.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | type: 'textfield',
4 | label: 'Default Value',
5 | key: 'defaultValue',
6 | weight: 5,
7 | placeholder: 'Default Value',
8 | tooltip: 'The will be the value for this field, before user interaction. Having a default value will override the placeholder text.',
9 | input: true
10 | },
11 | {
12 | type: 'textfield',
13 | input: true,
14 | key: 'dataFormat',
15 | label: 'Data Format',
16 | placeholder: 'HH:mm:ss',
17 | tooltip: 'The moment.js format for saving the value of this field.',
18 | weight: 25,
19 | },
20 |
21 | ];
22 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTimeAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/time/Time.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTimeAdvanced/Component.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable */
2 | import { Components } from 'formiojs';
3 | const ParentComponent = (Components as any).components.time;
4 | import editForm from './Component.form';
5 |
6 | import { Constants } from '../Common/Constants';
7 |
8 | const ID = 'simpletimeadvanced';
9 | const DISPLAY = 'Time';
10 |
11 | export default class Component extends (ParentComponent as any) {
12 | static schema(...extend) {
13 | return ParentComponent.schema({
14 | type: ID,
15 | label: DISPLAY,
16 | key: ID,
17 | }, ...extend);
18 | }
19 |
20 | public static editForm = editForm;
21 |
22 | static get builderInfo() {
23 | return {
24 | title: DISPLAY,
25 | group: 'advanced',
26 | icon: 'clock-o',
27 | weight: 800,
28 | documentation: Constants.DEFAULT_HELP_LINK,
29 | schema: Component.schema()
30 | };
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/components/src/components/SimpleTimeAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validate.required',
7 | 'unique',
8 | 'validateOn',
9 | 'errorLabel',
10 | 'validate.customMessage',
11 | 'custom-validation-js',
12 | 'json-validation-json',
13 | 'errors',
14 | ];
15 |
16 | const newPosition = reArrangeComponents(neededposition,common);
17 |
18 |
19 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/components/SimpleUrlAdvanced/Component.form.ts:
--------------------------------------------------------------------------------
1 | import baseEditForm from 'formiojs/components/url/Url.form';
2 | import EditValidation from './editForm/Component.edit.validation';
3 |
4 | export default function(...extend) {
5 | return baseEditForm([
6 | {
7 | key: 'validation',
8 | ignore: true
9 | },
10 | {
11 | label: 'Validation',
12 | key: 'customValidation',
13 | weight: 15,
14 | components: EditValidation
15 | }
16 | ], ...extend);
17 | }
18 |
--------------------------------------------------------------------------------
/components/src/components/SimpleUrlAdvanced/editForm/Component.edit.validation.ts:
--------------------------------------------------------------------------------
1 | import common from '../../Common/Advanced.edit.validation';
2 | import {reArrangeComponents} from '../../Common/function';
3 |
4 | const neededposition = [
5 | 'validate.isUseForCopy',
6 | 'validateOn',
7 | 'validate.required',
8 | 'unique',
9 | 'validate.minLength',
10 | 'validate.maxLength',
11 | 'validate.pattern',
12 | 'errorLabel',
13 | 'validate.customMessage',
14 | 'errors',
15 | 'custom-validation-js',
16 | 'json-validation-json'
17 | ];
18 |
19 | const newPosition = reArrangeComponents(neededposition,common);
20 |
21 | export default newPosition;
--------------------------------------------------------------------------------
/components/src/ejs.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.ejs' {
2 | const value: string;
3 | export default value
4 | }
5 |
6 | declare var Formio: any;
7 |
--------------------------------------------------------------------------------
/components/src/index.ts:
--------------------------------------------------------------------------------
1 | import './overrides/editform/utils';
2 |
3 | import components from './components';
4 |
5 | export default {
6 | components,
7 | };
8 |
--------------------------------------------------------------------------------
/components/src/sass/contrib.scss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/components/src/sass/contrib.scss
--------------------------------------------------------------------------------
/components/src/use.ts:
--------------------------------------------------------------------------------
1 | import { Formio } from 'formiojs';
2 | import BcGovFormioComponents from './index';
3 | (Formio as any).use(BcGovFormioComponents);
4 | export default BcGovFormioComponents;
5 |
--------------------------------------------------------------------------------
/components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "preserveConstEnums": true,
5 | "outDir": "lib",
6 | "noImplicitAny": false,
7 | "sourceMap": false,
8 | "declaration": true,
9 | "rootDir": "src",
10 | "module": "esnext",
11 | "moduleResolution": "node",
12 | "lib": [
13 | "esnext",
14 | "dom"
15 | ],
16 | "types": ["vite/client"]
17 | },
18 | "include": [
19 | "src/*.ts",
20 | "src/*.ejs",
21 | "src/**/*.ts",
22 | "src/**/*.ejs"
23 | ],
24 | "exclude": [
25 | "node_modules",
26 | "**/*.spec.ts"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/components/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "jsRules": {},
7 | "rules": {
8 | "quotemark": [true, "single", "avoid-escape", "avoid-template"],
9 | "one-line": [false, "check-catch", "check-finally", "check-else"],
10 | "object-literal-sort-keys": false,
11 | "no-shadowed-variable": false,
12 | "variable-name": {
13 | "options": [
14 | "allow-leading-underscore",
15 | "allow-pascal-case",
16 | "ban-keywords"
17 | ]
18 | },
19 | "max-classes-per-file": [false]
20 | },
21 | "rulesDirectory": [],
22 | "exclude": [
23 | "lib",
24 | "node_modules"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/components/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | module: {
5 | rules: [
6 | {
7 | test: /\.css$/i,
8 | use: ["css-loader"],
9 | },
10 | ],
11 | },
12 | entry: path.join(path.resolve(__dirname, 'lib'), 'index.js'),
13 | output: {
14 | library: 'BcGovFormioComponents',
15 | libraryTarget: 'umd',
16 | libraryExport: 'default',
17 | path: path.resolve(__dirname, 'dist'),
18 | filename: 'bcgov-formio-components.js',
19 | },
20 | mode: 'development',
21 | performance: { hints: false },
22 | externals: {
23 | formiojs: 'Formio'
24 | }
25 | };
26 |
--------------------------------------------------------------------------------
/components/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const config = require('./webpack.config.js');
2 | config.mode = 'production';
3 | config.output.filename = 'bcgov-formio-components.min.js';
4 | module.exports = config;
5 |
--------------------------------------------------------------------------------
/components/webpack.use.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const config = require('./webpack.config.js');
3 | config.entry = path.join(path.resolve(__dirname, 'lib'), 'use.js'),
4 | config.mode = 'production';
5 | config.output.filename = 'bcgov-formio-components.use.min.js';
6 | module.exports = config;
7 |
--------------------------------------------------------------------------------
/openshift/allow-from-openshift-ingress.np.yaml:
--------------------------------------------------------------------------------
1 | kind: NetworkPolicy
2 | apiVersion: networking.k8s.io/v1
3 | metadata:
4 | name: allow-from-openshift-ingress
5 | spec:
6 | podSelector: {}
7 | ingress:
8 | - from:
9 | - namespaceSelector:
10 | matchLabels:
11 | network.openshift.io/policy-group: ingress
12 | policyTypes:
13 | - Ingress
14 | status: {}
15 |
--------------------------------------------------------------------------------
/openshift/app.dev.param:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/openshift/app.dev.param
--------------------------------------------------------------------------------
/openshift/app.prod.param:
--------------------------------------------------------------------------------
1 | CPU_LIMIT=1500m
2 | CPU_REQUEST=250m
3 | MEMORY_LIMIT=2Gi
4 | REPLICAS=3
5 |
--------------------------------------------------------------------------------
/openshift/app.test.param:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/openshift/app.test.param
--------------------------------------------------------------------------------
/openshift/clamav.dev.param:
--------------------------------------------------------------------------------
1 | HOST=10.98.191.237
2 | PORT=3310
--------------------------------------------------------------------------------
/openshift/clamav.prod.param:
--------------------------------------------------------------------------------
1 | HOST=10.98.60.250
2 | PORT=3310
--------------------------------------------------------------------------------
/openshift/clamav.test.param:
--------------------------------------------------------------------------------
1 | HOST=10.98.132.77
2 | PORT=3310
--------------------------------------------------------------------------------
/openshift/crunchydb/README.md:
--------------------------------------------------------------------------------
1 | # CrunchyDB
2 |
3 | CHEFS uses CrunchyDB for all of its highly available databases. CrunchyDB uses
4 | Patroni for replication and failovers, and Patroni uses PostgreSQL as the
5 | underlying database.
6 |
7 | ## Installation
8 |
9 | The CrunchyDB installations use the
10 | [Helm charts](https://github.com/bcgov/crunchy-postgres) provided by the fine
11 | folks over at platform services. Huge thanks go to that team for doing the hard
12 | work of figuring out the CrunchyDB setup and making it easier for the community
13 | to use CrunchyDB.
14 |
15 | The `charts` directory has been copied here so that changes to the upstream repo
16 | don't unexpectedly change our deployments. This stability and consistency comes
17 | at the cost of added maintenance effort to stay in sync.
18 |
19 | This code is current to commit `91d32cb` in December 2024.
20 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/crunchy-postgres/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/crunchy-postgres/templates/_s3.tpl:
--------------------------------------------------------------------------------
1 | {{/* Allow for S3 secret information to be stored in a Secret */}}
2 | {{- define "postgres.s3" }}
3 | [global]
4 | {{- if .s3 }}
5 | {{- if .s3.key }}
6 | repo{{ add .index 1 }}-s3-key={{ .s3.key }}
7 | {{- end }}
8 | {{- if .s3.keySecret }}
9 | repo{{ add .index 1 }}-s3-key-secret={{ .s3.keySecret }}
10 | {{- end }}
11 | {{- if .s3.keyType }}
12 | repo{{ add .index 1 }}-s3-key-type={{ .s3.keyType }}
13 | {{- end }}
14 | {{- if .s3.encryptionPassphrase }}
15 | repo{{ add .index 1 }}-cipher-pass={{ .s3.encryptionPassphrase }}
16 | {{- end }}
17 | {{- end }}
18 | {{ end }}
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/crunchy-postgres/templates/s3Secret.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.pgBackRest.s3.enabled .Values.pgBackRest.s3.createS3Secret }}
2 | apiVersion: v1
3 | kind: Secret
4 | metadata:
5 | name: {{ .Values.pgBackRest.s3.s3Secret }}
6 | type: Opaque
7 | data:
8 | {{- $args := dict "s3" .Values.pgBackRest.s3 "index" 1 }}
9 | s3.conf: |-
10 | {{ include "postgres.s3" $args | b64enc }}
11 | {{- end }}
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/deployer/deployerRoleBinding.yaml:
--------------------------------------------------------------------------------
1 | {{ if and .Values.deployer.serviceAccount.enabled (ne .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: RoleBinding
4 | apiVersion: rbac.authorization.k8s.io/v1
5 | metadata:
6 | name: {{ or .Values.deploymentName .Release.Name }}-deployer
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4}}
9 | roleRef:
10 | apiGroup: rbac.authorization.k8s.io
11 | kind: Role
12 | name: {{ or .Values.deploymentName .Release.Name }}-deployer
13 | subjects:
14 | - kind: ServiceAccount
15 | name: {{ or .Values.deploymentName .Release.Name }}-deployer
16 | namespace: {{ .Release.namespace }}
17 |
18 | {{ end }}
19 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/deployer/deployerServiceAccount.yaml:
--------------------------------------------------------------------------------
1 | {{ if and .Values.deployer.serviceAccount.enabled (ne .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: ServiceAccount
4 | apiVersion: v1
5 | metadata:
6 | name: {{ or .Values.deploymentName .Release.Name }}-deployer
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4}}
9 | namespace: {{ .Release.namespace }}
10 |
11 | {{ end }}
12 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/linter/linterRoleBinding.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.linter.serviceAccount.enabled (eq .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: RoleBinding
4 | apiVersion: rbac.authorization.k8s.io/v1
5 | metadata:
6 | name: {{ .Release.Name }}-linter
7 | labels: {{ include "crunchy-postgres-tools.labels" . | nindent 4}}
8 | roleRef:
9 | apiGroup: rbac.authorization.k8s.io
10 | kind: Role
11 | name: {{ .Release.Name }}-linter
12 | subjects:
13 | - kind: ServiceAccount
14 | name: {{ .Release.Name }}-linter
15 | namespace: {{ .Values.linter.namespace }}
16 |
17 | {{ end }}
18 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/linter/linterServiceAccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.linter.serviceAccount.enabled (eq .Release.Namespace .Values.provisioner.namespace)}}
2 |
3 | kind: ServiceAccount
4 | apiVersion: v1
5 | metadata:
6 | name: {{ .Release.Name }}-linter
7 | labels: {{ include "crunchy-postgres-tools.labels" . | nindent 4}}
8 | namespace: {{ .Values.linter.namespace }}
9 |
10 | {{ end }}
11 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/networking/networkPolicy.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.networking.networkPolicy.enabled (ne .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: NetworkPolicy
4 | apiVersion: networking.k8s.io/v1
5 | metadata:
6 | name: {{ or .Values.deploymentName .Release.Name }}-allow-route-ingress
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4}}
9 | spec:
10 | # This policy allows any pod with a route & service combination
11 | # to accept traffic from the OpenShift router pods. This is
12 | # required for things outside of OpenShift (like the Internet)
13 | # to reach your pods.
14 | ingress:
15 | - from:
16 | - namespaceSelector:
17 | matchLabels:
18 | network.openshift.io/policy-group: ingress
19 | podSelector: {}
20 | policyTypes:
21 | - Ingress
22 |
23 | {{- end }}
24 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/networking/podNetworkPolicy.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.networking.podNetworkPolicy.enabled (ne .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: NetworkPolicy
4 | apiVersion: networking.k8s.io/v1
5 | metadata:
6 | name: {{ or .Values.deploymentName .Release.Name }}-allow-same-namespace
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4}}
9 | spec:
10 | # This policy allows pods to accept traffic from other pods in this namespace
11 | ingress:
12 | - from:
13 | - podSelector: {}
14 | podSelector: {}
15 |
16 | {{ end }}
17 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/networking/route.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.networking.route.enabled (ne .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | apiVersion: route.openshift.io/v1
4 | kind: Route
5 | metadata:
6 | name: {{ template "crunchy-postgres-tools.fullname" . }}
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4}}
9 | spec:
10 | host: {{ .Values.networking.route.host }}
11 | port:
12 | targetPort: {{ template "crunchy-postgres-tools.fullname" . }}
13 | tls:
14 | termination: edge
15 | insecureEdgeTerminationPolicy: Redirect
16 | to:
17 | kind: Service
18 | name: {{ template "crunchy-postgres-tools.fullname" . }}
19 | weight: 100
20 |
21 | {{ end }}
22 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/provisioner/provisionerRoleBinding.yaml:
--------------------------------------------------------------------------------
1 | {{ if .Values.provisioner.serviceAccount.enabled }}
2 |
3 | kind: RoleBinding
4 | apiVersion: rbac.authorization.k8s.io/v1
5 | metadata:
6 | name: {{ .Release.Name }}-provisioner
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4 }}
9 | roleRef:
10 | apiGroup: rbac.authorization.k8s.io
11 | kind: Role
12 | name: {{ .Release.Name }}-provisioner
13 | subjects:
14 | - kind: ServiceAccount
15 | name: {{ .Release.Name }}-provisioner
16 | namespace: {{ .Values.provisioner.namespace }}
17 |
18 |
19 | {{ end }}
20 |
--------------------------------------------------------------------------------
/openshift/crunchydb/charts/tools/templates/provisioner/provisionerServiceAccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if and .Values.provisioner.serviceAccount.enabled (eq .Release.Namespace .Values.provisioner.namespace) }}
2 |
3 | kind: ServiceAccount
4 | apiVersion: v1
5 | metadata:
6 | name: {{ .Release.Name }}-provisioner
7 | labels:
8 | {{ include "crunchy-postgres-tools.labels" . | indent 4 }}
9 | namespace: {{ .Values.provisioner.namespace }}
10 |
11 | {{ end }}
12 |
--------------------------------------------------------------------------------
/openshift/ess.dev.param:
--------------------------------------------------------------------------------
1 | STREAMNAME=CHEFS
2 | SOURCE=chefs-dev
3 | DOMAIN=forms
4 | MAXAGE="604800000"
5 | MAXBYTES="966367641"
6 | MAXMSGS="1000"
7 | MAXMSGSIZE="966367"
8 | DUPLICATEWINDOW="60000"
9 | NUMREPLICAS="3"
10 | SERVERS=ess-nats.a191b5-dev.svc.cluster.local
11 | WEBSOCKETS=false
12 | CONSUMERSERVERS=stream-dev.apps.silver.devops.gov.bc.ca
--------------------------------------------------------------------------------
/openshift/ess.prod.param:
--------------------------------------------------------------------------------
1 | STREAMNAME=CHEFS
2 | SOURCE=chefs
3 | DOMAIN=forms
4 | MAXAGE="604800000"
5 | MAXBYTES="966367641"
6 | MAXMSGS="1000"
7 | MAXMSGSIZE="966367"
8 | DUPLICATEWINDOW="60000"
9 | NUMREPLICAS="3"
10 | SERVERS=ess-nats.a191b5-prod.svc.cluster.local
11 | WEBSOCKETS=false
12 | CONSUMERSERVERS=stream.digital.gov.bc.ca
--------------------------------------------------------------------------------
/openshift/ess.test.param:
--------------------------------------------------------------------------------
1 | STREAMNAME=CHEFS
2 | SOURCE=chefs-test
3 | DOMAIN=forms
4 | MAXAGE="900000"
5 | MAXBYTES="209715200"
6 | MAXMSGS="500"
7 | MAXMSGSIZE="419430"
8 | DUPLICATEWINDOW="60000"
9 | NUMREPLICAS="3"
10 | SERVERS=ess-nats.a191b5-test.svc.cluster.local
11 | WEBSOCKETS=false
12 | CONSUMERSERVERS=stream-test.apps.silver.devops.gov.bc.ca
--------------------------------------------------------------------------------
/openshift/patroni.dev.param:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/openshift/patroni.dev.param
--------------------------------------------------------------------------------
/openshift/patroni.prod.param:
--------------------------------------------------------------------------------
1 | CPU_LIMIT=2
2 | MEMORY_LIMIT=2048Mi
3 | MEMORY_REQUEST=1536Mi
4 |
--------------------------------------------------------------------------------
/openshift/patroni.test.param:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/openshift/patroni.test.param
--------------------------------------------------------------------------------
/openshift/redash/crunchydb-postgres-values-no-limits.yaml:
--------------------------------------------------------------------------------
1 | instances:
2 | limits:
3 | cpu:
4 | memory:
5 | replicaCertCopy:
6 | limits:
7 | cpu:
8 | memory:
9 |
10 | pgBackRest:
11 | repoHost:
12 | limits:
13 | cpu:
14 | memory:
15 | sidecars:
16 | limits:
17 | cpu:
18 | memory:
19 |
20 | proxy:
21 | pgBouncer:
22 | limits:
23 | cpu:
24 | memory:
25 |
--------------------------------------------------------------------------------
/openshift/redash/crunchydb-postgres-values.yaml:
--------------------------------------------------------------------------------
1 | fullnameOverride: crunchy-postgres-redash
2 |
3 | postgresVersion: 16
4 |
5 | instances:
6 | replicas: 3
7 | dataVolumeClaimSpec:
8 | storage: 512Mi
9 |
10 | pgBackRest:
11 | repos:
12 | schedules:
13 | full: 0 12 * * *
14 | incremental: 0 0,4,8,16,20 * * *
15 |
16 | proxy:
17 | pgBouncer:
18 | replicas: 3
19 |
--------------------------------------------------------------------------------
/openshift/redash/crunchydb-tools-values.yaml:
--------------------------------------------------------------------------------
1 | fullnameOverride: crunchy-postgres-tools-redash
2 | deploymentName: crunchy-postgres-redash
3 |
--------------------------------------------------------------------------------
/openshift/redash/redash.route.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | kind: Template
3 | apiVersion: template.openshift.io/v1
4 | labels:
5 | app.kubernetes.io/component: server
6 | app.kubernetes.io/instance: ${NAME}
7 | app.kubernetes.io/managed-by: kubectl
8 | app.kubernetes.io/name: redash
9 | app.kubernetes.io/part-of: redash
10 | metadata:
11 | name: ${NAME}
12 | objects:
13 | - kind: Route
14 | apiVersion: route.openshift.io/v1
15 | metadata:
16 | name: ${NAME}
17 | spec:
18 | host: ${NAME}.apps.silver.devops.gov.bc.ca
19 | port:
20 | targetPort: http
21 | tls:
22 | insecureEdgeTerminationPolicy: Redirect
23 | termination: edge
24 | to:
25 | kind: Service
26 | name: ${NAME}
27 | weight: 100
28 | wildcardPolicy: None
29 | parameters:
30 | - name: NAME
31 | displayName: Name
32 | description: The name assigned to all of the objects defined in this template.
33 | required: true
34 | value: chefs-redash
35 |
--------------------------------------------------------------------------------
/tests/functional/cypress/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | 'cypress'
4 | ],
5 | env: {
6 | mocha: true,
7 | 'cypress/globals': true
8 | },
9 | rules: {
10 | strict: 'off'
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/functional/cypress/e2e/about.cy.js:
--------------------------------------------------------------------------------
1 |
2 | const depEnv = Cypress.env('depEnv');
3 | const baseUrl = Cypress.env('baseUrl');
4 |
5 |
6 |
7 | describe('Application About Page', () => {
8 | it('Visits the app about page', () => {
9 |
10 | if(depEnv=="")
11 | {
12 | cy.visit(`/app`);
13 | cy.contains('Create, publish forms, and receive submissions with the Common Hosted Forms Service.').should('be.visible');
14 | }
15 | else
16 | {
17 |
18 | cy.visit(`/${depEnv}`);
19 | cy.contains('Create, publish forms, and receive submissions with the Common Hosted Forms Service.').should('be.visible');
20 | cy.get('[data-test="base-auth-btn"] > .v-btn > .v-btn__content > span').click();
21 | }
22 |
23 | });
24 | });
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/SamplePPTx.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/tests/functional/cypress/fixtures/SamplePPTx.pptx
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/Testing_files.txt:
--------------------------------------------------------------------------------
1 | Testing cdogs.txt
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/add1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/tests/functional/cypress/fixtures/add1.png
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/file_example_XLSX_50.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/tests/functional/cypress/fixtures/file_example_XLSX_50.xlsx
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/formInitialBuilder/add1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/tests/functional/cypress/fixtures/formInitialBuilder/add1.png
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/formInitialBuilder/ccHelpLinkInfoList.json:
--------------------------------------------------------------------------------
1 | {"Basic Layout":[{"id":"a96f3760-1444-4ac0-91c6-ec20793f5488","status":false,"componentName":"simplecols2","moreHelpInfoLink":"https://www.google.com/","imageUrl":"simplecols2.jpeg","version":7,"groupName":"Basic Layout","description":"Lorem Ipsum is"}]}
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/forms/empty-array.json:
--------------------------------------------------------------------------------
1 | []
2 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/forms/form-field.json:
--------------------------------------------------------------------------------
1 | ["simpletextfield"]
2 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/forms/form-submission-deleted.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "confirmationId": "ABF006D6",
4 | "createdAt": "2022-10-26T20:08:30.737Z",
5 | "formId": "1111111111-1111-1111-111111111111",
6 | "formSubmissionStatusCode": "SUBMITTED",
7 | "submissionId": "1111111111-1111-1111-111111111113",
8 | "deleted": true,
9 | "createdBy": "7ddfdd92d0c64cfc8d96a29a8a5bdcd7@idir@idir",
10 | "formVersionId": "1111111111-1111-1111-111111111112"
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/forms/form-submission.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "confirmationId": "ABF006D6",
4 | "createdAt": "2022-10-26T20:08:30.737Z",
5 | "formId": "1111111111-1111-1111-111111111111",
6 | "formSubmissionStatusCode": "SUBMITTED",
7 | "submissionId": "1111111111-1111-1111-111111111113",
8 | "deleted": false,
9 | "createdBy": "7ddfdd92d0c64cfc8d96a29a8a5bdcd7@idir@idir",
10 | "formVersionId": "1111111111-1111-1111-111111111112"
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/forms/form.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1111111111-1111-1111-111111111111",
3 | "name": "test",
4 | "description": "",
5 | "active": true,
6 | "labels": null,
7 | "createdBy": "7ddfdd92d0c64cfc8d96a29a8a5bdcd7@idir@idir",
8 | "createdAt": "2022-10-26T20:06:56.435Z",
9 | "updatedBy": null,
10 | "updatedAt": "2022-10-26T20:06:56.420Z",
11 | "showSubmissionConfirmation": true,
12 | "submissionReceivedEmails": [],
13 | "enableStatusUpdates": false,
14 | "enableSubmitterDraft": false,
15 | "versions": [
16 | {
17 | "id": "1111111111-1111-1111-111111111112",
18 | "formId": "1111111111-1111-1111-111111111111",
19 | "version": 1,
20 | "published": true,
21 | "createdBy": "7ddfdd92d0c64cfc8d96a29a8a5bdcd7@idir@idir",
22 | "createdAt": "2022-10-26T20:08:13.893Z",
23 | "updatedBy": null,
24 | "updatedAt": "2022-10-26T20:08:13.866Z"
25 | }
26 | ],
27 | "identityProviders": [],
28 | "snake": "test"
29 | }
30 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/kitchensink/formOptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "897e2ca1-d81c-4079-a135-63b930f98590",
3 | "name": "Kitchen Sink Simple",
4 | "description": "Test complicated form with the simple design interface",
5 | "idpHints": [
6 | "public"
7 | ],
8 | "snake": "kitchen_sink_simple"
9 | }
10 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/kitchensink/submissionOptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "submission": {
3 | "id": "3d2d6833-6e78-43e3-b332-6e66b6b8879c",
4 | "formVersionId": "897e2ca1-d81c-4079-a135-63b930f98590"
5 | },
6 | "version": {
7 | "id": "897e2ca1-d81c-4079-a135-63b930f98590",
8 | "formId": "897e2ca1-d81c-4079-a135-63b930f98590"
9 | },
10 | "form": {
11 | "id": "897e2ca1-d81c-4079-a135-63b930f98590",
12 | "name": "Kitchen Sink Simple",
13 | "description": "Test complicated form with the simple design interface",
14 | "idpHints": [
15 | "public"
16 | ],
17 | "snake": "kitchen_sink_simple"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/test.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/common-hosted-form-service/ee209435541c048da1bc081f42fd5008ae415c06/tests/functional/cypress/fixtures/test.docx
--------------------------------------------------------------------------------
/tests/functional/cypress/fixtures/users/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "username": "admin",
3 | "password": "admin"
4 | }
--------------------------------------------------------------------------------
/tests/functional/cypress/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chefs-cypress",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "Cypress functional test suite for CHEFS",
6 | "main": "index.js",
7 | "scripts": {
8 | "clean": "rm -rf **/screenshots **/videos",
9 | "purge": "rm -rf node_modules",
10 | "test": "cypress run",
11 | "test:allbrowsers": "npm run test:chrome && npm run test:edge && npm run test:firefox",
12 | "test:chrome": "npm run test -- --browser chrome",
13 | "test:dev": "cypress open",
14 | "test:edge": "npm run test -- --browser edge",
15 | "test:firefox": "npm run test -- --browser firefox"
16 | },
17 | "keywords": [
18 | "chefs",
19 | "cypress"
20 | ],
21 | "author": "",
22 | "license": "Apache-2.0",
23 | "dependencies": {
24 | "date-fns": "^2.26.0"
25 | },
26 | "devDependencies": {
27 | "cypress": "14.2.0",
28 | "cypress-file-upload": "^5.0.8",
29 | "cypress-keycloak-commands": "^1.2.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tests/functional/cypress/support/component.js:
--------------------------------------------------------------------------------
1 | import { mount } from 'cypress/vue'
2 |
3 | Cypress.Commands.add('mount', mount)
--------------------------------------------------------------------------------
/tests/functional/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
--------------------------------------------------------------------------------
/tests/functional/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands';
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/tests/performance/.sample-env:
--------------------------------------------------------------------------------
1 | OIDC_TOKEN_URL=https://dev.loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/token
2 | OIDC_CLIENT_ID=chefs-frontend-localhost-5300
3 |
4 | BASE_URL=http://localhost:8080/app
5 | FORM_NAME=01_kitchen_sink_advanced
6 | SCENARIOS=createAndPublishForm,fetchAndSubmitForm
7 |
8 | RPS=1
9 |
10 | TEST_RUN_USERS=1
11 | MIN_USERS=5
12 | MAX_USERS=50
13 | AVERAGE_USERS=35
14 | STRESS_LOAD_USERS=100
15 |
16 | STAGE=test_run
17 |
18 | INITIAL_TOKEN=
19 | INITIAL_REFRESH_TOKEN=
20 |
21 |
22 |
--------------------------------------------------------------------------------
/tests/performance/common/auth.js:
--------------------------------------------------------------------------------
1 | export const INITIAL_TOKEN = __ENV.INITIAL_TOKEN;
2 | export const INITIAL_REFRESH_TOKEN = __ENV.INITIAL_REFRESH_TOKEN;
3 |
4 | export const generateRequestConfig = (token) => {
5 | return {
6 | headers: {
7 | "Content-Type": "application/json",
8 | Authorization: `Bearer ${token}`,
9 | },
10 | };
11 | };
12 |
--------------------------------------------------------------------------------