From 014b9109ee03f13a67d29583e3a24d64ef16afb8 Mon Sep 17 00:00:00 2001 From: Kyle Morel Date: Wed, 27 Dec 2023 15:15:08 -0800 Subject: [PATCH 1/2] Align submission/activity view with new UX design --- .github/environments/values.pr.yaml | 2 +- .github/workflows/unit-tests.yaml | 2 + app/src/db/migrations/20231212000000_init.ts | 31 ++- app/src/db/models/submission.ts | 75 ++++-- app/src/db/prisma/schema.prisma | 65 +++-- app/src/services/chefs.ts | 17 +- app/src/types/ChefsSubmissionForm.ts | 38 +-- frontend/src/assets/main.scss | 4 + frontend/src/components/demo/DemoButtons.vue | 42 --- .../src/components/demo/DemoDataTable.vue | 166 ------------ frontend/src/components/demo/DemoHeadings.vue | 12 - frontend/src/components/demo/DemoModals.vue | 123 --------- frontend/src/components/demo/DemoToasts.vue | 40 --- frontend/src/components/demo/index.ts | 5 - frontend/src/components/form/Calendar.vue | 18 +- frontend/src/components/form/Checkbox.vue | 51 ++++ frontend/src/components/form/Dropdown.vue | 20 +- .../src/components/form/EditableDropdown.vue | 20 +- frontend/src/components/form/InputMask.vue | 53 ++++ frontend/src/components/form/InputNumber.vue | 62 +++++ .../form/{TextInput.vue => InputText.vue} | 18 +- frontend/src/components/form/Password.vue | 16 +- frontend/src/components/form/TextArea.vue | 18 +- frontend/src/components/form/index.ts | 5 +- .../components/submission/SubmissionForm.vue | 249 +++++++++++++----- frontend/src/lib/primevue/index.ts | 2 + frontend/src/router/index.ts | 6 - frontend/src/types/ChefsSubmissionForm.ts | 37 ++- frontend/src/utils/constants.ts | 2 + frontend/src/views/StylingsView.vue | 27 -- frontend/src/views/SubmissionView.vue | 4 +- .../form/{TextInput.spec.ts => InputText.ts} | 14 +- 32 files changed, 611 insertions(+), 633 deletions(-) delete mode 100644 frontend/src/components/demo/DemoButtons.vue delete mode 100644 frontend/src/components/demo/DemoDataTable.vue delete mode 100644 frontend/src/components/demo/DemoHeadings.vue delete mode 100644 frontend/src/components/demo/DemoModals.vue delete mode 100644 frontend/src/components/demo/DemoToasts.vue delete mode 100644 frontend/src/components/demo/index.ts create mode 100644 frontend/src/components/form/Checkbox.vue create mode 100644 frontend/src/components/form/InputMask.vue create mode 100644 frontend/src/components/form/InputNumber.vue rename frontend/src/components/form/{TextInput.vue => InputText.vue} (73%) delete mode 100644 frontend/src/views/StylingsView.vue rename frontend/tests/unit/components/form/{TextInput.spec.ts => InputText.ts} (81%) diff --git a/.github/environments/values.pr.yaml b/.github/environments/values.pr.yaml index 778d397e..e29cf5ec 100644 --- a/.github/environments/values.pr.yaml +++ b/.github/environments/values.pr.yaml @@ -1,6 +1,6 @@ --- patroni: - enabled: false + enabled: true replicaCount: 2 resources: limits: diff --git a/.github/workflows/unit-tests.yaml b/.github/workflows/unit-tests.yaml index 6b0132f4..6e80a05f 100644 --- a/.github/workflows/unit-tests.yaml +++ b/.github/workflows/unit-tests.yaml @@ -48,6 +48,8 @@ jobs: - name: Install dependencies if: steps.cache-app.outputs.cache-hit != 'true' run: npm ci + - name: Generate Prisma Schema + run: npm run prisma:generate - name: Test run: npm run test env: diff --git a/app/src/db/migrations/20231212000000_init.ts b/app/src/db/migrations/20231212000000_init.ts index 20ddc91f..9a885893 100644 --- a/app/src/db/migrations/20231212000000_init.ts +++ b/app/src/db/migrations/20231212000000_init.ts @@ -37,26 +37,35 @@ export async function up(knex: Knex): Promise { table.uuid('submissionId').primary(); table.uuid('assignedToUserId').references('userId').inTable('user').onUpdate('CASCADE').onDelete('CASCADE'); table.text('confirmationId').notNullable(); - table.text('contactEmail'); + table.timestamp('submittedAt', { useTz: true }).notNullable(); + table.text('submittedBy').notNullable(); + table.text('locationPIDs'); + table.text('contactName'); table.text('contactPhoneNumber'); - table.text('contactFirstName'); - table.text('contactLastName'); - table.text('intakeStatus'); + table.text('contactEmail'); table.text('projectName'); - table.integer('queuePriority'); table.text('singleFamilyUnits'); table.text('streetAddress'); - table.text('atsClientNumber'); + table.integer('latitude'); + table.integer('longitude'); + table.integer('queuePriority'); + table.text('relatedPermits'); + table.text('astNotes'); + table.boolean('astUpdated'); table.boolean('addedToATS'); + table.text('atsClientNumber'); + table.boolean('ltsaCompleted'); + table.boolean('naturalDisaster'); table.boolean('financiallySupported'); - table.text('applicationStatus'); - table.text('relatedPermits'); - table.boolean('updatedAai'); + table.boolean('financiallySupportedBC'); + table.boolean('financiallySupportedIndigenous'); + table.boolean('financiallySupportedNonProfit'); + table.boolean('financiallySupportedHousingCoop'); table.text('waitingOn'); - table.timestamp('submittedAt', { useTz: true }).notNullable(); - table.text('submittedBy').notNullable(); table.timestamp('bringForwardDate', { useTz: true }); table.text('notes'); + table.text('intakeStatus'); + table.text('applicationStatus'); stamps(knex, table); }) ) diff --git a/app/src/db/models/submission.ts b/app/src/db/models/submission.ts index 3dcc44a1..32e399d3 100644 --- a/app/src/db/models/submission.ts +++ b/app/src/db/models/submission.ts @@ -1,7 +1,6 @@ import { Prisma } from '@prisma/client'; import { default as user } from './user'; import disconnectRelation from '../utils/disconnectRelation'; -import { fromYrn, toYrn } from '../../components/utils'; import type { IStamps } from '../../interfaces/IStamps'; import type { ChefsSubmissionForm } from '../../types'; @@ -33,27 +32,36 @@ export default { return { submissionId: input.submissionId, confirmationId: input.confirmationId, - contactEmail: input.contactEmail, + submittedAt: new Date(input.submittedAt), + submittedBy: input.submittedBy, + locationPIDs: input.locationPIDs, + contactName: input.contactName, contactPhoneNumber: input.contactPhoneNumber, - contactFirstName: input.contactFirstName, - contactLastName: input.contactLastName, - intakeStatus: input.intakeStatus, + contactEmail: input.contactEmail, projectName: input.projectName, - queuePriority: input.queuePriority, singleFamilyUnits: input.singleFamilyUnits, streetAddress: input.streetAddress, - atsClientNumber: input.atsClientNumber, - addedToATS: fromYrn(input.addedToATS), - financiallySupported: fromYrn(input.financiallySupported), - applicationStatus: input.applicationStatus, + latitude: input.latitude, + longitude: input.longitude, + queuePriority: input.queuePriority, relatedPermits: input.relatedPermits, - updatedAai: fromYrn(input.updatedAai), + astNotes: input.astNotes, + astUpdated: input.astUpdated, + addedToATS: input.addedToATS, + atsClientNumber: input.atsClientNumber, + ltsaCompleted: input.ltsaCompleted, + naturalDisaster: input.naturalDisaster, + financiallySupported: input.financiallySupported, + financiallySupportedBC: input.financiallySupportedBC, + financiallySupportedIndigenous: input.financiallySupportedIndigenous, + financiallySupportedNonProfit: input.financiallySupportedNonProfit, + financiallySupportedHousingCoop: input.financiallySupportedHousingCoop, waitingOn: input.waitingOn, - submittedAt: new Date(input.submittedAt), - submittedBy: input.submittedBy, bringForwardDate: input.bringForwardDate ? new Date(input.bringForwardDate) : null, notes: input.notes, - user: input.user?.userId ? { connect: { userId: input.user.userId } } : disconnectRelation + user: input.user?.userId ? { connect: { userId: input.user.userId } } : disconnectRelation, + intakeStatus: input.intakeStatus, + applicationStatus: input.applicationStatus }; }, @@ -61,29 +69,38 @@ export default { if (!input) return null; return { - submissionId: input.submissionId as string, - confirmationId: input.confirmationId as string, - contactEmail: input.contactEmail, + submissionId: input.submissionId, + confirmationId: input.confirmationId, + submittedAt: input.submittedAt?.toISOString() as string, + submittedBy: input.submittedBy as string, + locationPIDs: input.locationPIDs, + contactName: input.contactName, contactPhoneNumber: input.contactPhoneNumber, - contactFirstName: input.contactFirstName, - contactLastName: input.contactLastName, - intakeStatus: input.intakeStatus, + contactEmail: input.contactEmail, projectName: input.projectName, - queuePriority: input.queuePriority, singleFamilyUnits: input.singleFamilyUnits, streetAddress: input.streetAddress, - atsClientNumber: input.atsClientNumber, - addedToATS: toYrn(input.addedToATS as boolean | null), - financiallySupported: toYrn(input.financiallySupported as boolean | null), - applicationStatus: input.applicationStatus, + latitude: input.latitude, + longitude: input.longitude, + queuePriority: input.queuePriority, relatedPermits: input.relatedPermits, - updatedAai: toYrn(input.updatedAai as boolean | null), + astNotes: input.astNotes, + astUpdated: input.astUpdated, + addedToATS: input.addedToATS, + atsClientNumber: input.atsClientNumber, + ltsaCompleted: input.ltsaCompleted, + naturalDisaster: input.naturalDisaster, + financiallySupported: input.financiallySupported, + financiallySupportedBC: input.financiallySupportedBC, + financiallySupportedIndigenous: input.financiallySupportedIndigenous, + financiallySupportedNonProfit: input.financiallySupportedNonProfit, + financiallySupportedHousingCoop: input.financiallySupportedHousingCoop, waitingOn: input.waitingOn, - submittedAt: input.submittedAt?.toISOString() as string, - submittedBy: input.submittedBy as string, bringForwardDate: input.bringForwardDate?.toISOString() ?? null, notes: input.notes, - user: user.fromDBModel(input.user) + user: user.fromDBModel(input.user), + intakeStatus: input.intakeStatus, + applicationStatus: input.applicationStatus }; } }; diff --git a/app/src/db/prisma/schema.prisma b/app/src/db/prisma/schema.prisma index 738b3ddb..f2100484 100644 --- a/app/src/db/prisma/schema.prisma +++ b/app/src/db/prisma/schema.prisma @@ -30,34 +30,43 @@ model knex_migrations_lock { } model submission { - submissionId String @id @db.Uuid - assignedToUserId String? @db.Uuid - confirmationId String - contactEmail String? - contactPhoneNumber String? - contactFirstName String? - contactLastName String? - intakeStatus String? - projectName String? - queuePriority Int? - singleFamilyUnits String? - streetAddress String? - atsClientNumber String? - addedToATS Boolean? - financiallySupported Boolean? - applicationStatus String? - relatedPermits String? - updatedAai Boolean? - waitingOn String? - submittedAt DateTime @db.Timestamptz(6) - submittedBy String - bringForwardDate DateTime? @db.Timestamptz(6) - notes String? - createdBy String? @default("00000000-0000-0000-0000-000000000000") - createdAt DateTime? @default(now()) @db.Timestamptz(6) - updatedBy String? - updatedAt DateTime? @db.Timestamptz(6) - user user? @relation(fields: [assignedToUserId], references: [userId], onDelete: Cascade, map: "submission_assignedtouserid_foreign") + submissionId String @id @db.Uuid + assignedToUserId String? @db.Uuid + confirmationId String + submittedAt DateTime @db.Timestamptz(6) + submittedBy String + locationPIDs String? + contactName String? + contactPhoneNumber String? + contactEmail String? + projectName String? + singleFamilyUnits String? + streetAddress String? + latitude Int? + longitude Int? + queuePriority Int? + relatedPermits String? + astNotes String? + astUpdated Boolean? + addedToATS Boolean? + atsClientNumber String? + ltsaCompleted Boolean? + naturalDisaster Boolean? + financiallySupported Boolean? + financiallySupportedBC Boolean? + financiallySupportedIndigenous Boolean? + financiallySupportedNonProfit Boolean? + financiallySupportedHousingCoop Boolean? + waitingOn String? + bringForwardDate DateTime? @db.Timestamptz(6) + notes String? + intakeStatus String? + applicationStatus String? + createdBy String? @default("00000000-0000-0000-0000-000000000000") + createdAt DateTime? @default(now()) @db.Timestamptz(6) + updatedBy String? + updatedAt DateTime? @db.Timestamptz(6) + user user? @relation(fields: [assignedToUserId], references: [userId], onDelete: Cascade, map: "submission_assignedtouserid_foreign") } model user { diff --git a/app/src/services/chefs.ts b/app/src/services/chefs.ts index 17358613..140fa33a 100644 --- a/app/src/services/chefs.ts +++ b/app/src/services/chefs.ts @@ -50,19 +50,20 @@ const service = { const response = (await chefsAxios(formId).get(`submissions/${submissionId}`)).data; const status = (await chefsAxios(formId).get(`submissions/${submissionId}/status`)).data; + const submission = response.submission.submission.data; + await prisma.submission.create({ data: { submissionId: response.submission.id, confirmationId: response.submission.confirmationId, - contactEmail: response.submission.submission.data.contactEmail, - contactPhoneNumber: response.submission.submission.data.contactPhoneNumber, - contactFirstName: response.submission.submission.data.contactFirstName, - contactLastName: response.submission.submission.data.contactLastName, + contactEmail: submission.contactEmail, + contactPhoneNumber: submission.contactPhoneNumber, + contactName: `${submission.contactFirstName} ${submission.contactLastName}`, intakeStatus: status[0].code, - projectName: response.submission.submission.data.projectName, - queuePriority: parseInt(response.submission.submission.data.queuePriority), - singleFamilyUnits: response.submission.submission.data.singleFamilyUnits, - streetAddress: response.submission.submission.data.streetAddress, + projectName: submission.projectName, + queuePriority: parseInt(submission.queuePriority), + singleFamilyUnits: submission.singleFamilyUnits, + streetAddress: submission.streetAddress, submittedAt: response.submission.createdAt, submittedBy: response.submission.createdBy } diff --git a/app/src/types/ChefsSubmissionForm.ts b/app/src/types/ChefsSubmissionForm.ts index f04f747d..2915c7fa 100644 --- a/app/src/types/ChefsSubmissionForm.ts +++ b/app/src/types/ChefsSubmissionForm.ts @@ -1,29 +1,37 @@ import { User } from './User'; -import { YRN } from './YRN'; import { IStamps } from '../interfaces/IStamps'; export type ChefsSubmissionForm = { - submissionId: string; // Primary Key + submissionId: string; confirmationId: string; - contactEmail: string | null; + submittedAt: string; + submittedBy: string; + locationPIDs: string | null; + contactName: string | null; contactPhoneNumber: string | null; - contactFirstName: string | null; - contactLastName: string | null; - intakeStatus: string | null; + contactEmail: string | null; projectName: string | null; - queuePriority: number | null; singleFamilyUnits: string | null; streetAddress: string | null; - atsClientNumber: string | null; - addedToATS: YRN; - financiallySupported: YRN; - applicationStatus: string | null; + latitude: number | null; + longitude: number | null; + queuePriority: number | null; relatedPermits: string | null; - updatedAai: YRN; + astNotes: string | null; + astUpdated: boolean | null; + addedToATS: boolean | null; + atsClientNumber: string | null; + ltsaCompleted: boolean | null; + naturalDisaster: boolean | null; + financiallySupported: boolean | null; + financiallySupportedBC: boolean | null; + financiallySupportedIndigenous: boolean | null; + financiallySupportedNonProfit: boolean | null; + financiallySupportedHousingCoop: boolean | null; waitingOn: string | null; - submittedAt: string; - submittedBy: string; bringForwardDate: string | null; notes: string | null; - user: User | null; + user: User | null; // assigned to + intakeStatus: string | null; + applicationStatus: string | null; } & Partial; diff --git a/frontend/src/assets/main.scss b/frontend/src/assets/main.scss index a2a12c1f..24bf1c05 100644 --- a/frontend/src/assets/main.scss +++ b/frontend/src/assets/main.scss @@ -73,6 +73,10 @@ a:visited { } } +label { + color: #38598a; +} + .wrap-block { display: inline-block; overflow-wrap: break-word; diff --git a/frontend/src/components/demo/DemoButtons.vue b/frontend/src/components/demo/DemoButtons.vue deleted file mode 100644 index 764c4088..00000000 --- a/frontend/src/components/demo/DemoButtons.vue +++ /dev/null @@ -1,42 +0,0 @@ - - - diff --git a/frontend/src/components/demo/DemoDataTable.vue b/frontend/src/components/demo/DemoDataTable.vue deleted file mode 100644 index 9fb32667..00000000 --- a/frontend/src/components/demo/DemoDataTable.vue +++ /dev/null @@ -1,166 +0,0 @@ - - - - - diff --git a/frontend/src/components/demo/DemoHeadings.vue b/frontend/src/components/demo/DemoHeadings.vue deleted file mode 100644 index e76ab998..00000000 --- a/frontend/src/components/demo/DemoHeadings.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/frontend/src/components/demo/DemoModals.vue b/frontend/src/components/demo/DemoModals.vue deleted file mode 100644 index 0ea7ac10..00000000 --- a/frontend/src/components/demo/DemoModals.vue +++ /dev/null @@ -1,123 +0,0 @@ - - - diff --git a/frontend/src/components/demo/DemoToasts.vue b/frontend/src/components/demo/DemoToasts.vue deleted file mode 100644 index e618e3ab..00000000 --- a/frontend/src/components/demo/DemoToasts.vue +++ /dev/null @@ -1,40 +0,0 @@ - - - diff --git a/frontend/src/components/demo/index.ts b/frontend/src/components/demo/index.ts deleted file mode 100644 index c445fed0..00000000 --- a/frontend/src/components/demo/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as DemoButtons } from './DemoButtons.vue'; -export { default as DemoDataTable } from './DemoDataTable.vue'; -export { default as DemoHeadings } from './DemoHeadings.vue'; -export { default as DemoModals } from './DemoModals.vue'; -export { default as DemoToasts } from './DemoToasts.vue'; diff --git a/frontend/src/components/form/Calendar.vue b/frontend/src/components/form/Calendar.vue index e71b0251..318aa485 100644 --- a/frontend/src/components/form/Calendar.vue +++ b/frontend/src/components/form/Calendar.vue @@ -11,6 +11,7 @@ type Props = { name: string; disabled?: boolean; showTime?: boolean; + bold?: boolean; }; const props = withDefaults(defineProps(), { @@ -18,7 +19,8 @@ const props = withDefaults(defineProps(), { type: 'text', label: '', disabled: false, - showTime: false + showTime: false, + bold: true }); const { errorMessage, value } = useField(toRef(props, 'name')); @@ -26,12 +28,18 @@ const { errorMessage, value } = useField(toRef(props, 'name')); diff --git a/frontend/src/components/form/Checkbox.vue b/frontend/src/components/form/Checkbox.vue new file mode 100644 index 00000000..1f78a83c --- /dev/null +++ b/frontend/src/components/form/Checkbox.vue @@ -0,0 +1,51 @@ + + + diff --git a/frontend/src/components/form/Dropdown.vue b/frontend/src/components/form/Dropdown.vue index 528de09d..a971d608 100644 --- a/frontend/src/components/form/Dropdown.vue +++ b/frontend/src/components/form/Dropdown.vue @@ -11,7 +11,8 @@ type Props = { name: string; placeholder?: string; disabled?: boolean; - options: Array; + options: Array; + bold?: boolean; }; const props = withDefaults(defineProps(), { @@ -19,7 +20,8 @@ const props = withDefaults(defineProps(), { type: 'text', label: '', placeholder: '', - disabled: false + disabled: false, + bold: true }); const { errorMessage, value } = useField(toRef(props, 'name')); @@ -27,17 +29,25 @@ const { errorMessage, value } = useField(toRef(props, 'name')); diff --git a/frontend/src/components/form/EditableDropdown.vue b/frontend/src/components/form/EditableDropdown.vue index d82976eb..cf69f877 100644 --- a/frontend/src/components/form/EditableDropdown.vue +++ b/frontend/src/components/form/EditableDropdown.vue @@ -14,8 +14,9 @@ type Props = { name: string; placeholder?: string; disabled?: boolean; - options: Array; + options: Array; getOptionLabel: Function; + bold?: boolean; }; const props = withDefaults(defineProps(), { @@ -23,7 +24,8 @@ const props = withDefaults(defineProps(), { type: 'text', label: '', placeholder: '', - disabled: false + disabled: false, + bold: true }); // Emits @@ -34,14 +36,20 @@ const { errorMessage, value } = useField(toRef(props, 'name')); diff --git a/frontend/src/components/form/InputMask.vue b/frontend/src/components/form/InputMask.vue new file mode 100644 index 00000000..3f635b23 --- /dev/null +++ b/frontend/src/components/form/InputMask.vue @@ -0,0 +1,53 @@ + + + diff --git a/frontend/src/components/form/InputNumber.vue b/frontend/src/components/form/InputNumber.vue new file mode 100644 index 00000000..027b2bd5 --- /dev/null +++ b/frontend/src/components/form/InputNumber.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend/src/components/form/TextInput.vue b/frontend/src/components/form/InputText.vue similarity index 73% rename from frontend/src/components/form/TextInput.vue rename to frontend/src/components/form/InputText.vue index 56d33582..e9e893d2 100644 --- a/frontend/src/components/form/TextInput.vue +++ b/frontend/src/components/form/InputText.vue @@ -11,6 +11,7 @@ type Props = { name: string; placeholder?: string; disabled?: boolean; + bold?: boolean; }; const props = withDefaults(defineProps(), { @@ -18,7 +19,8 @@ const props = withDefaults(defineProps(), { type: 'text', label: '', placeholder: '', - disabled: false + disabled: false, + bold: true }); const { errorMessage, value } = useField(toRef(props, 'name')); @@ -26,16 +28,24 @@ const { errorMessage, value } = useField(toRef(props, 'name')); diff --git a/frontend/src/components/form/Password.vue b/frontend/src/components/form/Password.vue index e36cad18..0b9f4a25 100644 --- a/frontend/src/components/form/Password.vue +++ b/frontend/src/components/form/Password.vue @@ -10,13 +10,15 @@ type Props = { name: string; placeholder?: string; type?: string; + bold?: boolean; }; const props = withDefaults(defineProps(), { helptext: '', type: 'text', label: '', - placeholder: '' + placeholder: '', + bold: true }); const { errorMessage, value } = useField(toRef(props, 'name')); @@ -24,18 +26,26 @@ const { errorMessage, value } = useField(toRef(props, 'name')); diff --git a/frontend/src/components/form/TextArea.vue b/frontend/src/components/form/TextArea.vue index 00bcbfa2..4095db5b 100644 --- a/frontend/src/components/form/TextArea.vue +++ b/frontend/src/components/form/TextArea.vue @@ -11,6 +11,7 @@ type Props = { name: string; placeholder?: string; disabled?: boolean; + bold?: boolean; }; const props = withDefaults(defineProps(), { @@ -18,7 +19,8 @@ const props = withDefaults(defineProps(), { type: 'text', label: '', placeholder: '', - disabled: false + disabled: false, + bold: true }); const { errorMessage, value } = useField(toRef(props, 'name')); @@ -26,17 +28,25 @@ const { errorMessage, value } = useField(toRef(props, 'name'));