refactor: admin search to edit, delete
This commit is contained in:
parent
83441e6bed
commit
2d6cbe2dc4
3 changed files with 233 additions and 36 deletions
|
|
@ -2,21 +2,52 @@
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useSearchDataStore } from '@/stores/searched-data'
|
import { useSearchDataStore } from '@/stores/searched-data'
|
||||||
import { useFileInfoStore } from '@/stores/file-info-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 FileIcon from '@/components/FileIcon.vue'
|
||||||
|
|
||||||
import type { QTableProps } from 'quasar'
|
import type { QTableProps } from 'quasar'
|
||||||
import { onMounted, ref, watch } from 'vue'
|
import { onMounted, ref, watch } from 'vue'
|
||||||
|
|
||||||
defineProps<{
|
const props = withDefaults(
|
||||||
viewMode: 'view_list' | 'view_module'
|
defineProps<{
|
||||||
}>()
|
action: boolean
|
||||||
|
viewMode: 'view_list' | 'view_module'
|
||||||
const { foundFile } = storeToRefs(useSearchDataStore())
|
}>(),
|
||||||
|
{
|
||||||
|
action: false,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
const { foundFile, isActFoundFile } = storeToRefs(useSearchDataStore())
|
||||||
const { getFileInfo, getSize, getType } = useFileInfoStore()
|
const { getFileInfo, getSize, getType } = useFileInfoStore()
|
||||||
|
const { updateFile, deleteFile, checkFile } = useTreeDataStore()
|
||||||
const keywordList = ref<string[]>([])
|
const keywordList = ref<string[]>([])
|
||||||
const categoryList = ref<string[]>([])
|
const categoryList = ref<string[]>([])
|
||||||
const selectKeyword = ref<string[]>([])
|
const selectKeyword = ref<string[]>([])
|
||||||
const selectCategory = ref<string[]>([])
|
const selectCategory = ref<string[]>([])
|
||||||
const filterFoundFile = ref<any>()
|
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'] = [
|
const columns: QTableProps['columns'] = [
|
||||||
{
|
{
|
||||||
name: 'name',
|
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 filterSearch() {
|
||||||
function updateList() {
|
function updateList() {
|
||||||
keywordList.value = []
|
keywordList.value = []
|
||||||
|
|
@ -101,7 +208,7 @@ onMounted(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="row grid q-pt-md q-gutter-sm">
|
<div class="row grid q-py-md q-gutter-sm">
|
||||||
<q-select
|
<q-select
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
|
|
@ -111,6 +218,7 @@ onMounted(() => {
|
||||||
:options="keywordList"
|
:options="keywordList"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
label="คำสำคัญ"
|
label="คำสำคัญ"
|
||||||
|
class="custom-selection"
|
||||||
/>
|
/>
|
||||||
<q-select
|
<q-select
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -124,7 +232,7 @@ onMounted(() => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</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 class="grid q-mt-md">
|
||||||
<div v-for="(value, index) in filterFoundFile" :key="value.title">
|
<div v-for="(value, index) in filterFoundFile" :key="value.title">
|
||||||
<div
|
<div
|
||||||
|
|
@ -147,6 +255,28 @@ onMounted(() => {
|
||||||
:fileMimeType="value.fileType ? value.fileType : 'unknow'"
|
:fileMimeType="value.fileType ? value.fileType : 'unknow'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</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
|
<div
|
||||||
class="text-overflow-handle block q-px-md text-center"
|
class="text-overflow-handle block q-px-md text-center"
|
||||||
style="max-width: 100%"
|
style="max-width: 100%"
|
||||||
|
|
@ -158,7 +288,10 @@ onMounted(() => {
|
||||||
</div>
|
</div>
|
||||||
</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
|
<q-table
|
||||||
flat
|
flat
|
||||||
bordered
|
bordered
|
||||||
|
|
@ -184,7 +317,7 @@ onMounted(() => {
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:body-cell-actions="sizeData">
|
<template v-slot:body-cell-actions="actionData">
|
||||||
<q-td class="justify-center">
|
<q-td class="justify-center">
|
||||||
<div>
|
<div>
|
||||||
<q-icon class="q-ma-sm" name="info" size="2em" color="primary" />
|
<q-icon class="q-ma-sm" name="info" size="2em" color="primary" />
|
||||||
|
|
@ -193,9 +326,29 @@ onMounted(() => {
|
||||||
self="center right"
|
self="center right"
|
||||||
:offset="[5, 1]"
|
:offset="[5, 1]"
|
||||||
>
|
>
|
||||||
{{ getSize(sizeData.row.fileSize) }}
|
{{ getSize(actionData.row.fileSize) }}
|
||||||
</q-tooltip>
|
</q-tooltip>
|
||||||
</div>
|
</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>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
|
|
@ -204,6 +357,26 @@ onMounted(() => {
|
||||||
<div class="q-mt-md" v-if="foundFile.length == 0">
|
<div class="q-mt-md" v-if="foundFile.length == 0">
|
||||||
<span>ไม่พบรายการที่ค้นหา</span>
|
<span>ไม่พบรายการที่ค้นหา</span>
|
||||||
</div>
|
</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>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
@ -239,4 +412,10 @@ onMounted(() => {
|
||||||
.grid .box {
|
.grid .box {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.justify-center {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ const { data, currentDept, currentPath } = storeToRefs(useTreeDataStore())
|
||||||
const { createFolder, getCabinet, gotoParent, getFolder } = useTreeDataStore()
|
const { createFolder, getCabinet, gotoParent, getFolder } = useTreeDataStore()
|
||||||
|
|
||||||
const viewMode = ref<'view_list' | 'view_module'>('view_list')
|
const viewMode = ref<'view_list' | 'view_module'>('view_list')
|
||||||
const inputSearch = ref<string>()
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
mode: 'admin' | 'user'
|
mode: 'admin' | 'user'
|
||||||
}>()
|
}>()
|
||||||
|
|
@ -71,10 +70,12 @@ onMounted(getCabinet)
|
||||||
<div
|
<div
|
||||||
class="q-px-md q-py-sm text-primary bg-grey-1 pointer"
|
class="q-px-md q-py-sm text-primary bg-grey-1 pointer"
|
||||||
id="container-header"
|
id="container-header"
|
||||||
@click="() => {
|
@click="
|
||||||
currentPath = '' ;
|
() => {
|
||||||
getFolder(currentPath)
|
currentPath = ''
|
||||||
}"
|
getFolder(currentPath)
|
||||||
|
}
|
||||||
|
"
|
||||||
>
|
>
|
||||||
<span class="block q-my-sm text-weight-bold">ตู้จัดเก็บเอกสาร</span>
|
<span class="block q-my-sm text-weight-bold">ตู้จัดเก็บเอกสาร</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -110,6 +111,7 @@ onMounted(getCabinet)
|
||||||
>
|
>
|
||||||
<q-icon name="arrow_back" size="1rem" color="primary" />
|
<q-icon name="arrow_back" size="1rem" color="primary" />
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
<span v-if="isSearch === true">ผลการค้นหา</span>
|
||||||
<q-breadcrumbs v-if="isSearch === false" active-color="primary">
|
<q-breadcrumbs v-if="isSearch === false" active-color="primary">
|
||||||
<q-breadcrumbs-el
|
<q-breadcrumbs-el
|
||||||
v-if="currentPath === '/' || !currentPath"
|
v-if="currentPath === '/' || !currentPath"
|
||||||
|
|
@ -136,7 +138,7 @@ onMounted(getCabinet)
|
||||||
/>
|
/>
|
||||||
</q-breadcrumbs>
|
</q-breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="isSearch === true">ผลการค้นหา</span>
|
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="
|
v-if="
|
||||||
mode === 'admin' &&
|
mode === 'admin' &&
|
||||||
|
|
@ -179,7 +181,11 @@ onMounted(getCabinet)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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
|
<file-item
|
||||||
:viewMode="viewMode"
|
:viewMode="viewMode"
|
||||||
:action="props.mode === 'admin'"
|
:action="props.mode === 'admin'"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import axiosClient from '@/services/HttpService'
|
import axiosClient from '@/services/HttpService'
|
||||||
|
|
||||||
|
|
@ -10,22 +10,21 @@ import { useLoader } from '@/stores/loader'
|
||||||
import AdvancedSearch from '@/modules/01_user/components/AdvancedSearch.vue'
|
import AdvancedSearch from '@/modules/01_user/components/AdvancedSearch.vue'
|
||||||
|
|
||||||
const loaderStore = useLoader()
|
const loaderStore = useLoader()
|
||||||
const { isSearch, isAdvSearchCall } = storeToRefs(useSearchDataStore())
|
const {
|
||||||
|
isSearch,
|
||||||
|
isAdvSearchCall,
|
||||||
|
isActFoundFile,
|
||||||
|
searchData,
|
||||||
|
advSearchDataField,
|
||||||
|
advSearchDataRow,
|
||||||
|
} = storeToRefs(useSearchDataStore())
|
||||||
const { getFoundFile } = useSearchDataStore()
|
const { getFoundFile } = useSearchDataStore()
|
||||||
const advSearchComp = ref<InstanceType<typeof AdvancedSearch>>()
|
|
||||||
const optionsField = [
|
const optionsField = [
|
||||||
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
|
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
|
||||||
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
|
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
|
||||||
{ label: 'หมวดหมู่ (category)', value: 'category' },
|
{ label: 'หมวดหมู่ (category)', value: 'category' },
|
||||||
{ label: 'เนื้อหาในไฟล์ (content)', value: 'attachment.content' },
|
{ label: 'เนื้อหาในไฟล์ (content)', value: 'attachment.content' },
|
||||||
]
|
]
|
||||||
const searchData = ref<{
|
|
||||||
field: string
|
|
||||||
value: string
|
|
||||||
}>({
|
|
||||||
field: 'title',
|
|
||||||
value: '',
|
|
||||||
})
|
|
||||||
const submitSearchData = ref<{
|
const submitSearchData = ref<{
|
||||||
AND: { field: string; value: string }[]
|
AND: { field: string; value: string }[]
|
||||||
OR: { field: string; value: string }[]
|
OR: { field: string; value: string }[]
|
||||||
|
|
@ -53,9 +52,9 @@ async function searchSubmit() {
|
||||||
value: searchData.value.value,
|
value: searchData.value.value,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isAdvSearchCall.value && advSearchComp.value) {
|
if (isAdvSearchCall.value) {
|
||||||
const advField = advSearchComp.value.advSearchDataField
|
let advField = advSearchDataField.value
|
||||||
const advRow = advSearchComp.value.advSearchDataRow
|
let advRow = advSearchDataRow.value
|
||||||
|
|
||||||
advRow.forEach((d: { field: string; value: string; op: string }) => {
|
advRow.forEach((d: { field: string; value: string; op: string }) => {
|
||||||
if (d.field && d.value.trim() !== '') {
|
if (d.field && d.value.trim() !== '') {
|
||||||
|
|
@ -63,11 +62,13 @@ async function searchSubmit() {
|
||||||
submitSearchData.value[op].push({ field: d.field, value: d.value })
|
submitSearchData.value[op].push({ field: d.field, value: d.value })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (advField.keyword.trim() !== '') {
|
if (advField.keyword.length > 0) {
|
||||||
submitSearchData.value.AND.push({
|
for (let i = 0; i < advField.keyword.length; i++) {
|
||||||
field: 'keyword',
|
submitSearchData.value.AND.push({
|
||||||
value: advField.keyword,
|
field: 'keyword',
|
||||||
})
|
value: advField.keyword[i],
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (advField.description.trim() !== '') {
|
if (advField.description.trim() !== '') {
|
||||||
submitSearchData.value.AND.push({
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -154,7 +167,6 @@ async function searchSubmit() {
|
||||||
<div class="row items-center justify-between q-gutter-y-md q-pt-sm">
|
<div class="row items-center justify-between q-gutter-y-md q-pt-sm">
|
||||||
<div class="column col-grow">
|
<div class="column col-grow">
|
||||||
<advanced-search
|
<advanced-search
|
||||||
ref="advSearchComp"
|
|
||||||
:searchSubmit="searchSubmit"
|
:searchSubmit="searchSubmit"
|
||||||
:submit-search-data="submitSearchData"
|
:submit-search-data="submitSearchData"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue