From ff2bae0b7e775638b4725cc637a6022d664496f0 Mon Sep 17 00:00:00 2001 From: Kyle Morel Date: Mon, 8 Jan 2024 18:44:01 -0800 Subject: [PATCH 1/5] FileUpload and Carousel components --- frontend/src/components/file/FileUpload.vue | 79 +++++++++++++++++ frontend/src/lib/primevue/index.ts | 4 + frontend/src/store/fileStore.ts | 44 +++++++++ frontend/src/store/index.ts | 1 + frontend/src/views/SubmissionView.vue | 98 +++++++++++++++++---- 5 files changed, 209 insertions(+), 17 deletions(-) create mode 100644 frontend/src/components/file/FileUpload.vue create mode 100644 frontend/src/store/fileStore.ts diff --git a/frontend/src/components/file/FileUpload.vue b/frontend/src/components/file/FileUpload.vue new file mode 100644 index 00000000..17fb48f2 --- /dev/null +++ b/frontend/src/components/file/FileUpload.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/frontend/src/lib/primevue/index.ts b/frontend/src/lib/primevue/index.ts index 9076b762..885be73a 100644 --- a/frontend/src/lib/primevue/index.ts +++ b/frontend/src/lib/primevue/index.ts @@ -2,6 +2,7 @@ export { FilterMatchMode } from 'primevue/api'; export { default as Button } from 'primevue/button'; export { default as Calendar } from 'primevue/calendar'; +export { default as Carousel } from 'primevue/carousel'; export { default as Checkbox } from 'primevue/checkbox'; export { default as Column } from 'primevue/column'; export { default as ConfirmDialog } from 'primevue/confirmdialog'; @@ -9,6 +10,7 @@ export { default as DataTable } from 'primevue/datatable'; export { default as Dialog } from 'primevue/dialog'; export { default as Divider } from 'primevue/divider'; export { default as Dropdown } from 'primevue/dropdown'; +export { default as FileUpload } from 'primevue/fileupload'; export { default as InputMask } from 'primevue/inputmask'; export { default as InputNumber } from 'primevue/inputnumber'; export { default as InputSwitch } from 'primevue/inputswitch'; @@ -17,6 +19,8 @@ export { default as Message } from 'primevue/message'; export { default as Password } from 'primevue/password'; export { default as ProgressBar } from 'primevue/progressbar'; export { default as ProgressSpinner } from 'primevue/progressspinner'; +export { default as TabView } from 'primevue/tabview'; +export { default as TabPanel } from 'primevue/tabpanel'; export { default as Textarea } from 'primevue/textarea'; export { default as Toast } from 'primevue/toast'; export { default as Toolbar } from 'primevue/toolbar'; diff --git a/frontend/src/store/fileStore.ts b/frontend/src/store/fileStore.ts new file mode 100644 index 00000000..60382696 --- /dev/null +++ b/frontend/src/store/fileStore.ts @@ -0,0 +1,44 @@ +import { defineStore } from 'pinia'; +import { computed, ref } from 'vue'; + +import type { Ref } from 'vue'; + +export type FileStoreState = { + files: Ref>; +}; + +export const useFileStore = defineStore('file', () => { + // State + const state: FileStoreState = { + files: ref([]) + }; + + // Getters + const getters = { + getFiles: computed(() => state.files.value) + }; + + // Actions + function createFile(file: File) { + let newFileName = file.name; + const count = state.files.value.filter((x: File) => x.name.includes(file.name)).length; + if (count > 0) { + newFileName = file.name + ` (${count + 1})`; + } + const newFile = new File([file], newFileName, { type: file.type }); + state.files.value.push(newFile); + } + + return { + // State + ...state, + + // Getters + ...getters, + + // Actions + createFile + }; +}); + +export default useFileStore; diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts index 414fd236..0fe9992c 100644 --- a/frontend/src/store/index.ts +++ b/frontend/src/store/index.ts @@ -1,3 +1,4 @@ export { default as useAppStore } from './appStore'; export { default as useAuthStore } from './authStore'; export { default as useConfigStore } from './configStore'; +export { default as useFileStore } from './fileStore'; diff --git a/frontend/src/views/SubmissionView.vue b/frontend/src/views/SubmissionView.vue index 922f8a34..7bf8b6c3 100644 --- a/frontend/src/views/SubmissionView.vue +++ b/frontend/src/views/SubmissionView.vue @@ -2,9 +2,12 @@ import { storeToRefs } from 'pinia'; import { onMounted, ref } from 'vue'; -import SubmissionForm from '../components/submission/SubmissionForm.vue'; -import { Button, useToast } from '@/lib/primevue'; -import { chefsService, documentService } from '@/services'; +import FileUpload from '@/components/file/FileUpload.vue'; +import SubmissionForm from '@/components/submission/SubmissionForm.vue'; +import { Button, Carousel, TabPanel, TabView, useToast } from '@/lib/primevue'; +import { chefsService } from '@/services'; +import { useFileStore } from '@/store'; +import { formatDateLong } from '@/utils/formatters'; import { useConfigStore } from '@/store'; import type { Ref } from 'vue'; @@ -24,6 +27,8 @@ const { getConfig } = storeToRefs(useConfigStore()); const editable: Ref = ref(false); const submission: Ref = ref(undefined); +const { getFiles } = storeToRefs(useFileStore()); + // Actions const toast = useToast(); @@ -52,18 +57,77 @@ const onUpload = async (file: File) => { + + From d37a6ccaa5410f0185777677fdf8feea4d0443c3 Mon Sep 17 00:00:00 2001 From: Kyle Morel Date: Mon, 15 Jan 2024 15:11:07 -0800 Subject: [PATCH 2/5] Front end document upload integration using COMS --- app/package-lock.json | 32 +-- app/package.json | 6 +- app/src/components/utils.ts | 23 +- app/src/db/models/document.ts | 1 + app/src/services/document.ts | 7 +- app/src/types/YRN.ts | 1 - app/src/types/index.ts | 1 - frontend/package-lock.json | 268 +++++++++--------- frontend/package.json | 22 +- frontend/src/components/file/FileUpload.vue | 23 +- .../src/interfaces/{IAudit.ts => IStamps.ts} | 2 +- frontend/src/interfaces/index.ts | 2 +- frontend/src/services/documentService.ts | 22 +- frontend/src/store/fileStore.ts | 44 --- frontend/src/store/index.ts | 1 - frontend/src/types/Document.ts | 9 + frontend/src/types/User.ts | 4 +- frontend/src/types/YRN.ts | 1 - frontend/src/types/index.ts | 2 +- frontend/src/utils/utils.ts | 16 ++ frontend/src/views/SubmissionView.vue | 53 ++-- 21 files changed, 278 insertions(+), 262 deletions(-) delete mode 100644 app/src/types/YRN.ts rename frontend/src/interfaces/{IAudit.ts => IStamps.ts} (76%) delete mode 100644 frontend/src/store/fileStore.ts create mode 100644 frontend/src/types/Document.ts delete mode 100644 frontend/src/types/YRN.ts diff --git a/app/package-lock.json b/app/package-lock.json index e584e8c2..68e13efc 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -11,11 +11,11 @@ "dependencies": { "@prisma/client": "^5.7.1", "api-problem": "^9.0.2", - "axios": "^1.6.2", + "axios": "^1.6.5", "compression": "^1.7.4", - "config": "^3.3.9", + "config": "^3.3.10", "cors": "^2.8.5", - "date-fns": "^3.0.5", + "date-fns": "^3.2.0", "express": "^4.18.2", "express-winston": "^4.2.0", "helmet": "^7.1.0", @@ -2414,11 +2414,11 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3088,9 +3088,9 @@ "dev": true }, "node_modules/config": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz", - "integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.10.tgz", + "integrity": "sha512-9Kl3LpQ6zj93KaqgfIMTcpwTpgozFOqNl/Dk7mjras1BgGIOlqxWkyIGeU1my+sRuskRYwrCATgCk1RjAnRPGA==", "dependencies": { "json5": "^2.2.3" }, @@ -3208,9 +3208,9 @@ } }, "node_modules/date-fns": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.0.5.tgz", - "integrity": "sha512-Q4Tq5c5s/Zl/zbgdWf6pejn9ru7UwdIlLfvEEg1hVsQNQ7LKt76qIduagIT9OPK7+JCv1mAKherdU6bOqGYDnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.2.0.tgz", + "integrity": "sha512-E4KWKavANzeuusPi0jUjpuI22SURAznGkx7eZV+4i6x2A+IZxAMcajgkvuDAU1bg40+xuhW1zRdVIIM/4khuIg==", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -6482,9 +6482,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", diff --git a/app/package.json b/app/package.json index c41e0e98..b3012fa5 100644 --- a/app/package.json +++ b/app/package.json @@ -48,11 +48,11 @@ "dependencies": { "@prisma/client": "^5.7.1", "api-problem": "^9.0.2", - "axios": "^1.6.2", + "axios": "^1.6.5", "compression": "^1.7.4", - "config": "^3.3.9", + "config": "^3.3.10", "cors": "^2.8.5", - "date-fns": "^3.0.5", + "date-fns": "^3.2.0", "express": "^4.18.2", "express-winston": "^4.2.0", "helmet": "^7.1.0", diff --git a/app/src/components/utils.ts b/app/src/components/utils.ts index 8c4fe070..4ecb5526 100644 --- a/app/src/components/utils.ts +++ b/app/src/components/utils.ts @@ -4,7 +4,7 @@ import { join } from 'path'; import { getLogger } from './log'; -import type { ChefsFormConfig, ChefsFormConfigData, YRN } from '../types'; +import type { ChefsFormConfig, ChefsFormConfigData } from '../types'; const log = getLogger(module.filename); @@ -22,16 +22,6 @@ export function addDashesToUuid(str: string): string { } else return str; } -/** - * @function fromYrn - * Converts a YRN to boolean - * @param {YRN} yrn An arbitrary YRN - * @returns {boolean | null} The converted value - */ -export function fromYrn(yrn: YRN): boolean | null { - return yrn === null ? null : yrn.toUpperCase() === 'Y'; -} - /** * @function getChefsApiKey * Search for a CHEFS form Api Key @@ -168,14 +158,3 @@ export function redactSecrets(data: { [key: string]: unknown }, fields: Array { - await prisma.document.create({ + const response = await prisma.document.create({ data: { documentId: documentId, submissionId: submissionId, @@ -27,6 +27,8 @@ const service = { filesize: filesize } }); + + return document.fromPrismaModel(response); }, /** @@ -39,6 +41,9 @@ const service = { const response = await prisma.document.findMany({ where: { submissionId: submissionId + }, + orderBy: { + createdAt: 'asc' } }); diff --git a/app/src/types/YRN.ts b/app/src/types/YRN.ts deleted file mode 100644 index 1ba0a1f1..00000000 --- a/app/src/types/YRN.ts +++ /dev/null @@ -1 +0,0 @@ -export type YRN = 'Y' | 'N' | null; diff --git a/app/src/types/index.ts b/app/src/types/index.ts index 3fdb273f..6533eee4 100644 --- a/app/src/types/index.ts +++ b/app/src/types/index.ts @@ -7,4 +7,3 @@ export type { IdentityProvider } from './IdentityProvider'; export type { SubmissionSearchParameters } from './SubmissionSearchParameters'; export type { User } from './User'; export type { UserSearchParameters } from './UserSearchParameters'; -export type { YRN } from './YRN'; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6c5214d9..9c1ee330 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,18 +13,19 @@ "@fortawesome/fontawesome-svg-core": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/vue-fontawesome": "^3.0.5", - "axios": "^1.6.2", - "date-fns": "^3.0.5", + "axios": "^1.6.5", + "date-fns": "^3.2.0", "filesize": "^10.1.0", "oidc-client-ts": "^2.4.0", "pinia": "^2.1.7", "pinia-plugin-persistedstate": "^3.2.1", "primeflex": "^3.3.1", "primeicons": "^6.0.1", - "primevue": "^3.44.0", + "primevue": "^3.46.0", "qrcode.vue": "^3.4.1", - "vee-validate": "^4.12.3", - "vue": "^3.3.13", + "uuid": "^9.0.1", + "vee-validate": "^4.12.4", + "vue": "^3.4.14", "vue-router": "^4.2.5", "yup": "^1.3.3" }, @@ -32,8 +33,9 @@ "@pinia/testing": "^0.1.3", "@testing-library/vue": "^8.0.1", "@tsconfig/node18": "^18.2.2", - "@types/node": "^20.9.5", - "@vitejs/plugin-vue": "^4.5.2", + "@types/node": "^20.11.3", + "@types/uuid": "^9.0.7", + "@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue-jsx": "^3.1.0", "@vitest/coverage-c8": "^0.33.0", "@vitest/coverage-istanbul": "^0.34.6", @@ -43,17 +45,17 @@ "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-vitest-globals": "^1.4.0", - "eslint-plugin-vue": "^9.19.2", + "eslint-plugin-vue": "^9.20.1", "happy-dom": "^12.10.3", "prettier": "^3.1.1", "rimraf": "^5.0.5", "sass": "^1.69.5", "ts-node": "^10.9.2", "typescript": "^5.3.3", - "vite": "^5.0.10", + "vite": "^5.0.11", "vitest": "^0.34.6", "volar-service-eslint": "^0.0.17", - "vue-tsc": "^1.8.26" + "vue-tsc": "^1.8.27" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -1700,9 +1702,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.9.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.5.tgz", - "integrity": "sha512-Uq2xbNq0chGg+/WQEU0LJTSs/1nKxz6u1iemLcGomkSnKokbW1fbLqc3HOqCf2JP7KjlL4QkS7oZZTrOQHQYgQ==", + "version": "20.11.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.3.tgz", + "integrity": "sha512-nrlmbvGPNGaj84IJZXMPhQuCMEVTT/hXZMJJG/aIqVL9fKxqk814sGGtJA4GI6hpJSLQjpi6cn0Qx9eOf9SDVg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1713,6 +1715,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/uuid": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", + "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.9.0", "dev": true, @@ -1990,15 +1998,15 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-vue": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.5.2.tgz", - "integrity": "sha512-UGR3DlzLi/SaVBPX0cnSyE37vqxU3O6chn8l0HJNzQzDia6/Au2A4xKv+iIJW8w2daf80G7TYHhi1pAUjdZ0bQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.3.tgz", + "integrity": "sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==", "dev": true, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "vite": "^4.0.0 || ^5.0.0", + "vite": "^5.0.0", "vue": "^3.2.25" } }, @@ -2270,49 +2278,49 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.13.tgz", - "integrity": "sha512-bwi9HShGu7uaZLOErZgsH2+ojsEdsjerbf2cMXPwmvcgZfVPZ2BVZzCVnwZBxTAYd6Mzbmf6izcUNDkWnBBQ6A==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.14.tgz", + "integrity": "sha512-ro4Zzl/MPdWs7XwxT7omHRxAjMbDFRZEEjD+2m3NBf8YzAe3HuoSEZosXQo+m1GQ1G3LQ1LdmNh1RKTYe+ssEg==", "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/shared": "3.3.13", + "@babel/parser": "^7.23.6", + "@vue/shared": "3.4.14", + "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.13.tgz", - "integrity": "sha512-EYRDpbLadGtNL0Gph+HoKiYqXLqZ0xSSpR5Dvnu/Ep7ggaCbjRDIus1MMxTS2Qm0koXED4xSlvTZaTnI8cYAsw==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.14.tgz", + "integrity": "sha512-nOZTY+veWNa0DKAceNWxorAbWm0INHdQq7cejFaWM1WYnoNSJbSEKYtE7Ir6lR/+mo9fttZpPVI9ZFGJ1juUEQ==", "dependencies": { - "@vue/compiler-core": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/compiler-core": "3.4.14", + "@vue/shared": "3.4.14" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.13.tgz", - "integrity": "sha512-DQVmHEy/EKIgggvnGRLx21hSqnr1smUS9Aq8tfxiiot8UR0/pXKHN9k78/qQ7etyQTFj5em5nruODON7dBeumw==", - "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.13", - "@vue/compiler-dom": "3.3.13", - "@vue/compiler-ssr": "3.3.13", - "@vue/reactivity-transform": "3.3.13", - "@vue/shared": "3.3.13", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.14.tgz", + "integrity": "sha512-1vHc9Kv1jV+YBZC/RJxQJ9JCxildTI+qrhtDh6tPkR1O8S+olBUekimY0km0ZNn8nG1wjtFAe9XHij+YLR8cRQ==", + "dependencies": { + "@babel/parser": "^7.23.6", + "@vue/compiler-core": "3.4.14", + "@vue/compiler-dom": "3.4.14", + "@vue/compiler-ssr": "3.4.14", + "@vue/shared": "3.4.14", "estree-walker": "^2.0.2", "magic-string": "^0.30.5", - "postcss": "^8.4.32", + "postcss": "^8.4.33", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.13.tgz", - "integrity": "sha512-d/P3bCeUGmkJNS1QUZSAvoCIW4fkOKK3l2deE7zrp0ypJEy+En2AcypIkqvcFQOcw3F0zt2VfMvNsA9JmExTaw==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.14.tgz", + "integrity": "sha512-bXT6+oAGlFjTYVOTtFJ4l4Jab1wjsC0cfSfOe2B4Z0N2vD2zOBSQ9w694RsCfhjk+bC2DY5Gubb1rHZVii107Q==", "dependencies": { - "@vue/compiler-dom": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/compiler-dom": "3.4.14", + "@vue/shared": "3.4.14" } }, "node_modules/@vue/devtools-api": { @@ -2343,9 +2351,9 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.26", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.26.tgz", - "integrity": "sha512-9cmza/Y2YTiOnKZ0Mi9zsNn7Irw+aKirP+5LLWVSNaL3fjKJjW1cD3HGBckasY2RuVh4YycvdA9/Q6EBpVd/7Q==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", "dev": true, "dependencies": { "@volar/language-core": "~1.11.1", @@ -2392,60 +2400,48 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.13.tgz", - "integrity": "sha512-fjzCxceMahHhi4AxUBzQqqVhuA21RJ0COaWTbIBl1PruGW1CeY97louZzLi4smpYx+CHfFPPU/CS8NybbGvPKQ==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.14.tgz", + "integrity": "sha512-xRYwze5Q4tK7tT2J4uy4XLhK/AIXdU5EBUu9PLnIHcOKXO0uyXpNNMzlQKuq7B+zwtq6K2wuUL39pHA6ZQzObw==", "dependencies": { - "@vue/shared": "3.3.13" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.13.tgz", - "integrity": "sha512-oWnydGH0bBauhXvh5KXUy61xr9gKaMbtsMHk40IK9M4gMuKPJ342tKFarY0eQ6jef8906m35q37wwA8DMZOm5Q==", - "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.13", - "@vue/shared": "3.3.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5" + "@vue/shared": "3.4.14" } }, "node_modules/@vue/runtime-core": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.13.tgz", - "integrity": "sha512-1TzA5TvGuh2zUwMJgdfvrBABWZ7y8kBwBhm7BXk8rvdx2SsgcGfz2ruv2GzuGZNvL1aKnK8CQMV/jFOrxNQUMA==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.14.tgz", + "integrity": "sha512-qu+NMkfujCoZL6cfqK5NOfxgXJROSlP2ZPs4CTcVR+mLrwl4TtycF5Tgo0QupkdBL+2kigc6EsJlTcuuZC1NaQ==", "dependencies": { - "@vue/reactivity": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/reactivity": "3.4.14", + "@vue/shared": "3.4.14" } }, "node_modules/@vue/runtime-dom": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.13.tgz", - "integrity": "sha512-JJkpE8R/hJKXqVTgUoODwS5wqKtOsmJPEqmp90PDVGygtJ4C0PtOkcEYXwhiVEmef6xeXcIlrT3Yo5aQ4qkHhQ==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.14.tgz", + "integrity": "sha512-B85XmcR4E7XsirEHVqhmy4HPbRT9WLFWV9Uhie3OapV9m1MEN9+Er6hmUIE6d8/l2sUygpK9RstFM2bmHEUigA==", "dependencies": { - "@vue/runtime-core": "3.3.13", - "@vue/shared": "3.3.13", + "@vue/runtime-core": "3.4.14", + "@vue/shared": "3.4.14", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.13.tgz", - "integrity": "sha512-vSnN+nuf6iSqTL3Qgx/9A+BT+0Zf/VJOgF5uMZrKjYPs38GMYyAU1coDyBNHauehXDaP+zl73VhwWv0vBRBHcg==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.14.tgz", + "integrity": "sha512-pwSKXQfYdJBTpvWHGEYI+akDE18TXAiLcGn+Q/2Fj8wQSHWztoo7PSvfMNqu6NDhp309QXXbPFEGCU5p85HqkA==", "dependencies": { - "@vue/compiler-ssr": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/compiler-ssr": "3.4.14", + "@vue/shared": "3.4.14" }, "peerDependencies": { - "vue": "3.3.13" + "vue": "3.4.14" } }, "node_modules/@vue/shared": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.13.tgz", - "integrity": "sha512-/zYUwiHD8j7gKx2argXEMCUXVST6q/21DFU0sTfNX0URJroCe3b1UF6vLJ3lQDfLNIiiRl2ONp7Nh5UVWS6QnA==" + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.14.tgz", + "integrity": "sha512-nmi3BtLpvqXAWoRZ6HQ+pFJOHBU4UnH3vD3opgmwXac7vhaHKA9nj1VeGjMggdB9eLtW83eHyPCmOU1qzdsC7Q==" }, "node_modules/@vue/test-utils": { "version": "2.4.3", @@ -2623,11 +2619,11 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -3019,9 +3015,9 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/date-fns": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.0.5.tgz", - "integrity": "sha512-Q4Tq5c5s/Zl/zbgdWf6pejn9ru7UwdIlLfvEEg1hVsQNQ7LKt76qIduagIT9OPK7+JCv1mAKherdU6bOqGYDnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.2.0.tgz", + "integrity": "sha512-E4KWKavANzeuusPi0jUjpuI22SURAznGkx7eZV+4i6x2A+IZxAMcajgkvuDAU1bg40+xuhW1zRdVIIM/4khuIg==", "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -3267,7 +3263,6 @@ }, "node_modules/entities": { "version": "4.5.0", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -3425,9 +3420,9 @@ "license": "MIT" }, "node_modules/eslint-plugin-vue": { - "version": "9.19.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz", - "integrity": "sha512-CPDqTOG2K4Ni2o4J5wixkLVNwgctKXFu6oBpVJlpNq7f38lh9I80pRTouZSJ2MAebPJlINU/KTFSXyQfBUlymA==", + "version": "9.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.20.1.tgz", + "integrity": "sha512-GyCs8K3lkEvoyC1VV97GJhP1SvqsKCiWGHnbn0gVUYiUhaH2+nB+Dv1uekv1THFMPbBfYxukrzQdltw950k+LQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -3435,7 +3430,7 @@ "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.13", "semver": "^7.5.4", - "vue-eslint-parser": "^9.3.1", + "vue-eslint-parser": "^9.4.0", "xml-name-validator": "^4.0.0" }, "engines": { @@ -3648,7 +3643,8 @@ }, "node_modules/filesize": { "version": "10.1.0", - "license": "BSD-3-Clause", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.0.tgz", + "integrity": "sha512-GTLKYyBSDz3nPhlLVPjPWZCnhkd9TrrRArNcy8Z+J2cqScB7h2McAzR6NBX6nYOoWafql0roY8hrocxnZBv9CQ==", "engines": { "node": ">= 10.4.0" } @@ -3731,14 +3727,15 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.15.3", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], - "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5196,9 +5193,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "funding": [ { "type": "opencollective", @@ -5290,9 +5287,9 @@ "license": "MIT" }, "node_modules/primevue": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/primevue/-/primevue-3.44.0.tgz", - "integrity": "sha512-BqSg6rKP0vq7WRHhLlVt4BD4rQZbVVXjgSfOAcebv3mO4wJZcJbgC04mxAI9fl26PhmPy1jLOuCtNOBWo7IekA==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/primevue/-/primevue-3.46.0.tgz", + "integrity": "sha512-WGprXj9HA+j6gLLDaSxcRRSChIF99ld5fg1D3hYFA7hNiEuON1aqe83gf52vUSw8yjVMtFQ3CMPQSTYhooNwIg==", "peerDependencies": { "vue": "^3.0.0" } @@ -5950,6 +5947,18 @@ "dev": true, "license": "MIT" }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "dev": true, @@ -5969,9 +5978,9 @@ } }, "node_modules/vee-validate": { - "version": "4.12.3", - "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.12.3.tgz", - "integrity": "sha512-+ux21pFm2beGK21Q8LFDJdYqCu/7yd0HDIGolNvr7GjjlBTrK0JXm2y+h01jssyIlT1/+sSTNwAEqlSs0Nz0QA==", + "version": "4.12.4", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.12.4.tgz", + "integrity": "sha512-rqSjMdl0l/RiGKywKhkXttUKwDlQOoxTxe31uMQiMlwK4Hbtlvr3OcQvpREp/qPTARxNKudKWCUVW/mfzuxUVQ==", "dependencies": { "@vue/devtools-api": "^6.5.1", "type-fest": "^4.8.3" @@ -5981,9 +5990,9 @@ } }, "node_modules/vite": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.10.tgz", - "integrity": "sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.11.tgz", + "integrity": "sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==", "dev": true, "dependencies": { "esbuild": "^0.19.3", @@ -6151,15 +6160,15 @@ } }, "node_modules/vue": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.13.tgz", - "integrity": "sha512-LDnUpQvDgsfc0u/YgtAgTMXJlJQqjkxW1PVcOnJA5cshPleULDjHi7U45pl2VJYazSSvLH8UKcid/kzH8I0a0Q==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.14.tgz", + "integrity": "sha512-Rop5Al/ZcBbBz+KjPZaZDgHDX0kUP4duEzDbm+1o91uxYUNmJrZSBuegsNIJvUGy+epLevNRNhLjm08VKTgGyw==", "dependencies": { - "@vue/compiler-dom": "3.3.13", - "@vue/compiler-sfc": "3.3.13", - "@vue/runtime-dom": "3.3.13", - "@vue/server-renderer": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/compiler-dom": "3.4.14", + "@vue/compiler-sfc": "3.4.14", + "@vue/runtime-dom": "3.4.14", + "@vue/server-renderer": "3.4.14", + "@vue/shared": "3.4.14" }, "peerDependencies": { "typescript": "*" @@ -6171,15 +6180,16 @@ } }, "node_modules/vue-component-type-helpers": { - "version": "1.8.26", - "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.26.tgz", - "integrity": "sha512-CIwb7s8cqUuPpHDk+0DY8EJ/x8tzdzqw8ycX8hhw1GnbngTgSsIceHAqrrLjmv8zXi+j5XaiqYRQMw8sKyyjkw==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-1.8.27.tgz", + "integrity": "sha512-0vOfAtI67UjeO1G6UiX5Kd76CqaQ67wrRZiOe7UAb9Jm6GzlUr/fC7CV90XfwapJRjpCMaZFhv1V0ajWRmE9Dg==", "dev": true }, "node_modules/vue-eslint-parser": { - "version": "9.3.2", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.0.tgz", + "integrity": "sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", @@ -6243,9 +6253,9 @@ } }, "node_modules/vue-template-compiler": { - "version": "2.7.15", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz", - "integrity": "sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==", + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", "dev": true, "dependencies": { "de-indent": "^1.0.2", @@ -6253,13 +6263,13 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.26", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.26.tgz", - "integrity": "sha512-jMEJ4aqU/l1hdgmeExH5h1TFoN+hbho0A2ZAhHy53/947DGm7Qj/bpB85VpECOCwV00h7JYNVnvoD2ceOorB4Q==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", "dev": true, "dependencies": { "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.26", + "@vue/language-core": "1.8.27", "semver": "^7.5.4" }, "bin": { diff --git a/frontend/package.json b/frontend/package.json index 663de456..348bdebe 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,18 +28,19 @@ "@fortawesome/fontawesome-svg-core": "^6.5.1", "@fortawesome/free-solid-svg-icons": "^6.5.1", "@fortawesome/vue-fontawesome": "^3.0.5", - "axios": "^1.6.2", - "date-fns": "^3.0.5", + "axios": "^1.6.5", + "date-fns": "^3.2.0", "filesize": "^10.1.0", "oidc-client-ts": "^2.4.0", "pinia": "^2.1.7", "pinia-plugin-persistedstate": "^3.2.1", "primeflex": "^3.3.1", "primeicons": "^6.0.1", - "primevue": "^3.44.0", + "primevue": "^3.46.0", "qrcode.vue": "^3.4.1", - "vee-validate": "^4.12.3", - "vue": "^3.3.13", + "uuid": "^9.0.1", + "vee-validate": "^4.12.4", + "vue": "^3.4.14", "vue-router": "^4.2.5", "yup": "^1.3.3" }, @@ -47,8 +48,9 @@ "@pinia/testing": "^0.1.3", "@testing-library/vue": "^8.0.1", "@tsconfig/node18": "^18.2.2", - "@types/node": "^20.9.5", - "@vitejs/plugin-vue": "^4.5.2", + "@types/node": "^20.11.3", + "@types/uuid": "^9.0.7", + "@vitejs/plugin-vue": "^5.0.3", "@vitejs/plugin-vue-jsx": "^3.1.0", "@vitest/coverage-c8": "^0.33.0", "@vitest/coverage-istanbul": "^0.34.6", @@ -58,16 +60,16 @@ "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-vitest-globals": "^1.4.0", - "eslint-plugin-vue": "^9.19.2", + "eslint-plugin-vue": "^9.20.1", "happy-dom": "^12.10.3", "prettier": "^3.1.1", "rimraf": "^5.0.5", "sass": "^1.69.5", "ts-node": "^10.9.2", "typescript": "^5.3.3", - "vite": "^5.0.10", + "vite": "^5.0.11", "vitest": "^0.34.6", "volar-service-eslint": "^0.0.17", - "vue-tsc": "^1.8.26" + "vue-tsc": "^1.8.27" } } diff --git a/frontend/src/components/file/FileUpload.vue b/frontend/src/components/file/FileUpload.vue index 17fb48f2..e56bad27 100644 --- a/frontend/src/components/file/FileUpload.vue +++ b/frontend/src/components/file/FileUpload.vue @@ -1,14 +1,27 @@ diff --git a/frontend/src/interfaces/IAudit.ts b/frontend/src/interfaces/IStamps.ts similarity index 76% rename from frontend/src/interfaces/IAudit.ts rename to frontend/src/interfaces/IStamps.ts index c46da846..56e5b8f3 100644 --- a/frontend/src/interfaces/IAudit.ts +++ b/frontend/src/interfaces/IStamps.ts @@ -1,4 +1,4 @@ -export interface IAudit { +export interface IStamps { createdBy?: string; createdAt?: string; updatedBy?: string; diff --git a/frontend/src/interfaces/index.ts b/frontend/src/interfaces/index.ts index 323b44be..639e771b 100644 --- a/frontend/src/interfaces/index.ts +++ b/frontend/src/interfaces/index.ts @@ -1,2 +1,2 @@ -export type { IAudit } from './IAudit'; +export type { IStamps } from './IStamps'; export type { IInputEvent } from './IInputEvent'; diff --git a/frontend/src/services/documentService.ts b/frontend/src/services/documentService.ts index 9db46de7..1df290fd 100644 --- a/frontend/src/services/documentService.ts +++ b/frontend/src/services/documentService.ts @@ -1,5 +1,8 @@ +import { v4 } from 'uuid'; + import comsService from './comsService'; import { appAxios } from './interceptors'; +import { getFilenameAndExtension } from '@/utils/utils'; const PATH = '/document'; @@ -8,16 +11,27 @@ export default { * @function createDocument * @returns {Promise} An axios response */ - async createDocument(file: File, submissionId: string, bucketId: string) { + async createDocument(document: File, submissionId: string, bucketId: string) { let comsResponse; try { + // Add a unique hash to the end of the filename + const hash = v4(); + const fileAndExt = getFilenameAndExtension(document.name); + let newDocumentName = `${fileAndExt.filename}_${hash.substring(0, 8)}`; + if (fileAndExt.extension) { + newDocumentName = `${newDocumentName}.${fileAndExt.extension}`; + } + const newDocument = new File([document], newDocumentName, { type: document.type }); + + // Create COMS object comsResponse = await comsService.createObject( - file, + newDocument, {}, { bucketId }, - { timeout: 0 } // Infinite timeout for big files upload to avoid timeout error + { timeout: 0 } // Infinite timeout for big documents upload to avoid timeout error ); + // Create document link return appAxios().put(PATH, { submissionId: submissionId, documentId: comsResponse.data.id, @@ -26,7 +40,7 @@ export default { length: comsResponse.data.length }); } catch (e) { - // TODO: Delete object if Prisma write fails + // TODO: Delete COMS object if Prisma write fails } }, diff --git a/frontend/src/store/fileStore.ts b/frontend/src/store/fileStore.ts deleted file mode 100644 index 60382696..00000000 --- a/frontend/src/store/fileStore.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { defineStore } from 'pinia'; -import { computed, ref } from 'vue'; - -import type { Ref } from 'vue'; - -export type FileStoreState = { - files: Ref>; -}; - -export const useFileStore = defineStore('file', () => { - // State - const state: FileStoreState = { - files: ref([]) - }; - - // Getters - const getters = { - getFiles: computed(() => state.files.value) - }; - - // Actions - function createFile(file: File) { - let newFileName = file.name; - const count = state.files.value.filter((x: File) => x.name.includes(file.name)).length; - if (count > 0) { - newFileName = file.name + ` (${count + 1})`; - } - const newFile = new File([file], newFileName, { type: file.type }); - state.files.value.push(newFile); - } - - return { - // State - ...state, - - // Getters - ...getters, - - // Actions - createFile - }; -}); - -export default useFileStore; diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts index 0fe9992c..414fd236 100644 --- a/frontend/src/store/index.ts +++ b/frontend/src/store/index.ts @@ -1,4 +1,3 @@ export { default as useAppStore } from './appStore'; export { default as useAuthStore } from './authStore'; export { default as useConfigStore } from './configStore'; -export { default as useFileStore } from './fileStore'; diff --git a/frontend/src/types/Document.ts b/frontend/src/types/Document.ts new file mode 100644 index 00000000..2a2d2bad --- /dev/null +++ b/frontend/src/types/Document.ts @@ -0,0 +1,9 @@ +import type { IStamps } from '@/interfaces'; + +export type Document = { + documentId: string; // Primary Key + submissionId: string; + filename: string; + mimeType: string; + filesize: number; +} & Partial; diff --git a/frontend/src/types/User.ts b/frontend/src/types/User.ts index e43034e7..c57fc372 100644 --- a/frontend/src/types/User.ts +++ b/frontend/src/types/User.ts @@ -1,4 +1,4 @@ -import type { IAudit } from '@/interfaces'; +import type { IStamps } from '@/interfaces'; export type User = { active: boolean; @@ -11,4 +11,4 @@ export type User = { userId: string; username: string; elevatedRights: boolean; -} & IAudit; +} & IStamps; diff --git a/frontend/src/types/YRN.ts b/frontend/src/types/YRN.ts deleted file mode 100644 index 1ba0a1f1..00000000 --- a/frontend/src/types/YRN.ts +++ /dev/null @@ -1 +0,0 @@ -export type YRN = 'Y' | 'N' | null; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 4a77d63f..214c6f28 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -1,5 +1,5 @@ export type { ChefsSubmissionForm } from './ChefsSubmissionForm'; +export type { Document } from './Document'; export type { IdentityProvider } from './IdentityProvider'; export type { User } from './User'; export type { UserSearchParameters } from './UserSearchParameters'; -export type { YRN } from './YRN'; diff --git a/frontend/src/utils/utils.ts b/frontend/src/utils/utils.ts index 6509d96e..d2018e58 100644 --- a/frontend/src/utils/utils.ts +++ b/frontend/src/utils/utils.ts @@ -20,6 +20,22 @@ export function isDebugMode(): boolean { return import.meta.env.MODE.toUpperCase() === 'DEBUG'; } +/** + * @function getFilenameAndExtension + * Separates a full filename into name and extension parts + * @returns {filename: string, extension: string} An object containing filename and extension + */ +export function getFilenameAndExtension(filename: string): { filename: string; extension: string | undefined } { + const extensionIdx = filename.lastIndexOf('.'); + if (extensionIdx > 0) { + const name = filename.substring(0, extensionIdx); + const ext = filename.split('.').pop(); + return { filename: name, extension: ext }; + } else { + return { filename, extension: undefined }; + } +} + /** * @function joinPath * Joins a set of string arguments to yield a string path diff --git a/frontend/src/views/SubmissionView.vue b/frontend/src/views/SubmissionView.vue index 7bf8b6c3..a4ad7275 100644 --- a/frontend/src/views/SubmissionView.vue +++ b/frontend/src/views/SubmissionView.vue @@ -1,16 +1,15 @@