Merge branch 'phatt' into development

This commit is contained in:
puri-ph4tt 2023-12-06 09:13:14 +07:00
commit f2303bee8b
6 changed files with 283 additions and 69 deletions

View file

@ -190,6 +190,7 @@ const file = ref<File | undefined>()
<div class="q-mt-md">
<q-select
outlined
dense
:model-value="category"
label="กดปุ่มEnterเพื่อเพิ่ม"
use-input
@ -217,6 +218,7 @@ const file = ref<File | undefined>()
<div class="q-mt-md">
<q-select
outlined
dense
label="กดปุ่มEnterเพื่อเพิ่ม"
use-input
use-chips

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,11 +1,11 @@
divdivdivdivdivdiv
<script setup lang="ts">
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useSearchDataStore } from '@/stores/searched-data'
const { isAdvSearchCall } = storeToRefs(useSearchDataStore())
const { isAdvSearchCall, advSearchDataRow, advSearchDataField } =
storeToRefs(useSearchDataStore())
const optionsField = [
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
@ -16,26 +16,6 @@ const optionsOp = [
{ label: 'และ', value: 'AND' },
{ label: 'หรือ', value: 'OR' },
]
const advSearchDataRow = ref<
{
op: 'AND' | 'OR'
field: 'title' | 'keyword'
value: string
}[]
>([
{
op: 'AND',
field: 'title',
value: '',
},
])
const advSearchDataField = ref<{
keyword: string
description: string
}>({
keyword: '',
description: '',
})
const props = defineProps<{
searchSubmit: Function
submitSearchData: {
@ -50,11 +30,6 @@ const props = defineProps<{
}
}>()
defineExpose({
advSearchDataRow,
advSearchDataField,
})
function addAdvSearchData() {
advSearchDataRow.value.push({
op: 'AND',
@ -75,7 +50,7 @@ function clearAdvSearchData() {
},
]
advSearchDataField.value = {
keyword: '',
keyword: [],
description: '',
}
}
@ -193,13 +168,17 @@ function clearAdvSearchData() {
<div class="row q-col-gutter-md q-pb-md">
<div class="col-12 col-md-5">
<q-input
id="advSearchKeyword"
dense
<q-select
outlined
placeholder="คำสำคัญ"
@keydown.enter.prevent="searchSubmit()"
dense
v-model="advSearchDataField.keyword"
placeholder="คำสำคัญ"
use-input
use-chips
multiple
hide-dropdown-icon
input-debounce="0"
new-value-mode="add"
/>
</div>
<div class="col-12 col-md-grow">

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"
/>

View file

@ -2,10 +2,42 @@ import { ref } from 'vue'
import { defineStore } from 'pinia'
import type { EhrFile } from '@/stores/tree-data'
export interface searchData {
field: string
value: string
}
export interface advSearchDataRow {
op: 'AND' | 'OR'
field: 'title' | 'keyword'
value: string
}
export interface advSearchDataField {
keyword: string[]
description: string
}
export const useSearchDataStore = defineStore('searched', () => {
const foundFile = ref<EhrFile[]>([])
const isAdvSearchCall = ref<boolean>(false)
const isSearch = ref<Boolean>(false)
const isActFoundFile = ref<Boolean>(false)
const searchData = ref<searchData>({
field: 'title',
value: '',
})
const advSearchDataRow = ref<advSearchDataRow[]>([
{
op: 'AND',
field: 'title',
value: '',
},
])
const advSearchDataField = ref<advSearchDataField>({
keyword: [],
description: '',
})
async function getFoundFile(data: EhrFile[]) {
foundFile.value = data
@ -15,6 +47,10 @@ export const useSearchDataStore = defineStore('searched', () => {
foundFile,
isSearch,
isAdvSearchCall,
isActFoundFile,
searchData,
advSearchDataRow,
advSearchDataField,
getFoundFile,
}
})