From 95b5c0ef291d8dabc2723b61e74bc9235d3a13c3 Mon Sep 17 00:00:00 2001 From: jasonchung1871 <101672465+jasonchung1871@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:10:27 -0700 Subject: [PATCH 01/13] Update FormViewerMultiUpload.vue quick fix to missing module --- app/frontend/src/components/designer/FormViewerMultiUpload.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/frontend/src/components/designer/FormViewerMultiUpload.vue b/app/frontend/src/components/designer/FormViewerMultiUpload.vue index 3441c86c4..8e1d422a3 100644 --- a/app/frontend/src/components/designer/FormViewerMultiUpload.vue +++ b/app/frontend/src/components/designer/FormViewerMultiUpload.vue @@ -1,6 +1,6 @@ diff --git a/app/frontend/tests/unit/components/bcgov/BCGovAlertBanner.spec.js b/app/frontend/tests/unit/components/bcgov/BCGovAlertBanner.spec.js index e72645991..8ab59c095 100644 --- a/app/frontend/tests/unit/components/bcgov/BCGovAlertBanner.spec.js +++ b/app/frontend/tests/unit/components/bcgov/BCGovAlertBanner.spec.js @@ -36,7 +36,7 @@ describe('BCGovAlertBanner.vue', () => { await flushPromises(); expect(wrapper.html()).toContain(NotificationTypes.ERROR.type); - expect(wrapper.html()).toContain('Error'); + expect(wrapper.html()).toContain('defaultErrMsg'); }); it('renders with a custom error message', async () => { @@ -50,7 +50,7 @@ describe('BCGovAlertBanner.vue', () => { text: message, }, global: { - plugins: [router], + plugins: [pinia, router], }, }); diff --git a/app/frontend/tests/unit/store/modules/notifications.actions.spec.js b/app/frontend/tests/unit/store/modules/notifications.actions.spec.js index 1bc623597..32513bf8d 100644 --- a/app/frontend/tests/unit/store/modules/notifications.actions.spec.js +++ b/app/frontend/tests/unit/store/modules/notifications.actions.spec.js @@ -1,18 +1,11 @@ import { setActivePinia, createPinia } from 'pinia'; -import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; import { useNotificationStore } from '~/store/notification'; import { NotificationTypes } from '~/utils/constants'; describe('notifications actions', () => { - const mockConsoleError = vi.spyOn(console, 'error'); - beforeEach(() => { setActivePinia(createPinia()); - mockConsoleError.mockReset(); - }); - - afterAll(() => { - mockConsoleError.mockRestore(); }); it('addNotification should add notification', () => { @@ -23,7 +16,6 @@ describe('notifications actions', () => { }; const addNotificationSpy = vi.spyOn(mockStore, 'addNotification'); mockStore.addNotification(obj); - expect(mockConsoleError).toHaveBeenCalledTimes(1); expect(addNotificationSpy).toHaveBeenCalledTimes(1); expect(mockStore.notifications).toEqual([ { @@ -46,7 +38,6 @@ describe('notifications actions', () => { const addNotificationSpy = vi.spyOn(mockStore, 'addNotification'); mockStore.addNotification(obj); - expect(mockConsoleError).toHaveBeenCalledTimes(1); expect(addNotificationSpy).toHaveBeenCalledTimes(1); expect(mockStore.notifications).toEqual([ { @@ -66,7 +57,6 @@ describe('notifications actions', () => { }; const addNotificationSpy = vi.spyOn(mockStore, 'addNotification'); mockStore.addNotification(obj); - expect(mockConsoleError).toHaveBeenCalledTimes(0); expect(addNotificationSpy).toHaveBeenCalledTimes(1); expect(mockStore.notifications).toEqual([ { diff --git a/app/frontend/tests/unit/views/Error.spec.js b/app/frontend/tests/unit/views/Error.spec.js index 2a7ee3255..3c1a4ca66 100644 --- a/app/frontend/tests/unit/views/Error.spec.js +++ b/app/frontend/tests/unit/views/Error.spec.js @@ -29,13 +29,13 @@ describe('Error.vue', () => { await nextTick(); - expect(wrapper.text()).toMatch('Error: Something went wrong... :('); + expect(wrapper.text()).toMatch('trans.error.somethingWentWrong'); }); it('renders with a custom error message', async () => { const wrapper = mount(Error, { props: { - msg: 'Custom Error Message', + text: 'Custom Error Message', }, global: { plugins: [pinia], From 31cfbaa0bb80434f79d0ecf6d54f6b7af8bebf06 Mon Sep 17 00:00:00 2001 From: jasonchung1871 <101672465+jasonchung1871@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:36:18 -0700 Subject: [PATCH 05/13] Some fixes and sync with main BaseNotificationBar now allows for translating an unformatted locale message SubmissionsTable and MySubmissionsTable synced and search is working --- .../components/base/BaseNotificationBar.vue | 15 ++++--- .../src/components/forms/SubmissionsTable.vue | 37 +++++++--------- .../forms/submission/MySubmissionsTable.vue | 43 ++++++++++--------- app/frontend/src/store/form.js | 18 +++++++- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/app/frontend/src/components/base/BaseNotificationBar.vue b/app/frontend/src/components/base/BaseNotificationBar.vue index 88fc404dd..f2d41b462 100644 --- a/app/frontend/src/components/base/BaseNotificationBar.vue +++ b/app/frontend/src/components/base/BaseNotificationBar.vue @@ -20,18 +20,19 @@ export default { computed: { ...mapState(useFormStore, ['form', 'isRTL', 'lang']), }, - created() { + mounted() { if (this.notification.consoleError) { // eslint-disable-next-line no-console console.error( - i18n.t( - this.notification.consoleError.text, - this.notification.consoleError.options - ) + typeof this.notification.consoleError === 'string' || + this.notification.consoleError instanceof String + ? this.notification.consoleError + : i18n.t( + this.notification.consoleError.text, + this.notification.consoleError.options + ) ); } - }, - mounted() { const notificationStore = useNotificationStore(); this.timeout = setTimeout( () => notificationStore.deleteNotification(this.notification), diff --git a/app/frontend/src/components/forms/SubmissionsTable.vue b/app/frontend/src/components/forms/SubmissionsTable.vue index 5052b141b..dbcbef672 100644 --- a/app/frontend/src/components/forms/SubmissionsTable.vue +++ b/app/frontend/src/components/forms/SubmissionsTable.vue @@ -25,6 +25,7 @@ export default { return { // Show only items for the current logged in user currentUserOnly: false, + debounceInput: null, deleteItem: {}, // Show only deleted items deletedOnly: false, @@ -44,7 +45,6 @@ export default { loading: true, restoreItem: {}, search: '', - searchEnabled: false, selectedSubmissions: [], serverItems: [], showColumnsDialog: false, @@ -318,23 +318,10 @@ export default { }, //------------------------ END FILTER COLUMNS }, - watch: { - async search(newSearch, oldSearch) { - this.searchEnabled = true; - if (newSearch !== oldSearch) { - if (newSearch === '') { - this.searchEnabled = false; - await this.getSubmissionData(); - } else { - _.debounce(async () => { - await this.getSubmissionData(); - }, 300); - this.refreshSubmissions(); - } - } - }, - }, mounted() { + this.debounceInput = _.debounce(async () => { + this.refreshSubmissions(); + }, 300); this.refreshSubmissions(); }, methods: { @@ -378,7 +365,11 @@ export default { this.sortBy = {}; } this.itemsPerPage = itemsPerPage; - await this.getSubmissionData(); + if (this.search === '') { + await this.getSubmissionData(); + } else { + this.debounceInput(); + } }, async getSubmissionData() { let criteria = { @@ -388,7 +379,7 @@ export default { filterformSubmissionStatusCode: true, sortBy: this.sortBy, search: this.search, - searchEnabled: this.searchEnabled, + searchEnabled: this.search.length > 0, createdAt: Object.values({ minDate: this.userFormPreferences && @@ -469,7 +460,6 @@ export default { }, async refreshSubmissions() { this.loading = true; - this.page = 0; Promise.all([ this.getFormRolesForUser(this.formId), this.getFormPermissionsForUser(this.formId), @@ -552,6 +542,9 @@ export default { await this.populateSubmissionsTable(); }, + handleSearch(value) { + this.search = value; + }, }, }; @@ -660,7 +653,6 @@ export default { @@ -689,7 +682,7 @@ export default { :loading="loading" :loading-text="$t('trans.submissionsTable.loadingText')" :no-data-text=" - searchEnabled + search.length > 0 ? $t('trans.submissionsTable.noMachingRecordText') : $t('trans.submissionsTable.noDataText') " diff --git a/app/frontend/src/components/forms/submission/MySubmissionsTable.vue b/app/frontend/src/components/forms/submission/MySubmissionsTable.vue index 2acb5d345..39b654b04 100644 --- a/app/frontend/src/components/forms/submission/MySubmissionsTable.vue +++ b/app/frontend/src/components/forms/submission/MySubmissionsTable.vue @@ -1,4 +1,5 @@ @@ -390,7 +387,6 @@ export default { :class="isRTL ? 'float-left' : 'float-right'" > @@ -414,7 +411,11 @@ export default { :search="search" :loading="loading" :loading-text="$t('trans.mySubmissionsTable.loadingText')" - :no-data-text="$t('trans.mySubmissionsTable.noDataText')" + :no-data-text=" + search.length > 0 + ? $t('trans.mySubmissionsTable.noMatchingRecordText') + : $t('trans.mySubmissionsTable.noDataText') + " :lang="lang" @update:options="updateTableOptions" > diff --git a/app/frontend/src/store/form.js b/app/frontend/src/store/form.js index b1a4f2f35..e436a00c6 100644 --- a/app/frontend/src/store/form.js +++ b/app/frontend/src/store/form.js @@ -525,7 +525,14 @@ export const useFormStore = defineStore('form', { }); } }, - async fetchFormCSVExportFields({ formId, type, draft, deleted, version }) { + async fetchFormCSVExportFields({ + formId, + type, + draft, + deleted, + version, + singleRow, + }) { try { this.formFields = []; const { data } = await formService.readCSVExportFields( @@ -533,7 +540,8 @@ export const useFormStore = defineStore('form', { type, draft, deleted, - version + version, + singleRow ); this.formFields = data; } catch (error) { @@ -560,6 +568,8 @@ export const useFormStore = defineStore('form', { itemsPerPage, filterformSubmissionStatusCode, sortBy: sortBy, + search: search, + searchEnabled: searchEnabled, }) { try { this.submissionList = []; @@ -575,6 +585,8 @@ export const useFormStore = defineStore('form', { itemsPerPage: itemsPerPage, totalSubmissions: this.totalSubmissions, sortBy: sortBy, + search: search, + searchEnabled: searchEnabled, }) : await formService.listSubmissions(formId, { deleted: deletedOnly, @@ -586,6 +598,8 @@ export const useFormStore = defineStore('form', { itemsPerPage: itemsPerPage, totalSubmissions: this.totalSubmissions, sortBy: sortBy, + search: search, + searchEnabled: searchEnabled, }); this.submissionList = response.data.results; this.totalSubmissions = response.data.total; From d7017c5f802c7f12a20da9a824f72b859eb02e2e Mon Sep 17 00:00:00 2001 From: jasonchung1871 <101672465+jasonchung1871@users.noreply.github.com> Date: Mon, 25 Sep 2023 09:30:31 -0700 Subject: [PATCH 06/13] Form access validation and formio Form.io CSS styling moved away from the component level and into the root style.scss file. This seems to fix our issue but is not what we used to do. Unable to detect nested radio group in the form.idps for validation and there's no way to manually enforce a validation rules check. So when we detect a change in the idpType, we set the form idps ourselves and then change the userType twice to re-validate the radio group that is the parent. --- app/frontend/src/assets/scss/style.scss | 2 ++ .../src/components/designer/FormDesigner.vue | 3 --- .../src/components/designer/FormViewer.vue | 3 --- .../designer/settings/FormAccessSettings.vue | 27 ++++++++++++++++--- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/app/frontend/src/assets/scss/style.scss b/app/frontend/src/assets/scss/style.scss index e20cca29b..f677a6054 100644 --- a/app/frontend/src/assets/scss/style.scss +++ b/app/frontend/src/assets/scss/style.scss @@ -1,6 +1,8 @@ @import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900'); @import url('https://fonts.googleapis.com/css?family=Material+Icons'); @import '@mdi/font/css/materialdesignicons.css'; +@import '~font-awesome/css/font-awesome.min.css'; +@import '~formiojs/dist/formio.builder.min.css'; @import 'bootstrap-scss/bootstrap.scss'; // TODO: import this only for form designer/renderer formio components @import 'vue-json-pretty/lib/styles.css'; diff --git a/app/frontend/src/components/designer/FormDesigner.vue b/app/frontend/src/components/designer/FormDesigner.vue index 85fd363c6..0ca7dfedf 100644 --- a/app/frontend/src/components/designer/FormDesigner.vue +++ b/app/frontend/src/components/designer/FormDesigner.vue @@ -778,9 +778,6 @@ export default { diff --git a/app/frontend/src/components/forms/manage/EmailManagement.vue b/app/frontend/src/components/forms/manage/EmailManagement.vue index 157ad3143..4eb888ed3 100644 --- a/app/frontend/src/components/forms/manage/EmailManagement.vue +++ b/app/frontend/src/components/forms/manage/EmailManagement.vue @@ -1,3 +1,40 @@ + + diff --git a/app/frontend/src/views/form/Design.vue b/app/frontend/src/views/form/Design.vue index 2c64a1eae..e8d28cd6a 100644 --- a/app/frontend/src/views/form/Design.vue +++ b/app/frontend/src/views/form/Design.vue @@ -56,7 +56,7 @@ export default { methods: { ...mapActions(useFormStore, ['listFCProactiveHelp', 'deleteCurrentForm']), onFormLoad() { - this.$refs.formDesigner.onFormLoad(); + if (this.$refs?.formDesigner) this.$refs.formDesigner.onFormLoad(); }, }, }; diff --git a/app/frontend/src/views/form/PublishForm.vue b/app/frontend/src/views/form/PublishForm.vue index 1f88581a0..d17518aa8 100644 --- a/app/frontend/src/views/form/PublishForm.vue +++ b/app/frontend/src/views/form/PublishForm.vue @@ -1,4 +1,5 @@