Rename single-word Vue files to multi-word names and update references
Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
956
src/views/Files/FilesPage.vue
Normal file
956
src/views/Files/FilesPage.vue
Normal file
@@ -0,0 +1,956 @@
|
||||
<template>
|
||||
<div class="container pt-4 2xl:max-w-none">
|
||||
<!-- Recently Used & Performance Comparison -->
|
||||
<div>
|
||||
<!-- Performance Comparison -->
|
||||
<section v-if="filesTag === 'COMPARE'">
|
||||
<h2 class="h-12 font-bold py-4 mb-4 border-b border-neutral-500">
|
||||
Performance Comparison
|
||||
</h2>
|
||||
<div
|
||||
class="flex justify-start items-center gap-4 w-full h-[184px] scrollbar pb-4"
|
||||
>
|
||||
<!-- primaryDrag -->
|
||||
<div
|
||||
class="relative w-[216px] min-w-[216px] h-full"
|
||||
id="primaryDragCard"
|
||||
>
|
||||
<div
|
||||
v-if="primaryDragData.length === 0"
|
||||
class="w-full h-full p-4 border rounded border-neutral-300 duration-300 text-neutral-500 absolute"
|
||||
>
|
||||
<div
|
||||
class="h-full flex flex-col justify-center items-center gap-4"
|
||||
>
|
||||
<p class="text-4xl font-black">1</p>
|
||||
<p class="text-sm font-medium">Drag and drop a file here</p>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
v-model="primaryDragData"
|
||||
:group="{
|
||||
name: 'files',
|
||||
pull: false,
|
||||
put: primaryDragData.length < 1,
|
||||
}"
|
||||
item-key="id"
|
||||
class="w-full h-full"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div
|
||||
class="w-full h-full p-4 border rounded border-neutral-300 hover:bg-primary/10 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
|
||||
:title="element.name"
|
||||
>
|
||||
<div class="h-full">
|
||||
<span
|
||||
class="material-symbols-outlined mb-2 !text-[32px] block"
|
||||
>
|
||||
{{ element.icon }}
|
||||
</span>
|
||||
<h3
|
||||
class="text-sm font-medium mb-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis leading-tight"
|
||||
>
|
||||
{{ element.name }}
|
||||
</h3>
|
||||
<p
|
||||
class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden leading-tight"
|
||||
>
|
||||
{{ element.parentLog }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm text-neutral-500">
|
||||
{{ element.updated_at }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
<!-- delete icon -->
|
||||
<span
|
||||
v-show="primaryDragData.length > 0"
|
||||
class="material-symbols-outlined material-fill text-neutral-500 bg-neutral-10 block rounded-full absolute -top-[5%] -right-[5%] z-50 cursor-pointer hover:text-danger"
|
||||
@click="primaryDragDelete"
|
||||
>do_not_disturb_on</span
|
||||
>
|
||||
</div>
|
||||
<!-- secondaryDrag -->
|
||||
<div
|
||||
class="relative w-[216px] min-w-[216px] h-full"
|
||||
id="secondaryDragCard"
|
||||
>
|
||||
<div
|
||||
v-show="secondaryDragData.length === 0"
|
||||
class="w-full h-full p-4 border rounded border-neutral-300 duration-300 text-neutral-500 absolute"
|
||||
>
|
||||
<div
|
||||
class="h-full flex flex-col justify-center items-center gap-4"
|
||||
>
|
||||
<p class="text-4xl font-black">2</p>
|
||||
<p class="text-sm font-medium">Drag and drop a file here</p>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
v-model="secondaryDragData"
|
||||
:group="{
|
||||
name: 'files',
|
||||
pull: false,
|
||||
put: secondaryDragData.length < 1,
|
||||
}"
|
||||
item-key="id"
|
||||
class="w-full h-full"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div
|
||||
class="w-full h-full p-4 border rounded border-neutral-300 hover:bg-primary/10 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
|
||||
:title="element.name"
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
class="material-symbols-outlined mb-2 !text-[32px] block"
|
||||
>
|
||||
{{ element.icon }}
|
||||
</span>
|
||||
<h3
|
||||
class="text-sm font-medium mb-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis leading-tight"
|
||||
>
|
||||
{{ element.name }}
|
||||
</h3>
|
||||
<p
|
||||
class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden leading-tight"
|
||||
>
|
||||
{{ element.parentLog }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm text-neutral-500">
|
||||
{{ element.updated_at }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
<!-- delete icon -->
|
||||
<span
|
||||
v-show="secondaryDragData.length > 0"
|
||||
class="material-symbols-outlined material-fill bg-neutral-10 text-neutral-500 block rounded-full absolute -top-[5%] -right-[5%] cursor-pointer hover:text-danger"
|
||||
@click="secondaryDragDelete"
|
||||
>do_not_disturb_on</span
|
||||
>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
:class="isCompareDisabledButton ? 'btn-disable' : 'btn-c-primary'"
|
||||
:disabled="isCompareDisabledButton"
|
||||
@click="compareSubmit"
|
||||
>
|
||||
Compare
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Recently Used -->
|
||||
<section v-else>
|
||||
<h2 class="h-12 font-bold py-4 mb-4 border-b border-neutral-500">
|
||||
Recently Used
|
||||
</h2>
|
||||
<!-- card group, up to six items -->
|
||||
<ul
|
||||
class="flex justify-start items-center gap-4 overflow-x-auto w-full h-[184px] scrollbar pb-4"
|
||||
>
|
||||
<!-- card item v-for -->
|
||||
<li
|
||||
class="w-[216px] min-w-[216px] h-full p-4 border rounded border-neutral-300 hover:bg-primary/10 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
|
||||
v-for="file in recentlyUsedFiles.slice(0, 6)"
|
||||
:key="file.id"
|
||||
@dblclick="enterDiscover(file)"
|
||||
:title="file.name"
|
||||
@contextmenu="onRightClick($event, file)"
|
||||
>
|
||||
<div>
|
||||
<span class="material-symbols-outlined mb-2 !text-[32px] block">
|
||||
{{ file.icon }}
|
||||
</span>
|
||||
<h3
|
||||
class="text-sm font-medium mb-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis leading-tight"
|
||||
>
|
||||
{{ file.name }}
|
||||
</h3>
|
||||
<p
|
||||
class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden leading-tight"
|
||||
>
|
||||
{{ file.parentLog }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm text-neutral-500">
|
||||
{{ file.accessed_at }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<!-- All Files -->
|
||||
<div>
|
||||
<!-- Compare -->
|
||||
<section v-if="filesTag === 'COMPARE'">
|
||||
<!-- All Files header -->
|
||||
<div
|
||||
class="h-12 mb-4 border-b flex justify-between items-center border-neutral-500"
|
||||
>
|
||||
<h2 class="font-bold">All Files</h2>
|
||||
<ul class="flex items-center gap-x-4">
|
||||
<li>
|
||||
<Dropdown
|
||||
v-model="gridSort"
|
||||
:options="columnType"
|
||||
optionLabel="name"
|
||||
placeholder="Sort"
|
||||
class="w-full !border-neutral-500"
|
||||
inputClass="!text-sm"
|
||||
@change="getGridSortData($event)"
|
||||
></Dropdown>
|
||||
</li>
|
||||
<li>
|
||||
<IconGrid class="hover:bg-neutral-50 duration-300"></IconGrid>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- All Files type of grid -->
|
||||
<ul>
|
||||
<draggable
|
||||
tag="ul"
|
||||
:list="compareData"
|
||||
:group="{ name: 'files' }"
|
||||
itemKey="name"
|
||||
class="flex justify-start items-start gap-4 flex-wrap overflow-y-scroll overflow-x-hidden max-h-[calc(100vh_-_440px)] scrollbar"
|
||||
id="compareGridCards"
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<li
|
||||
class="w-[216px] h-[168px] p-4 border rounded border-neutral-300 hover:bg-primary/10 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
|
||||
:title="element.name"
|
||||
:id="'compareFile' + index"
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
class="material-symbols-outlined mb-2 !text-[32px] block"
|
||||
>
|
||||
{{ element.icon }}
|
||||
</span>
|
||||
<h3
|
||||
class="text-sm font-medium mb-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis leading-tight"
|
||||
>
|
||||
{{ element.name }}
|
||||
</h3>
|
||||
<p
|
||||
class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden leading-tight"
|
||||
>
|
||||
{{ element.parentLog }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm text-neutral-500">
|
||||
{{ element.updated_at }}
|
||||
</p>
|
||||
</li>
|
||||
</template>
|
||||
</draggable>
|
||||
</ul>
|
||||
</section>
|
||||
<!-- All & Discover -->
|
||||
<section v-else>
|
||||
<!-- All Files header -->
|
||||
<div
|
||||
class="h-12 mb-4 border-b flex justify-between items-center border-neutral-500"
|
||||
>
|
||||
<h2 class="font-bold">All Files</h2>
|
||||
<ul class="flex items-center gap-x-4">
|
||||
<li v-show="isActive !== null" class="animate-fadein">
|
||||
<ul
|
||||
class="flex justify-center items-center gap-x-4 px-4 py-1 rounded-full bg-neutral-200 text-neutral-700"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="rename"
|
||||
>edit_square</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="download"
|
||||
>download</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="deleteFile"
|
||||
>delete</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="cursor-pointer" @click="switchListOrGrid = false">
|
||||
<IconList
|
||||
class="hover:fill-primary hover:bg-neutral-50 duration-300"
|
||||
></IconList>
|
||||
</li>
|
||||
<li class="cursor-pointer" @click="switchListOrGrid = true">
|
||||
<IconGrid
|
||||
class="hover:fill-primary hover:bg-neutral-50 duration-300"
|
||||
></IconGrid>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- All Files type of List -->
|
||||
<div v-if="!switchListOrGrid">
|
||||
<DataTable
|
||||
:value="allFiles"
|
||||
dataKey="id"
|
||||
tableClass="w-full text-sm cursor-pointer relative table-fixed"
|
||||
:rowClass="setRowClass"
|
||||
breakpoint="0"
|
||||
@row-dblclick="enterDiscover($event.data)"
|
||||
contextmenu
|
||||
v-model:contextMenuSelection="selectedTableFile"
|
||||
@row-contextmenu="onRightClickTable"
|
||||
>
|
||||
<Column
|
||||
field="name"
|
||||
header="Name"
|
||||
bodyClass="font-medium fileName"
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="parentLog"
|
||||
header="Dependency"
|
||||
bodyClass="text-neutral-500"
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="fileType"
|
||||
header="File Type"
|
||||
bodyClass="text-neutral-500 fileType"
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="owner.name"
|
||||
header="Owner"
|
||||
bodyClass="text-neutral-500"
|
||||
sortable
|
||||
></Column>
|
||||
<Column
|
||||
field="updated_at"
|
||||
header="Last Update"
|
||||
bodyClass="text-neutral-500"
|
||||
sortable
|
||||
></Column>
|
||||
<Column bodyClass="text-neutral-500">
|
||||
<template #body="slotProps">
|
||||
<ul
|
||||
class="opacity-0 group-hover:opacity-100 flex justify-end items-center gap-x-2 text-neutral-700"
|
||||
>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="
|
||||
rename(
|
||||
slotProps.data.type,
|
||||
slotProps.data.id,
|
||||
'list-hover',
|
||||
slotProps.data.name,
|
||||
)
|
||||
"
|
||||
>edit_square</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="
|
||||
download(
|
||||
slotProps.data.type,
|
||||
slotProps.data.id,
|
||||
'list-hover',
|
||||
slotProps.data.name,
|
||||
)
|
||||
"
|
||||
>download</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
class="material-symbols-outlined align-bottom cursor-pointer hover:text-primary"
|
||||
@click="
|
||||
deleteFile(
|
||||
slotProps.data.type,
|
||||
slotProps.data.id,
|
||||
slotProps.data.name,
|
||||
'list-hover',
|
||||
)
|
||||
"
|
||||
>delete</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
<!-- All Files type of grid -->
|
||||
<ul
|
||||
class="flex justify-start items-start gap-4 flex-wrap overflow-y-scroll overflow-x-hidden max-h-[calc(100vh_-_440px)] scrollbar"
|
||||
v-else
|
||||
>
|
||||
<li
|
||||
class="w-[216px] h-[168px] p-4 border rounded border-neutral-300 hover:bg-primary/10 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
|
||||
v-for="(file, index) in allFiles"
|
||||
:key="file.id"
|
||||
:class="{ 'bg-primary/10 border-primary': isActive === index }"
|
||||
@dblclick="enterDiscover(file)"
|
||||
:title="file.name"
|
||||
@contextmenu="onRightClick($event, file)"
|
||||
@click="onGridCardClick(file, index)"
|
||||
:id="'li' + index"
|
||||
>
|
||||
<div>
|
||||
<span class="material-symbols-outlined mb-2 !text-[32px] block">
|
||||
{{ file.icon }}
|
||||
</span>
|
||||
<h3
|
||||
class="text-sm font-medium mb-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis leading-tight"
|
||||
>
|
||||
{{ file.name }}
|
||||
</h3>
|
||||
<p
|
||||
class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden leading-tight"
|
||||
>
|
||||
{{ file.parentLog }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm text-neutral-500">
|
||||
{{ file.updated_at }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
<!-- ContextMenu -->
|
||||
<ContextMenu
|
||||
ref="fileRightMenuRef"
|
||||
:model="items"
|
||||
@hide="selectedFile = null"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<template #item="{ item }">
|
||||
<a
|
||||
class="flex align-items-center px-4 py-2 duration-300 hover:bg-primary/20"
|
||||
>
|
||||
<span class="material-symbols-outlined">{{ item.icon }}</span>
|
||||
<span class="ml-2 text-sm inline-flex items-center">{{
|
||||
item.label
|
||||
}}</span>
|
||||
<span v-if="item.shortcut" class="border border-round p-1">{{
|
||||
item.shortcut
|
||||
}}</span>
|
||||
</a>
|
||||
</template>
|
||||
</ContextMenu>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
// The Lucia project.
|
||||
// Copyright 2024-2026 DSP, inc. All rights reserved.
|
||||
// Authors:
|
||||
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
|
||||
/**
|
||||
* @module views/Files/Files File management page with data
|
||||
* table listing uploaded files, discover/compare navigation,
|
||||
* and file operations (rename, delete).
|
||||
*/
|
||||
|
||||
import { ref, computed, watch, onMounted } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useMapCompareStore } from "@/stores/mapCompareStore";
|
||||
import { useLoginStore } from "@/stores/login";
|
||||
import { useFilesStore } from "@/stores/files";
|
||||
import { useAllMapDataStore } from "@/stores/allMapData";
|
||||
import { usePageAdminStore } from "@/stores/pageAdmin";
|
||||
import { useLoadingStore } from "@/stores/loading";
|
||||
import IconDataFormat from "@/components/icons/IconDataFormat.vue";
|
||||
import IconRule from "@/components/icons/IconRule.vue";
|
||||
import IconsFilter from "@/components/icons/IconsFilter.vue";
|
||||
import IconFlowChart from "@/components/icons/IconFlowChart.vue";
|
||||
import IconVector from "@/components/icons/IconVector.vue";
|
||||
import IconList from "@/components/icons/IconList.vue";
|
||||
import IconGrid from "@/components/icons/IconGrid.vue";
|
||||
import {
|
||||
renameModal,
|
||||
deleteFileModal,
|
||||
reallyDeleteInformation,
|
||||
} from "@/module/alertModal.js";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// Stores
|
||||
const mapCompareStore = useMapCompareStore();
|
||||
const loginStore = useLoginStore();
|
||||
const store = useFilesStore();
|
||||
const allMapDataStore = useAllMapDataStore();
|
||||
const pageAdminStore = usePageAdminStore();
|
||||
const loadingStore = useLoadingStore();
|
||||
|
||||
const { dependentsData, filesTag } = storeToRefs(store);
|
||||
const { createFilterId, baseLogId } = storeToRefs(allMapDataStore);
|
||||
const { isLoading } = storeToRefs(loadingStore);
|
||||
|
||||
// Data
|
||||
const isActive = ref(null);
|
||||
const isHover = ref(null);
|
||||
const switchListOrGrid = ref(false);
|
||||
const selectedTableFile = ref(null);
|
||||
const selectedFile = ref(null);
|
||||
const selectedType = ref(null);
|
||||
const selectedId = ref(null);
|
||||
const selectedName = ref(null);
|
||||
const compareData = ref(null);
|
||||
const primaryDragData = ref([]);
|
||||
const secondaryDragData = ref([]);
|
||||
const gridSort = ref(null);
|
||||
const fileRightMenuRef = ref(null);
|
||||
|
||||
const items = [
|
||||
{
|
||||
label: "Rename",
|
||||
icon: "edit_square",
|
||||
command: rename,
|
||||
},
|
||||
{
|
||||
label: "Download",
|
||||
icon: "download",
|
||||
command: download,
|
||||
},
|
||||
{
|
||||
separator: true,
|
||||
},
|
||||
{
|
||||
label: "Delete",
|
||||
icon: "delete",
|
||||
command: deleteFile,
|
||||
},
|
||||
];
|
||||
|
||||
const columnType = [
|
||||
{ name: "By File Name (A to Z)", code: "nameAscending" },
|
||||
{ name: "By File Name (Z to A)", code: "nameDescending" },
|
||||
{ name: "By Dependency (A to Z)", code: "parentLogAscending" },
|
||||
{ name: "By Dependency (Z to A)", code: "parentLogDescending" },
|
||||
{ name: "By File Type (A to Z)", code: "fileAscending" },
|
||||
{ name: "By File Type (Z to A)", code: "fileDescending" },
|
||||
{ name: "By Last Update (A to Z)", code: "updatedAscending" },
|
||||
{ name: "By Last Update (Z to A)", code: "updatedDescending" },
|
||||
];
|
||||
|
||||
// Computed
|
||||
/**
|
||||
* Read allFiles
|
||||
*/
|
||||
const allFiles = computed(() => {
|
||||
if (store.allFiles.length !== 0) {
|
||||
const sortFiles = Array.from(store.allFiles);
|
||||
sortFiles.sort(
|
||||
(x, y) => new Date(y.updated_base) - new Date(x.updated_base),
|
||||
);
|
||||
return sortFiles;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
/**
|
||||
* Sorts by time; entries without accessed_at are excluded.
|
||||
*/
|
||||
const recentlyUsedFiles = computed(() => {
|
||||
let recentlyUsed = Array.from(store.allFiles);
|
||||
recentlyUsed = recentlyUsed.filter((item) => item.accessed_at !== null);
|
||||
recentlyUsed.sort(
|
||||
(x, y) => new Date(y.accessed_base) - new Date(x.accessed_base),
|
||||
);
|
||||
return recentlyUsed;
|
||||
});
|
||||
|
||||
/**
|
||||
* Compare Submit button disabled
|
||||
*/
|
||||
const isCompareDisabledButton = computed(() => {
|
||||
return (
|
||||
primaryDragData.value.length === 0 || secondaryDragData.value.length === 0
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Really deleted information
|
||||
*/
|
||||
const reallyDeleteData = computed(() => {
|
||||
let result = [];
|
||||
if (store.allFiles.length !== 0) {
|
||||
result = JSON.parse(JSON.stringify(store.allFiles));
|
||||
result = result.filter((file) => file.is_deleted === true);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
// Watch
|
||||
watch(filesTag, (newValue) => {
|
||||
if (newValue !== "COMPARE") {
|
||||
primaryDragData.value = [];
|
||||
secondaryDragData.value = [];
|
||||
}
|
||||
});
|
||||
|
||||
watch(allFiles, (newValue) => {
|
||||
if (newValue !== null)
|
||||
compareData.value = JSON.parse(JSON.stringify(newValue));
|
||||
});
|
||||
|
||||
watch(
|
||||
reallyDeleteData,
|
||||
(newValue, oldValue) => {
|
||||
if (newValue.length !== 0 && oldValue.length === 0) {
|
||||
showReallyDelete();
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// Methods
|
||||
/**
|
||||
* Set Row Style
|
||||
*/
|
||||
function setRowClass() {
|
||||
return ["group"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Compare Row Style
|
||||
*/
|
||||
function setCompareRowClass() {
|
||||
return ["leading-6"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a file and navigates to the Discover/Compare/Design page.
|
||||
* @param {object} file - The file details.
|
||||
*/
|
||||
function enterDiscover(file) {
|
||||
let type;
|
||||
let fileId;
|
||||
let params;
|
||||
|
||||
pageAdminStore.setCurrentMapFile(file.name);
|
||||
|
||||
switch (file.type) {
|
||||
case "log":
|
||||
createFilterId.value = null;
|
||||
baseLogId.value = file.id;
|
||||
fileId = file.id;
|
||||
type = file.type;
|
||||
params = { type: type, fileId: fileId };
|
||||
router.push({ name: "Map", params: params });
|
||||
break;
|
||||
case "filter":
|
||||
createFilterId.value = file.id;
|
||||
baseLogId.value = file.parent.id;
|
||||
fileId = file.id;
|
||||
type = file.type;
|
||||
params = { type: type, fileId: fileId };
|
||||
router.push({ name: "Map", params: params });
|
||||
break;
|
||||
case "log-check":
|
||||
case "filter-check":
|
||||
fileId = file.id;
|
||||
type = file.parent.type;
|
||||
params = { type: type, fileId: fileId };
|
||||
router.push({ name: "CheckConformance", params: params });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Click DOM Event
|
||||
* @param {Event} event - The mouse event.
|
||||
* @param {string} file file's name
|
||||
*/
|
||||
function onRightClick(event, file) {
|
||||
selectedType.value = file.type;
|
||||
selectedId.value = file.id;
|
||||
selectedName.value = file.name;
|
||||
fileRightMenuRef.value.show(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Click Table DOM Event
|
||||
* @param {Event} event - The right-click event with row data.
|
||||
*/
|
||||
function onRightClickTable(event) {
|
||||
selectedType.value = event.data.type;
|
||||
selectedId.value = event.data.id;
|
||||
selectedName.value = event.data.name;
|
||||
fileRightMenuRef.value.show(event.originalEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Right Click Grid Card DOM Event
|
||||
* @param {object} file - The file object.
|
||||
* @param {number} index - The file index.
|
||||
*/
|
||||
function onGridCardClick(file, index) {
|
||||
selectedType.value = file.type;
|
||||
selectedId.value = file.id;
|
||||
selectedName.value = file.name;
|
||||
isActive.value = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* File's Rename
|
||||
* @param {string} type - The file type.
|
||||
* @param {number} id - The file ID.
|
||||
* @param {string} source - The hover icon source.
|
||||
* @param {string} fileName file's name
|
||||
*/
|
||||
function rename(type, id, source, fileName) {
|
||||
if (type && id && source === "list-hover") {
|
||||
selectedType.value = type;
|
||||
selectedId.value = id;
|
||||
selectedName.value = fileName;
|
||||
}
|
||||
renameModal(
|
||||
store.rename,
|
||||
selectedType.value,
|
||||
selectedId.value,
|
||||
selectedName.value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
* @param {string} type - The file type.
|
||||
* @param {number} id - The file ID.
|
||||
* @param {string} name - The file name.
|
||||
* @param {string} source - The hover icon source.
|
||||
*/
|
||||
async function deleteFile(type, id, name, source) {
|
||||
let srt = "";
|
||||
let data = [];
|
||||
// Check if the action comes from the hover icon menu
|
||||
if (type && id && name && source === "list-hover") {
|
||||
selectedType.value = type;
|
||||
selectedId.value = id;
|
||||
selectedName.value = name;
|
||||
}
|
||||
// Fetch dependent files
|
||||
await store.getDependents(selectedType.value, selectedId.value);
|
||||
if (dependentsData.value.length !== 0) {
|
||||
data = [...dependentsData.value];
|
||||
data.forEach((i) => {
|
||||
switch (i.type) {
|
||||
case "log-check":
|
||||
i.type = "rule";
|
||||
break;
|
||||
case "filter-check":
|
||||
i.type = "rule";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const content = `<li>[${i.type}] ${i.name}</li>`;
|
||||
srt += content;
|
||||
});
|
||||
}
|
||||
deleteFileModal(
|
||||
srt,
|
||||
selectedType.value,
|
||||
selectedId.value,
|
||||
selectedName.value,
|
||||
);
|
||||
srt = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows files deleted by admin or by other accounts.
|
||||
*/
|
||||
function showReallyDelete() {
|
||||
let srt = "";
|
||||
|
||||
if (reallyDeleteData.value.length !== 0) {
|
||||
reallyDeleteData.value.forEach((file) => {
|
||||
switch (file.type) {
|
||||
case "log-check":
|
||||
case "filter-check":
|
||||
default:
|
||||
file.type = "rule";
|
||||
break;
|
||||
}
|
||||
|
||||
const content = `<li>[${file.type}] ${file.name}</li>`;
|
||||
srt += content;
|
||||
});
|
||||
}
|
||||
reallyDeleteInformation(srt, reallyDeleteData.value);
|
||||
srt = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Download file as CSV
|
||||
* @param {string} type - The file type.
|
||||
* @param {number} id - The file ID.
|
||||
* @param {string} source - The hover icon source.
|
||||
* @param {string} name - The file name.
|
||||
*/
|
||||
function download(type, id, source, name) {
|
||||
if (type && id && source === "list-hover" && name) {
|
||||
selectedType.value = type;
|
||||
selectedId.value = id;
|
||||
selectedName.value = name;
|
||||
}
|
||||
store.downloadFileCSV(
|
||||
selectedType.value,
|
||||
selectedId.value,
|
||||
selectedName.value,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Compare Primary log
|
||||
*/
|
||||
function primaryDragDelete() {
|
||||
compareData.value.unshift(primaryDragData.value[0]);
|
||||
primaryDragData.value.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Compare Secondary log
|
||||
*/
|
||||
function secondaryDragDelete() {
|
||||
compareData.value.unshift(secondaryDragData.value[0]);
|
||||
secondaryDragData.value.length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter the Compare page
|
||||
*/
|
||||
function compareSubmit() {
|
||||
const primaryType = primaryDragData.value[0].type;
|
||||
const secondaryType = secondaryDragData.value[0].type;
|
||||
const primaryId = primaryDragData.value[0].id;
|
||||
const secondaryId = secondaryDragData.value[0].id;
|
||||
const params = {
|
||||
primaryType: primaryType,
|
||||
primaryId: primaryId,
|
||||
secondaryType: secondaryType,
|
||||
secondaryId: secondaryId,
|
||||
};
|
||||
|
||||
mapCompareStore.setCompareRouteParam(
|
||||
primaryType,
|
||||
primaryId,
|
||||
secondaryType,
|
||||
secondaryId,
|
||||
);
|
||||
router.push({ name: "CompareDashboard", params: params });
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter/sort handler for the grid view template.
|
||||
* @param {event} event choose columnType item
|
||||
*/
|
||||
function getGridSortData(event) {
|
||||
const code = event.value.code;
|
||||
|
||||
// Text sorting: convert the name field to lowercase for comparison using localeCompare()
|
||||
switch (code) {
|
||||
case "nameAscending":
|
||||
compareData.value = compareData.value.sort((a, b) =>
|
||||
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
|
||||
);
|
||||
break;
|
||||
case "nameDescending":
|
||||
compareData.value = compareData.value
|
||||
.sort((a, b) =>
|
||||
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
|
||||
)
|
||||
.reverse();
|
||||
break;
|
||||
case "parentLogAscending":
|
||||
compareData.value = compareData.value.sort((a, b) =>
|
||||
a.parentLog.toLowerCase().localeCompare(b.parentLog.toLowerCase()),
|
||||
);
|
||||
break;
|
||||
case "parentLogDescending":
|
||||
compareData.value = compareData.value
|
||||
.sort((a, b) =>
|
||||
a.parentLog.toLowerCase().localeCompare(b.parentLog.toLowerCase()),
|
||||
)
|
||||
.reverse();
|
||||
break;
|
||||
case "fileAscending":
|
||||
compareData.value = compareData.value.sort((a, b) =>
|
||||
a.fileType.toLowerCase().localeCompare(b.fileType.toLowerCase()),
|
||||
);
|
||||
break;
|
||||
case "fileDescending":
|
||||
compareData.value = compareData.value
|
||||
.sort((a, b) =>
|
||||
a.fileType.toLowerCase().localeCompare(b.fileType.toLowerCase()),
|
||||
)
|
||||
.reverse();
|
||||
break;
|
||||
case "updatedAscending":
|
||||
compareData.value = compareData.value.sort(
|
||||
(a, b) => new Date(a.updated_base) - new Date(b.updated_base),
|
||||
);
|
||||
break;
|
||||
case "updatedDescending":
|
||||
compareData.value = compareData.value
|
||||
.sort((a, b) => new Date(a.updated_base) - new Date(b.updated_base))
|
||||
.reverse();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mounted
|
||||
onMounted(() => {
|
||||
isLoading.value = true;
|
||||
store.fetchAllFiles();
|
||||
window.addEventListener("click", (e) => {
|
||||
const clickedLi = e.target.closest("li");
|
||||
if (!clickedLi || !clickedLi.id.startsWith("li")) isActive.value = null;
|
||||
});
|
||||
// Add the .scrollbar class to the DataTable tbody
|
||||
const tbodyElement = document.querySelector(".p-datatable-tbody");
|
||||
tbodyElement?.classList.add("scrollbar");
|
||||
isLoading.value = false;
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
@reference "../../assets/tailwind.css";
|
||||
:deep(thead) {
|
||||
@apply sticky top-0 bg-neutral-10 after:border-b after:border-neutral-500 after:w-full after:left-0 after:bottom-0 after:absolute table table-fixed w-full;
|
||||
}
|
||||
:deep(tbody) {
|
||||
@apply overflow-y-auto overflow-x-hidden max-h-[calc(100vh_-_480px)] block;
|
||||
}
|
||||
:deep(table th) {
|
||||
@apply border-b !border-neutral-500 !p-2 text-left font-bold !bg-neutral-10 whitespace-nowrap break-keep overflow-hidden text-ellipsis;
|
||||
}
|
||||
:deep(table td) {
|
||||
@apply border-b border-neutral-300 !p-2 whitespace-nowrap break-keep overflow-hidden text-ellipsis;
|
||||
}
|
||||
:deep(tbody > tr) {
|
||||
@apply duration-300 cursor-pointer hover:bg-primary/10 focus:!outline-none table table-fixed w-full;
|
||||
}
|
||||
:deep(.p-sortable-column) {
|
||||
@apply focus:!shadow-none !text-neutral-900;
|
||||
}
|
||||
:deep(.p-sortable-column-icon) {
|
||||
@apply !text-[#6c757d];
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user