refactor: admin search to edit, delete

This commit is contained in:
puri-ph4tt 2023-12-06 09:05:43 +07:00
parent 83441e6bed
commit 2d6cbe2dc4
3 changed files with 233 additions and 36 deletions

View file

@ -2,21 +2,52 @@
import { storeToRefs } from 'pinia'
import { useSearchDataStore } from '@/stores/searched-data'
import { useFileInfoStore } from '@/stores/file-info-data'
import { useTreeDataStore } from '@/stores/tree-data'
import DialogDelete from './DialogDelete.vue'
import UploadExistDialog from './UploadExistDialog.vue'
import FileForm from './FileForm.vue'
import FileItemAction from '@/components/FileItemAction.vue'
import FileIcon from '@/components/FileIcon.vue'
import type { QTableProps } from 'quasar'
import { onMounted, ref, watch } from 'vue'
defineProps<{
viewMode: 'view_list' | 'view_module'
}>()
const { foundFile } = storeToRefs(useSearchDataStore())
const props = withDefaults(
defineProps<{
action: boolean
viewMode: 'view_list' | 'view_module'
}>(),
{
action: false,
},
)
const { foundFile, isActFoundFile } = storeToRefs(useSearchDataStore())
const { getFileInfo, getSize, getType } = useFileInfoStore()
const { updateFile, deleteFile, checkFile } = useTreeDataStore()
const keywordList = ref<string[]>([])
const categoryList = ref<string[]>([])
const selectKeyword = ref<string[]>([])
const selectCategory = ref<string[]>([])
const filterFoundFile = ref<any>()
const fileExistNotification = ref<boolean>(false)
const fileFormError = ref<{ fileExist?: boolean }>({})
const deleteFormType = ref<'deleteFile'>('deleteFile')
const dialogDeleteState = ref<boolean>(false)
const deleteFormPath = ref<string>('')
const fileFormType = ref<'edit'>('edit')
const fileFormState = ref<boolean>(false)
const fileFormPath = ref<string>('')
const fileFormData = ref<{
file?: File
title?: string
description?: string
keyword?: string[]
category?: string[]
}>({})
const columns: QTableProps['columns'] = [
{
name: 'name',
@ -53,6 +84,82 @@ const columns: QTableProps['columns'] = [
},
]
const currentParam = ref<Parameters<typeof submitFileForm>[0]>()
async function submitFileForm(
value: {
mode: 'create' | 'edit'
file?: File
title: string
description: string
keyword: string[]
category: string[]
},
force = false,
) {
currentParam.value = value
if (value.file && checkFile(value.file.name) && !force) {
fileExistNotification.value = true
return
}
if (value.mode === 'edit') {
await updateFile(
fileFormPath.value,
{
title: value.title,
description: value.description,
keyword: value.keyword,
category: value.category,
},
value.file,
)
setTimeout(() => {
isActFoundFile.value = true
}, 300)
}
fileFormData.value = {}
fileFormState.value = false
currentParam.value = undefined
}
function triggerFileEdit(
value: {
title: string
description: string
keyword: string[]
category: string[]
},
pathname: string,
) {
fileFormState.value = true
fileFormType.value = 'edit'
fileFormPath.value = pathname
fileFormData.value = {
title: value.title,
description: value.description,
keyword: value.keyword,
category: value.category,
}
}
function triggerFileDelete(pathname: string) {
deleteFormType.value = 'deleteFile'
deleteFormPath.value = pathname
dialogDeleteState.value = !dialogDeleteState.value
}
function confirmDelete() {
if (deleteFormType) {
deleteFile(deleteFormPath.value)
setTimeout(() => {
isActFoundFile.value = true
}, 300)
}
}
function filterSearch() {
function updateList() {
keywordList.value = []
@ -101,7 +208,7 @@ onMounted(() => {
</script>
<template>
<div class="row grid q-pt-md q-gutter-sm">
<div class="row grid q-py-md q-gutter-sm">
<q-select
outlined
dense
@ -111,6 +218,7 @@ onMounted(() => {
:options="keywordList"
style="width: 100%"
label="คำสำคัญ"
class="custom-selection"
/>
<q-select
outlined
@ -124,7 +232,7 @@ onMounted(() => {
/>
</div>
<div v-if="viewMode === 'view_list' && foundFile.length > 0">
<div v-if="props.viewMode === 'view_list' && foundFile.length > 0">
<div class="grid q-mt-md">
<div v-for="(value, index) in filterFoundFile" :key="value.title">
<div
@ -147,6 +255,28 @@ onMounted(() => {
:fileMimeType="value.fileType ? value.fileType : 'unknow'"
/>
</div>
<div
class="absolute"
style="top: 0.5rem; right: 0.5rem"
v-if="props.action"
>
<file-item-action
:nameId="value.pathname"
@edit="
() =>
triggerFileEdit(
{
title: value.title,
description: value.description,
keyword: value.keyword,
category: value.category,
},
value.pathname,
)
"
@delete="() => triggerFileDelete(value.pathname)"
/>
</div>
<div
class="text-overflow-handle block q-px-md text-center"
style="max-width: 100%"
@ -158,7 +288,10 @@ onMounted(() => {
</div>
</div>
<div v-if="viewMode === 'view_module' && foundFile.length > 0">
<div
v-if="props.viewMode === 'view_module' && foundFile.length > 0"
class="q-gutter-sm"
>
<q-table
flat
bordered
@ -184,7 +317,7 @@ onMounted(() => {
</q-td>
</template>
<template v-slot:body-cell-actions="sizeData">
<template v-slot:body-cell-actions="actionData">
<q-td class="justify-center">
<div>
<q-icon class="q-ma-sm" name="info" size="2em" color="primary" />
@ -193,9 +326,29 @@ onMounted(() => {
self="center right"
:offset="[5, 1]"
>
{{ getSize(sizeData.row.fileSize) }}
{{ getSize(actionData.row.fileSize) }}
</q-tooltip>
</div>
<div v-if="props.action">
<q-btn
flat
color="positive"
dense
icon="edit"
@click="
() => triggerFileEdit(actionData.row, actionData.row.pathname)
"
id="listViewFileEdit"
/>
<q-btn
flat
color="negative"
dense
icon="delete"
@click="() => triggerFileDelete(actionData.row.pathname)"
id="listViewFileDelete"
/>
</div>
</q-td>
</template>
</q-table>
@ -204,6 +357,26 @@ onMounted(() => {
<div class="q-mt-md" v-if="foundFile.length == 0">
<span>ไมพบรายการทนหา</span>
</div>
<file-form
:mode="fileFormType"
:error="fileFormError"
v-model:open="fileFormState"
v-model:title="fileFormData.title"
v-model:description="fileFormData.description"
v-model:keyword="fileFormData.keyword"
v-model:category="fileFormData.category"
@filechange="(name: string) => (fileFormError.fileExist = checkFile(name))"
@submit="submitFileForm"
/>
<upload-exist-dialog
v-model:notification="fileExistNotification"
@confirm="() => currentParam && submitFileForm(currentParam, true)"
@cancel="() => (currentParam = undefined)"
/>
<dialog-delete v-model:open="dialogDeleteState" @confirm="confirmDelete" />
</template>
<style scoped lang="scss">
@ -239,4 +412,10 @@ onMounted(() => {
.grid .box {
position: relative;
}
.justify-center {
display: flex;
justify-content: center;
align-items: center;
}
</style>

View file

@ -23,7 +23,6 @@ const { data, currentDept, currentPath } = storeToRefs(useTreeDataStore())
const { createFolder, getCabinet, gotoParent, getFolder } = useTreeDataStore()
const viewMode = ref<'view_list' | 'view_module'>('view_list')
const inputSearch = ref<string>()
const props = defineProps<{
mode: 'admin' | 'user'
}>()
@ -71,10 +70,12 @@ onMounted(getCabinet)
<div
class="q-px-md q-py-sm text-primary bg-grey-1 pointer"
id="container-header"
@click="() => {
currentPath = '' ;
getFolder(currentPath)
}"
@click="
() => {
currentPath = ''
getFolder(currentPath)
}
"
>
<span class="block q-my-sm text-weight-bold">ดเกบเอกสาร</span>
</div>
@ -110,6 +111,7 @@ onMounted(getCabinet)
>
<q-icon name="arrow_back" size="1rem" color="primary" />
</q-btn>
<span v-if="isSearch === true">ผลการค้นหา</span>
<q-breadcrumbs v-if="isSearch === false" active-color="primary">
<q-breadcrumbs-el
v-if="currentPath === '/' || !currentPath"
@ -136,7 +138,7 @@ onMounted(getCabinet)
/>
</q-breadcrumbs>
</div>
<span v-if="isSearch === true">ผลการค้นหา</span>
<q-btn
v-if="
mode === 'admin' &&
@ -179,7 +181,11 @@ onMounted(getCabinet)
</div>
</div>
<div>
<file-searched :viewMode="viewMode" v-if="isSearch === true" />
<file-searched
:viewMode="viewMode"
:action="props.mode === 'admin'"
v-if="isSearch === true"
/>
<file-item
:viewMode="viewMode"
:action="props.mode === 'admin'"

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref } from 'vue'
import { ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import axiosClient from '@/services/HttpService'
@ -10,22 +10,21 @@ import { useLoader } from '@/stores/loader'
import AdvancedSearch from '@/modules/01_user/components/AdvancedSearch.vue'
const loaderStore = useLoader()
const { isSearch, isAdvSearchCall } = storeToRefs(useSearchDataStore())
const {
isSearch,
isAdvSearchCall,
isActFoundFile,
searchData,
advSearchDataField,
advSearchDataRow,
} = storeToRefs(useSearchDataStore())
const { getFoundFile } = useSearchDataStore()
const advSearchComp = ref<InstanceType<typeof AdvancedSearch>>()
const optionsField = [
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
{ label: 'หมวดหมู่ (category)', value: 'category' },
{ label: 'เนื้อหาในไฟล์ (content)', value: 'attachment.content' },
]
const searchData = ref<{
field: string
value: string
}>({
field: 'title',
value: '',
})
const submitSearchData = ref<{
AND: { field: string; value: string }[]
OR: { field: string; value: string }[]
@ -53,9 +52,9 @@ async function searchSubmit() {
value: searchData.value.value,
})
if (isAdvSearchCall.value && advSearchComp.value) {
const advField = advSearchComp.value.advSearchDataField
const advRow = advSearchComp.value.advSearchDataRow
if (isAdvSearchCall.value) {
let advField = advSearchDataField.value
let advRow = advSearchDataRow.value
advRow.forEach((d: { field: string; value: string; op: string }) => {
if (d.field && d.value.trim() !== '') {
@ -63,11 +62,13 @@ async function searchSubmit() {
submitSearchData.value[op].push({ field: d.field, value: d.value })
}
})
if (advField.keyword.trim() !== '') {
submitSearchData.value.AND.push({
field: 'keyword',
value: advField.keyword,
})
if (advField.keyword.length > 0) {
for (let i = 0; i < advField.keyword.length; i++) {
submitSearchData.value.AND.push({
field: 'keyword',
value: advField.keyword[i],
})
}
}
if (advField.description.trim() !== '') {
submitSearchData.value.AND.push({
@ -93,6 +94,18 @@ async function searchSubmit() {
}
}
}
watch(
() => isActFoundFile.value,
(edited) => {
if (edited === true) {
searchSubmit()
setTimeout(() => {
isActFoundFile.value = false
}, 300)
}
},
)
</script>
<template>
@ -154,7 +167,6 @@ async function searchSubmit() {
<div class="row items-center justify-between q-gutter-y-md q-pt-sm">
<div class="column col-grow">
<advanced-search
ref="advSearchComp"
:searchSubmit="searchSubmit"
:submit-search-data="submitSearchData"
/>