Files
lucia-frontend/src/components/Navbar.vue

367 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<nav class="bg-neutral-700">
<div class="mx-auto px-4" :class="[showNavbarBreadcrumb? 'min-h-12': 'h-12']">
<div class="flex justify-between items-center flex-wrap relative" v-show="showNavbarBreadcrumb">
<div id="nav_bar" class="flex flex-1 items-center">
<!-- Files -->
<router-link to="/files" class="mr-4" v-if="showIcon" id="backPage">
<span class="material-symbols-outlined text-neutral-10 !leading-loose">
arrow_back
</span>
</router-link>
<div>
<h2 v-if="navViewName !== 'UPLOAD'" class="mr-14 py-3 text-2xl font-black text-neutral-10">{{ navViewName }}</h2>
<h2 v-else class="mr-14 py-3 text-2xl font-black text-neutral-10">FILES</h2>
</div>
<ul class="flex justify-center items-center space-x-4 text-xl font-semibold text-neutral-300 cursor-pointer">
<li @click="onNavItemBtnClick($event, item)"
v-for="(item, index) in navViewData[navViewName]"
:key="index" class="nav-item"
:class="{'active': activePage === item}">
{{ item }}
</li>
</ul>
</div>
<!-- Files Page: Search and Upload -->
<div class="flex justify-end items-center" v-if="navViewName === 'FILES'">
<!-- <form role="search">
<label for="searchFiles" class="mr-4 relative">
<input type="search" id="searchFiles" placeholder="Search" class="px-5 py-2 w-72 rounded-full text-sm align-middle duration-300 border border-neutral-500 hover:border-neutral-300 focus:outline-none focus:ring focus:border-neutral-300">
<span class="absolute top-2 bottom-1.5 right-0.5 flex justify-center items-center gap-2">
<IconSetting class="w-6 h-6 cursor-pointer"></IconSetting>
<span class="w-px h-6 block after:border after:border-neutral-300 after:content-['']"></span>
<button class="pr-2">
<IconSearch class="w-6 h-6"></IconSearch>
</button>
</span>
</label>
</form> -->
<!-- <label class="btn btn-sm btn-neutral cursor-pointer">
<input id="uploadFiles" class="hidden" type="file">
Upload
</label> -->
<div id="import_btn" class="btn btn-sm btn-neutral cursor-pointer" @click="uploadModal = true">
Import
<UploadModal :visible="uploadModal" @closeModal="uploadModal = $event"></UploadModal>
</div>
</div>
<!-- Upload, Performance, Compare 無按鈕行為 -->
<div v-else-if="noShowSaveButton"></div>
<!-- Other Page: Save and Download -->
<!-- Save data 跳重新命名沒有 data 跳要不要儲存沒有動都不跳 -->
<div v-else class="space-x-4">
<button class="btn btn-sm" :class="[ disabledSave ? 'btn-disable' : 'btn-neutral']"
:disabled="disabledSave" @click="saveModal">
Save
</button>
<!-- <button class="btn btn-sm btn-neutral">Download</button> -->
</div>
<AcctMenu/>
</div>
</div>
</nav>
</template>
<script>
import { storeToRefs, mapState, mapActions, } from 'pinia';
import filesStore from '@/stores/files.js';
import AllMapDataStore from '@/stores/allMapData.js';
import ConformanceStore from '@/stores/conformance.js';
import PageAdminStore from '@/stores/pageAdmin.js';
import IconSearch from '@/components/icons/IconSearch.vue';
import IconSetting from '@/components/icons/IconSetting.vue';
import { saveFilter, savedSuccessfully, saveConformance } from '@/module/alertModal.js';
import UploadModal from './File/UploadModal.vue';
import AcctMenu from './AccountMenu/AcctMenu.vue';
export default {
setup() {
const store = filesStore();
const allMapDataStore = AllMapDataStore();
const conformanceStore = ConformanceStore();
const { logId, tempFilterId, createFilterId, filterName, postRuleData, isUpdataFilter } = storeToRefs(allMapDataStore);
const { conformanceRuleData, conformanceLogId, conformanceFilterId,
conformanceLogTempCheckId, conformanceFilterTempCheckId,
conformanceLogCreateCheckId, conformanceFilterCreateCheckId,
isUpdataConformance, conformanceFileName
} = storeToRefs(conformanceStore);
return {
store, allMapDataStore, logId, tempFilterId, createFilterId,
filterName, postRuleData, isUpdataFilter, conformanceStore, conformanceRuleData,
conformanceLogId, conformanceFilterId, conformanceLogTempCheckId,
conformanceFilterTempCheckId, conformanceLogCreateCheckId,
conformanceFilterCreateCheckId, isUpdataConformance, conformanceFileName,
};
},
components: {
IconSearch,
IconSetting,
UploadModal,
AcctMenu,
},
data() {
return {
showNavbarBreadcrumb: false,
navViewData:
{
// 舉例FILES: ['ALL', 'DISCOVER', 'COMPARE', 'DESIGN', 'SIMULATION'],
FILES: ['ALL', 'DISCOVER', 'COMPARE'],
// 舉例DISCOVER: ['MAP', 'CONFORMANCE', 'PERFORMANCE', 'DATA']
DISCOVER: ['MAP', 'CONFORMANCE', 'PERFORMANCE'],
// 舉例COMPARE: ['PROCESS MAP', 'DASHBOARD']
COMPARE: ['PERFORMANCE'],
'ACCOUNT MANAGEMENT': [],
},
navViewName: 'FILES',
uploadModal: false,
};
},
computed: {
disabledSave: function () {
switch (this.$route.name) {
case 'Map':
case 'CheckMap':
// 沒有 filter Id, 沒有暫存 tempFilterId Id 就不能存檔
return this.tempFilterId ? false : true;
case 'Conformance':
case 'CheckConformance':
return this.conformanceFilterTempCheckId || this.conformanceLogTempCheckId ? false : true;
}
},
showIcon: function() {
let result = true;
result = ['FILES', 'UPLOAD'].includes(this.navViewName) ? false : true;
return result;
},
noShowSaveButton: function() {
return this.navViewName === 'UPLOAD' || this.navViewName === 'COMPARE' ||
this.navViewName === 'ACCOUNT MANAGEMENT' ||
this.activePage === 'PERFORMANCE' ? true : false;
},
...mapState(PageAdminStore, [
'activePage',
'pendingActivePage',
'activePageComputedByRoute',
'shouldKeepPreviousPage',
]),
},
watch: {
'$route':'getNavViewName',
filterName: function(newVal, oldVal) {
this.filterName = newVal;
},
activePageComputedByRoute (newVal) {
// console.log('activePageComputedByRoute newVal', newVal);
},
activePage: function(newVal){
// console.log('watch activePage', this.activePage);
},
pendingActivePage: function(newVal){
// console.log('watch pendingActivePage', this.pendingActivePage);
},
},
mounted() {
this.handleNavItemBtn();
if(this.$route.params.type === 'filter') {
this.createFilterId= this.$route.params.fileId;
}
this.showNavbarBreadcrumb = this.$route.matched[0].name !== ('AuthContainer') ? true : false;
this.getNavViewName();
},
methods: {
/**
* switch navbar item
* @param {event} event 選取 Navbar 選項後傳入的值
*/
onNavItemBtnClick(event) {
// console.log('onNavItemBtnClick');
let type;
let fileId;
let isCheckPage;
const navItemCandidate = event.target.innerText;
this.setPendingActivePage(navItemCandidate);
switch (this.navViewName) {
case 'FILES':
this.store.filesTag = navItemCandidate;
break;
case 'DISCOVER':
type = this.$route.params.type;
fileId = this.$route.params.fileId;
isCheckPage = this.$route.name.includes('Check');
switch (navItemCandidate) {
case 'MAP':
if(isCheckPage) {
this.$router.push({name: 'CheckMap', params: { type: type, fileId: fileId }});
}
else {
this.$router.push({name: 'Map', params: { type: type, fileId: fileId }});
}
break;
case 'CONFORMANCE':
if(isCheckPage) { // Beware of Swal popup, it might disturb which is the current active page
this.$router.push({name: 'CheckConformance', params: { type: type, fileId: fileId }});
}
else { // Beware of Swal popup, it might disturb which is the current active page
this.$router.push({name: 'Conformance', params: { type: type, fileId: fileId }});
}
break
case 'PERFORMANCE':
if(isCheckPage) {
this.$router.push({name: 'CheckPerformance', params: { type: type, fileId: fileId }});
}
else {
this.$router.push({name: 'Performance', params: { type: type, fileId: fileId }});
}
break;
}
break;
case 'COMPARE':
break
};
},
/**
* Based on the route.name, decide the navViewName.
* @returns {string} the string of navigation name to return
*/
getNavViewName() {
let name = this.$route.name;
let valueToSet;
if(this.$route.name === 'NotFound404') {
return;
}
// 說明this.$route.matched[1] 表示當前路由匹配的第二個路由記錄
this.navViewName = this.$route.matched[1].name.toUpperCase();
this.store.filesTag = 'ALL';
switch (this.navViewName) {
case 'FILES':
valueToSet = this.navItemCandidate;
break;
case 'DISCOVER':
switch (name) {
case 'Map':
case 'CheckMap':
valueToSet = 'MAP';
break;
case 'Conformance':
case 'CheckConformance':
valueToSet = 'CONFORMANCE';
break;
case 'Performanc':
case 'CheckPerformanc':
valueToSet = 'PERFORMANCE';
break;
}
break;
case 'COMPARE':
switch(name) {
case 'CompareDashboard':
valueToSet = 'DASHBOARD';
break;
}
break;
}
// Frontend is not sure which button will the user press on the modal,
// so here we need to save to a pending state
// 前端無法確定用戶稍後會按下彈窗上的哪個按鈕(取消還是確認、儲存)
// 因此我們需要將其保存到待處理狀態
if(!this.shouldKeepPreviousPage) { // 若使用者不是按下取消按鈕或是點選按鈕時
this.setPendingActivePage(valueToSet);
}
return valueToSet;
},
/**
* Save button' modal
*/
async saveModal() {
// 協助判斷 MAP, CONFORMANCE 儲存有「送出」或「取消」。
let isSaved;
// 傳給 Map通知 Sidebar 要關閉。
this.$emitter.emit('saveModal', false);
// 判斷在哪個子頁面
switch (this.$route.name) {
case 'Map':
// 先判斷有沒有 filter Id有就儲存 return沒有就往下走
// 沒有 filter Id, 有暫存 tempFilterId Id 可以另存新檔
if(this.createFilterId) {
await this.allMapDataStore.updataFilter();
if(this.isUpdataFilter) {
await savedSuccessfully(this.filterName);
}
}else if(this.logId){
isSaved = await saveFilter(this.allMapDataStore.addFilterId);
// 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) {
this.setActivePage('MAP');
await this.$router.push(`/discover/filter/${this.createFilterId}/map`);
}
};
break;
case 'CheckMap':
// 無論 parentLog, parentFilter做新 filter 皆另存新檔
isSaved = await saveFilter(this.allMapDataStore.addFilterId);
// 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) {
this.setActivePage('MAP');
await this.$router.push(`/discover/filter/${this.createFilterId}/map`);
}
break;
case 'Conformance':
case 'CheckConformance':
// 先判斷有沒有 check Id有就儲存 return沒有就往下走
// 沒有 check Id, 有暫存 temp Id 可以另存新檔
if(this.conformanceFilterCreateCheckId || this.conformanceLogCreateCheckId){
await this.conformanceStore.updataConformance();
if(this.isUpdataConformance) {
await savedSuccessfully(this.conformanceFileName);
}
} else {
isSaved = await saveConformance(this.conformanceStore.addConformanceCreateCheckId);
// 存檔後為 checkID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) {
if(this.conformanceLogId) {
this.setActivePage('CONFORMANCE');
await this.$router.push(`/discover/conformance/log/${this.conformanceLogCreateCheckId}/conformance`);
}
else if(this.conformanceFilterId) {
this.setActivePage('CONFORMANCE');
await this.$router.push(`/discover/conformance/filter/${this.conformanceFilterCreateCheckId}/conformance`);
}
}
}
break;
}
},
/**
* Set nav item button background color in case the variable is an empty string
*/
handleNavItemBtn() {
if(this.activePageComputedByRoute === "") {
this.setActivePageComputedByRoute(this.$route.matched[this.$route.matched.length - 1].name);
}
},
...mapActions(PageAdminStore, [
'setPendingActivePage',
'setPrevioiusPage',
'setActivePage',
'setActivePageComputedByRoute',
'setIsPagePendingBoolean',
],),
},
}
</script>
<style scoped>
#searchFiles::-webkit-search-cancel-button{
appearance: none;
}
</style>