392 lines
11 KiB
Vue
392 lines
11 KiB
Vue
<script lang="ts" setup>
|
|
import type { QTableProps } from 'quasar'
|
|
import { computed, onMounted, ref } from 'vue'
|
|
import { storeToRefs } from 'pinia'
|
|
import api from '@/services/HttpService'
|
|
|
|
import FileIcon from '@/components/FileIcon.vue'
|
|
import DialogDelete from '@/components/DialogDelete.vue'
|
|
import FileFormWrapper from './FileFormWrapper.vue'
|
|
import FolderFormWrapper from './FolderFormWrapper.vue'
|
|
import { useFileInfoStore } from '@/stores/file-info-data'
|
|
import useStorage from '@/stores/storage'
|
|
|
|
const storageStore = useStorage()
|
|
const { folder, file, currentInfo } = storeToRefs(storageStore)
|
|
const { goto, deleteFolder, deleteFile, constructUrl } = storageStore
|
|
|
|
const { getFormatDate, getSize, getType, getFileInfo } = useFileInfoStore()
|
|
|
|
const fileFormComponent = ref<InstanceType<typeof FileFormWrapper>>()
|
|
const folderFormComponent = ref<InstanceType<typeof FolderFormWrapper>>()
|
|
|
|
const currentIcon = computed(() =>
|
|
currentInfo.value.dept === 0
|
|
? 'mdi-file-cabinet'
|
|
: currentInfo.value.dept === 1
|
|
? 'inbox'
|
|
: 'o_folder_open',
|
|
)
|
|
const TREE_LEVEL_NAME = ['ตู้เอกสาร', 'ลิ้นชัก', 'แฟ้ม', 'แฟ้มย่อย'] as const
|
|
|
|
const props = defineProps<{
|
|
mode: 'admin' | 'user'
|
|
}>()
|
|
|
|
interface ApiResponse {
|
|
size: string
|
|
}
|
|
|
|
const deleteState = ref<boolean>(false)
|
|
const open = ref<boolean>(false)
|
|
const sizefolder = ref<string>()
|
|
|
|
const deletePath = ref<string>('')
|
|
const deleteTarget = ref<'deleteFolder' | 'deleteFile'>()
|
|
const deleteMap = { deleteFolder, deleteFile }
|
|
|
|
function triggerFolderDelete(pathname: string) {
|
|
deleteTarget.value = 'deleteFolder'
|
|
deletePath.value = pathname
|
|
deleteState.value = !deleteState.value
|
|
}
|
|
|
|
function triggerFileDelete(pathname: string) {
|
|
deleteTarget.value = 'deleteFile'
|
|
deletePath.value = pathname
|
|
deleteState.value = !deleteState.value
|
|
}
|
|
|
|
function getSizeFolder(constructFolder: string) {
|
|
const src = constructFolder.split('/').filter(Boolean)
|
|
const path = src.join('/') + '/'
|
|
const res = async () => {
|
|
const response = await api.get(constructUrl(src, false) + '/size')
|
|
sizefolder.value = response.data.size
|
|
}
|
|
|
|
if (folder.value[currentInfo.value.path]) {
|
|
const idx = folder.value[currentInfo.value.path].findIndex(
|
|
(v) => v.pathname === path,
|
|
)
|
|
|
|
if (idx !== -1) {
|
|
res()
|
|
if (folder.value[currentInfo.value.path][idx].folderSize) {
|
|
if (
|
|
folder.value[currentInfo.value.path][idx].folderSize !=
|
|
sizefolder.value
|
|
) {
|
|
folder.value[currentInfo.value.path][idx].folderSize =
|
|
sizefolder.value
|
|
}
|
|
} else {
|
|
folder.value[currentInfo.value.path][idx].folderSize = sizefolder.value
|
|
}
|
|
}
|
|
return getSize(folder.value[currentInfo.value.path][idx].folderSize)
|
|
}
|
|
}
|
|
|
|
const colFolder = [
|
|
{
|
|
name: 'name',
|
|
required: true,
|
|
label: 'ชื่อ',
|
|
align: 'left',
|
|
field: 'name',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'createdBy',
|
|
label: 'สร้างโดย',
|
|
align: 'center',
|
|
field: 'createdBy',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'createdAt',
|
|
label: 'วันที่สร้าง',
|
|
align: 'center',
|
|
field: 'createdAt',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'actions',
|
|
align: 'center',
|
|
label: '',
|
|
field: '',
|
|
},
|
|
] satisfies QTableProps['columns']
|
|
|
|
const colFile = [
|
|
{
|
|
name: 'name',
|
|
label: 'ชื่อไฟล์',
|
|
align: 'left',
|
|
field: 'fileName',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'title',
|
|
label: 'ชื่อเรื่อง',
|
|
align: 'center',
|
|
field: 'title',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'fileType',
|
|
label: 'ประเภทของไฟล์',
|
|
align: 'center',
|
|
field: 'fileType',
|
|
sortable: true,
|
|
},
|
|
{
|
|
name: 'actions',
|
|
align: 'center',
|
|
label: '',
|
|
field: '',
|
|
},
|
|
] satisfies QTableProps['columns']
|
|
|
|
const onRowClick = ((_, row) => {
|
|
goto(row.pathname)
|
|
}) satisfies QTableProps['onRowClick']
|
|
</script>
|
|
|
|
<template>
|
|
<file-form-wrapper ref="fileFormComponent" />
|
|
<folder-form-wrapper ref="folderFormComponent" />
|
|
<dialog-delete
|
|
v-model:open="deleteState"
|
|
@confirm="() => deleteTarget && deleteMap[deleteTarget](deletePath)"
|
|
/>
|
|
<div class="q-mt-md">
|
|
<div class="q-gutter-sm">
|
|
<div
|
|
class="flex flex-break d justify-between space-between"
|
|
v-if="
|
|
currentInfo.dept >= 1 &&
|
|
currentInfo.dept < 4 &&
|
|
props.mode === 'admin'
|
|
"
|
|
>
|
|
<div>
|
|
<span class="text-h6">{{ TREE_LEVEL_NAME[currentInfo.dept] }}</span>
|
|
</div>
|
|
<div>
|
|
<q-btn
|
|
outline
|
|
push
|
|
dense
|
|
class="q-px-md q-ml-md"
|
|
type="submit"
|
|
color="primary"
|
|
icon="add"
|
|
id="listViewFolderCreate"
|
|
:label="'สร้าง' + TREE_LEVEL_NAME[currentInfo.dept]"
|
|
@click.stop="() => folderFormComponent?.triggerFolderCreate()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<q-table
|
|
flat
|
|
bordered
|
|
row-key="name"
|
|
class="cursor"
|
|
v-if="currentInfo.dept !== 4"
|
|
:pagination="{ rowsPerPage: 20 }"
|
|
:rows="folder[currentInfo.path]"
|
|
:columns="colFolder"
|
|
@row-click="onRowClick"
|
|
>
|
|
<template v-slot:body-cell-name="data">
|
|
<q-td>
|
|
<q-icon :name="currentIcon" size="2em" color="primary" />
|
|
{{ data.row.name }}
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-createdBy="data">
|
|
<q-td class="text-center">
|
|
<span class="sort-icon-offset-margin">
|
|
{{ data.row.createdBy }}
|
|
</span>
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-createdAt="data">
|
|
<q-td class="text-center">
|
|
<span class="sort-icon-offset-margin">
|
|
{{ getFormatDate(data.row.createdAt) }}
|
|
</span>
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-actions="data">
|
|
<q-td class="justify-center">
|
|
<div>
|
|
<q-icon
|
|
@click.stop="
|
|
() => {
|
|
open = !open
|
|
}
|
|
"
|
|
class="q-ma-sm"
|
|
name="o_info"
|
|
size="2em"
|
|
color="primary"
|
|
/>
|
|
<q-tooltip
|
|
:delay="1000"
|
|
anchor="center left"
|
|
self="center right"
|
|
:offset="[5, 1]"
|
|
>
|
|
{{ getSizeFolder(data.row.pathname) }}
|
|
</q-tooltip>
|
|
</div>
|
|
<div v-if="props.mode === 'admin'">
|
|
<q-btn
|
|
flat
|
|
dense
|
|
id="listViewFolderEdit"
|
|
icon="o_edit"
|
|
color="positive"
|
|
@click.stop="
|
|
folderFormComponent?.triggerFolderEdit(
|
|
data.row.name,
|
|
data.row.pathname,
|
|
)
|
|
"
|
|
/>
|
|
<q-btn
|
|
flat
|
|
dense
|
|
id="listViewFolderDelete"
|
|
color="negative"
|
|
icon="mdi-trash-can-outline"
|
|
:data-testid="data.row.name"
|
|
@click.stop="triggerFolderDelete(data.row.pathname)"
|
|
/>
|
|
</div>
|
|
</q-td>
|
|
</template>
|
|
</q-table>
|
|
</div>
|
|
</div>
|
|
<div class="q-mt-md" v-if="currentInfo.dept >= 3">
|
|
<div class="q-gutter-sm">
|
|
<div class="flex flex-break justify-between space-between">
|
|
<div><span class="text-h6">เอกสาร</span></div>
|
|
<div>
|
|
<q-btn
|
|
outline
|
|
push
|
|
dense
|
|
id="listViewFileCreate"
|
|
class="q-px-md q-ml-md"
|
|
label="สร้างเอกสาร"
|
|
type="submit"
|
|
color="primary"
|
|
icon="add"
|
|
v-if="props.mode == 'admin'"
|
|
@click.stop="() => fileFormComponent?.triggerFileCreate()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<q-table
|
|
flat
|
|
bordered
|
|
class="cursor"
|
|
row-key="name"
|
|
:rows="file[currentInfo.path]"
|
|
:columns="colFile"
|
|
:pagination="{ rowsPerPage: 20 }"
|
|
>
|
|
<template v-slot:body-cell-name="data">
|
|
<q-td
|
|
id="listViewGetFileInfo"
|
|
style="width: 50%"
|
|
@click="() => getFileInfo(data.row)"
|
|
>
|
|
<file-icon
|
|
size="list"
|
|
:fileMimeType="data.row.fileType || '-'"
|
|
:fileName="data.row.fileName || '-'"
|
|
/>
|
|
{{ data.row.fileName }}
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-title="data">
|
|
<q-td class="text-center">
|
|
<span class="sort-icon-offset-margin">{{ data.row.title }}</span>
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-fileType="data">
|
|
<q-td class="text-center">
|
|
<span class="sort-icon-offset-margin">
|
|
{{ getType(data.row.fileType, data.row.fileName) }}
|
|
</span>
|
|
</q-td>
|
|
</template>
|
|
<template v-slot:body-cell-actions="data">
|
|
<q-td class="justify-center">
|
|
<div>
|
|
<q-icon
|
|
class="q-ma-sm"
|
|
name="o_info"
|
|
size="2em"
|
|
color="primary"
|
|
/>
|
|
<q-tooltip
|
|
anchor="center left"
|
|
self="center right"
|
|
:offset="[5, 1]"
|
|
>
|
|
{{ getSize(data.row.fileSize) }}
|
|
</q-tooltip>
|
|
</div>
|
|
<div v-if="props.mode === 'admin'">
|
|
<q-btn
|
|
flat
|
|
color="positive"
|
|
dense
|
|
icon="o_edit"
|
|
@click.stop="
|
|
() =>
|
|
fileFormComponent?.triggerFileEdit(
|
|
data.row,
|
|
data.row.pathname,
|
|
)
|
|
"
|
|
id="listViewFileEdit"
|
|
/>
|
|
<q-btn
|
|
flat
|
|
dense
|
|
id="listViewFileDelete"
|
|
color="negative"
|
|
icon="mdi-trash-can-outline"
|
|
@click.stop="() => triggerFileDelete(data.row.pathname)"
|
|
/>
|
|
</div>
|
|
</q-td>
|
|
</template>
|
|
</q-table>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
.justify-center {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.sort-icon-offset-margin {
|
|
margin-right: 18px;
|
|
}
|
|
|
|
.cursor {
|
|
cursor: pointer;
|
|
}
|
|
</style>
|