From 9ff9c179bccb51cf173eac1199d534dabc8da242 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Sun, 10 Dec 2023 09:27:26 +0700 Subject: [PATCH] refactor: new storage store --- Services/client/src/components/PageLayout.vue | 2 + Services/client/src/stores/storage.ts | 217 ++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 Services/client/src/stores/storage.ts diff --git a/Services/client/src/components/PageLayout.vue b/Services/client/src/components/PageLayout.vue index 9c3ceb0..278c305 100644 --- a/Services/client/src/components/PageLayout.vue +++ b/Services/client/src/components/PageLayout.vue @@ -15,6 +15,7 @@ import GlobalErrorDialog from './GlobalErrorDialog.vue' import SearchBar from '@/modules/01_user/components/SearchBar.vue' import FileDownload from '@/modules/01_user/components/FileDownload.vue' +import useStorage from '@/stores/storage' const DEPT_NAME = ['ตู้เอกสาร', 'ลิ้นชัก', 'แฟ้ม', 'แฟ้มย่อย'] as const @@ -23,6 +24,7 @@ const { isSearch } = storeToRefs(useSearchDataStore()) const { data, currentDept, currentPath } = storeToRefs(useTreeDataStore()) const { createFolder, getCabinet, gotoParent, getFolder } = useTreeDataStore() +useStorage() useSocketStore() const viewMode = ref<'view_list' | 'view_module'>('view_list') diff --git a/Services/client/src/stores/storage.ts b/Services/client/src/stores/storage.ts new file mode 100644 index 0000000..3533435 --- /dev/null +++ b/Services/client/src/stores/storage.ts @@ -0,0 +1,217 @@ +import { computed, reactive, ref } from 'vue' +import { defineStore } from 'pinia' +import { io } from 'socket.io-client' +import api from '@/services/HttpService' + +function constructUrl(path: string | string[], append = true) { + const arr = Array.isArray(path) ? path : path.split('/').filter(Boolean) + const url = + import.meta.env.VITE_API_ENDPOINT + + arr.reduce((a, v, i) => { + switch (String(i)) { + case '0': + return `cabinet/${v}` + case '1': + return `${a}/drawer/${v}` + case '2': + return `${a}/folder/${v}` + case '3': + return `${a}/subfolder/${v}` + default: + return a + } + }, '') + return append + ? url + ['cabinet', '/drawer', '/folder', '/subfolder'][arr.length] + : url +} + +const useStorage = defineStore('storage', async () => { + const folderList = ref< + Record< + string, // path that contains folders + { + pathname: string + name: string + }[] + > + >({}) + const fileList = ref< + Record< + string, // path that contains files + { + pathname: string + path: string + fileName: string + fileSize: string + fileType: string + title: string + description: string + category: string[] + keyword: string[] + updatedAt: string + updatedBy: string + createdAt: string + createdBy: string + }[] + > + >({}) + const tree = computed(() => { + type Structure = { + pathname: string + name: string + folder: Structure + file: (typeof fileList.value)[string] + }[] + + let structure: Structure = [] + + // parse list of folder and list of file into tree + Object.entries(folderList.value).forEach(([key, value]) => { + const arr = key.split('/').filter(Boolean) + + // init outer tree + if (arr.length === 0) { + structure = value.map((v) => ({ + pathname: v.pathname, + name: v.name, + folder: [], + file: [], + })) + } else { + let current: Structure[number] | undefined + + // traverse into tree + arr.forEach((v, i) => { + current = + i === 0 + ? structure.find((x) => x.name === v) + : current?.folder.find((x) => x.name === v) + }) + + // set data in tree (object is references to the same object) + if (current) { + current.folder = value.map((v) => ({ + pathname: v.pathname, + name: v.name, + folder: [], + file: [], + })) + current.file = fileList.value[key] ?? [] + } + } + }) + + return structure + }) + const currentInfo = reactive<{ + path: string + dept: number + }>({ + path: '', + dept: 0, + }) + + async function getStorage(path: string = '') { + const res = await api.get<(typeof folderList.value)[string]>( + constructUrl(path), + ) + if (res.status === 200) + folderList.value[path] = res.data.sort((a, b) => + a.pathname.localeCompare(b.pathname), + ) + } + + async function getStorageFile(path: string = '') { + const arr = path.split('/').filter(Boolean) + + if (arr.length < 3) return + + const res = await api.get<(typeof fileList.value)[string]>( + constructUrl(path, false) + '/file', + ) + if (res.status === 200) + fileList.value[path] = res.data.sort((a, b) => + a.pathname.localeCompare(b.pathname), + ) + } + + async function goto(path: string) { + const arr = path.split('/').filter(Boolean) + + for (let i = 0; i < arr.length; i++) { + const current = arr.slice(0, i - arr.length).join('/') + '/' + if (!folderList.value[current]) await getStorage(current) + } + + // only get this path once, after that will get from socket.io-client instead + if (!folderList.value[path]) await getStorage(path) + if (!fileList.value[path]) await getStorageFile(path) + + currentInfo.path = path + currentInfo.dept = path.split('/').filter(Boolean).length - 1 + } + + async function gotoParent() { + const arr = currentInfo.path.split('/').filter(Boolean) + await goto([...arr.slice(0, -1), ''].join('/')) + } + + const socket = io('http://localhost:25570') + + socket.on('connect', () => console.info('Socket.io connected.')) + socket.on('disconnect', () => console.info('Socket.io disconnected.')) + socket.on('CreateFolder', (data: { pathname: string }) => { + const arr = data.pathname.split('/').filter(Boolean) + const path = [...arr.slice(0, -1), ''].join('/') + + if (folderList.value[path]) { + folderList.value[path].push({ + pathname: data.pathname, + name: arr[arr.length - 1], + }) + folderList.value[path].sort((a, b) => + a.pathname.localeCompare(b.pathname), + ) + } + }) + socket.on( + 'EditFolder', + (data: { from: { pathname: string }; to: { pathname: string } }) => { + console.log(data) // TODO: Implement + }, + ) + socket.on('DeleteFolder', (data: { pathname: string }) => { + if (folderList.value[data.pathname]) { + delete folderList.value[data.pathname] + } + + const arr = data.pathname.split('/').filter(Boolean) + const path = [...arr.slice(0, -1), ''].join('/') + + if (folderList.value[path]) { + folderList.value[path] = folderList.value[path].filter( + (v) => v.pathname !== data.pathname, + ) + } + }) + + await goto('เอกสารทดสอบระบบ/dev-test/dev-test/') + console.log(tree.value) + + return { + // information + currentInfo, + folderList, + fileList, + tree, + // fetch + getStorage, + getStorageFile, + // traverse + goto, + gotoParent, + } +}) + +export default useStorage