Files
lucia-frontend/src/views/Files/index.vue

172 lines
6.3 KiB
Vue

<template>
<div class="container pt-4 2xl:max-w-none">
<!-- Recently Used -->
<section class="mb-4">
<h2 class="font-bold py-4 mb-4 border-b border-neutral-500">Recently Used</h2>
<!-- card group 最多六個-->
<ul class="flex justify-start items-center gap-4 overflow-x-auto w-full h-[192px] scrollbar whitespace-nowrap pb-4">
<!-- card item v-for -->
<li class="min-w-[216px] h-[168px] p-4 border rounded border-neutral-300 hover:text-primary hover:bg-primary/50 hover:border-primary duration-300
flex flex-col justify-between cursor-pointer" v-for="(file, index) in recentlyUsedFiles.slice(0, 6)" :key="file.id" @dblclick="enterDiscover(file)">
<div>
<figure class="mb-2">
<IconDataFormat class="w-8 h-8 hover:fill-primary"></IconDataFormat>
</figure>
<h3 class="text-sm font-medium mb-2">
{{ file.name }}
</h3>
<p class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden">
{{ file.parentLog }}
</p>
</div>
<p class="text-sm text-neutral-500">
{{ file.accessed_at }}
</p>
</li>
</ul>
</section>
<section>
<div class="py-4 mb-4 border-b flex justify-between items-center border-neutral-500">
<h2 class="font-bold">All Files</h2>
<ul class="flex items-center">
<li class="mr-4 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 class="overflow-y-scroll overflow-x-hidden scrollbar -mx-2 max-h-[calc(100vh_-_480px)]" v-if="!switchListOrGrid">
<DataTable :value="allFiles" dataKey="id" tableClass="w-full !border-separate !border-spacing-x-2 text-sm cursor-pointer" breakpoint="0" @row-dblclick="enterDiscover($event.data)">
<Column field="name" header="Name" bodyClass="font-medium" sortable></Column>
<Column field="parentLog" header="Parent log" bodyClass="text-neutral-500" sortable></Column>
<Column field="fileType" header="File type" bodyClass="text-neutral-500" 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>
</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_-_480px)] scrollbar" v-else>
<li class="w-[216px] h-[168px] p-4 border rounded border-neutral-300 hover:text-primary hover:bg-primary/50 hover:border-primary duration-300 flex flex-col justify-between cursor-pointer"
v-for="(file, index) in allFiles" :key="file.id" @dblclick="enterDiscover(file)">
<div>
<figure class="mb-2">
<IconDataFormat class="w-8 h-8 hover:fill-primary"></IconDataFormat>
</figure>
<h3 class="text-sm font-medium mb-2">
{{ file.name }}
</h3>
<p class="text-sm text-neutral-500 whitespace-nowrap break-keep text-ellipsis overflow-hidden">
{{ file.parentLog }}
</p>
</div>
<p class="text-sm text-neutral-500">
{{ file.updated_at }}
</p>
</li>
</ul>
</section>
</div>
</template>
<script>
import filesStore from '@/stores/files.js';
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';
export default {
data() {
return {
switchListOrGrid: false,
filesTag: 'all',
}
},
setup() {
const store = filesStore();
return {
store,
}
},
components: {
IconDataFormat,
IconRule,
IconsFilter,
IconFlowChart,
IconVector,
IconList,
IconGrid,
},
computed: {
/**
* Read allFiles
*/
allFiles: function() {
if(this.store.allFiles.length !== 0){
let sortFiles = Array.from(this.store.allFiles);
sortFiles.sort((x,y) => new Date(x.updated_at) - new Date(y.updated_at));
return sortFiles;
}
},
/**
* 時間排序,如果沒有 accessed_at 就不加入 data
*/
recentlyUsedFiles: function() {
let recentlyUsedFiles = Array.from(this.store.allFiles);
recentlyUsedFiles.filter(item => item.accessed_at !== null);
recentlyUsedFiles.sort((x, y) => new Date(y.accessed_at) - new Date(x.accessed_at));
return recentlyUsedFiles;
},
},
watch:{
allFiles:{
handler:function(val,oldVal){
this.allFiles;
},
deep:true,
}
},
methods: {
/**
* 選擇該 files 進入 Discover/Compare/Design 頁面
* @param {object} file
*/
enterDiscover(file){
this.$router.push({ name: 'Discover', params: { logId: file.id }});
},
},
mounted() {
this.store.fetchEventLog();
this.store.fetchFilter();
}
}
</script>
<style scoped>
:deep(thead) {
@apply sticky top-0 bg-neutral-10
}
:deep(table th) {
@apply border-b !border-neutral-500 p-3 text-left font-black !bg-neutral-10 whitespace-nowrap break-keep overflow-hidden text-ellipsis
}
:deep(table td) {
@apply border-b border-neutral-300 p-3 whitespace-nowrap break-keep overflow-hidden text-ellipsis
}
:deep(tbody > tr) {
@apply duration-300 cursor-pointer hover:bg-primary/10 focus:!outline-none
}
:deep(.p-sortable-column) {
@apply focus:!shadow-none !text-neutral-900
}
:deep(.p-sortable-column-icon) {
@apply !text-[#6c757d]
}
</style>