WIP #295 not yet keep previous page

This commit is contained in:
Cindy Chang
2024-05-31 12:03:09 +08:00
parent 83f399b746
commit 69f6a2048a
6 changed files with 190 additions and 35 deletions

View File

@@ -5,5 +5,5 @@
<style scoped></style> <style scoped></style>
<script setup> <script setup>
import { RouterLink, RouterView } from "vue-router"; import { RouterView } from "vue-router";
</script> </script>

View File

@@ -2,7 +2,7 @@
<nav class="bg-neutral-700"> <nav class="bg-neutral-700">
<div class="mx-auto px-4" :class="[showNavbarBreadcrumb? 'min-h-12': 'h-12']"> <div class="mx-auto px-4" :class="[showNavbarBreadcrumb? 'min-h-12': 'h-12']">
<div class="flex justify-between items-center flex-wrap" v-show="showNavbarBreadcrumb"> <div class="flex justify-between items-center flex-wrap" v-show="showNavbarBreadcrumb">
<div class="flex flex-1 items-center"> <div id="nav_bar" class="flex flex-1 items-center">
<!-- Files --> <!-- Files -->
<router-link to="/files" class="mr-4" v-if="showIcon" id="backPage"> <router-link to="/files" class="mr-4" v-if="showIcon" id="backPage">
<span class="material-symbols-outlined text-neutral-10 !leading-loose"> <span class="material-symbols-outlined text-neutral-10 !leading-loose">
@@ -14,7 +14,10 @@
<h2 v-else class="mr-14 py-3 text-2xl font-black text-neutral-10">FILES</h2> <h2 v-else class="mr-14 py-3 text-2xl font-black text-neutral-10">FILES</h2>
</div> </div>
<ul class="flex justify-center items-center space-x-4 text-xl font-semibold text-neutral-300 cursor-pointer"> <ul class="flex justify-center items-center space-x-4 text-xl font-semibold text-neutral-300 cursor-pointer">
<li @click="switchNavItem($event, item)" v-for="(item, index) in navViewData[navViewName]" :key="index" :class="{'active': isActive === item}">{{ item }}</li> <li @click="switchNavItem($event, item)" v-for="(item, index) in navViewData[navViewName]"
:key="index" :class="{'active': activePage === item}">
{{ item }}
</li>
</ul> </ul>
</div> </div>
<!-- Files Page: Search and Upload --> <!-- Files Page: Search and Upload -->
@@ -45,7 +48,10 @@
<!-- Other Page: Save and Download --> <!-- Other Page: Save and Download -->
<!-- Save data 跳重新命名沒有 data 跳要不要儲存沒有動都不跳 --> <!-- Save data 跳重新命名沒有 data 跳要不要儲存沒有動都不跳 -->
<div v-else class="space-x-4"> <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" :class="[ disabledSave ? 'btn-disable' : 'btn-neutral']"
:disabled="disabledSave" @click="saveModal">
Save
</button>
<!-- <button class="btn btn-sm btn-neutral">Download</button> --> <!-- <button class="btn btn-sm btn-neutral">Download</button> -->
</div> </div>
</div> </div>
@@ -53,10 +59,11 @@
</nav> </nav>
</template> </template>
<script> <script>
import { storeToRefs } from 'pinia'; import { storeToRefs, mapState, mapActions, } from 'pinia';
import filesStore from '@/stores/files.js'; import filesStore from '@/stores/files.js';
import AllMapDataStore from '@/stores/allMapData.js'; import AllMapDataStore from '@/stores/allMapData.js';
import ConformanceStore from '@/stores/conformance.js'; import ConformanceStore from '@/stores/conformance.js';
import PageAdminStore from '@/stores/pageAdmin.js';
import IconSearch from '@/components/icons/IconSearch.vue'; import IconSearch from '@/components/icons/IconSearch.vue';
import IconSetting from '@/components/icons/IconSetting.vue'; import IconSetting from '@/components/icons/IconSetting.vue';
import { saveFilter, savedSuccessfully, saveConformance } from '@/module/alertModal.js'; import { saveFilter, savedSuccessfully, saveConformance } from '@/module/alertModal.js';
@@ -68,9 +75,19 @@ export default {
const allMapDataStore = AllMapDataStore(); const allMapDataStore = AllMapDataStore();
const conformanceStore = ConformanceStore(); const conformanceStore = ConformanceStore();
const { logId, tempFilterId, createFilterId, filterName, postRuleData, isUpdataFilter } = storeToRefs(allMapDataStore); const { logId, tempFilterId, createFilterId, filterName, postRuleData, isUpdataFilter } = storeToRefs(allMapDataStore);
const { conformanceRuleData, conformanceLogId, conformanceFilterId, conformanceLogTempCheckId, conformanceFilterTempCheckId, conformanceLogCreateCheckId, conformanceFilterCreateCheckId, isUpdataConformance, conformanceFileName } = storeToRefs(conformanceStore); 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 } return {
store, allMapDataStore, logId, tempFilterId, createFilterId,
filterName, postRuleData, isUpdataFilter, conformanceStore, conformanceRuleData,
conformanceLogId, conformanceFilterId, conformanceLogTempCheckId,
conformanceFilterTempCheckId, conformanceLogCreateCheckId,
conformanceFilterCreateCheckId, isUpdataConformance, conformanceFileName,
};
}, },
components: { components: {
IconSearch, IconSearch,
@@ -90,7 +107,6 @@ export default {
COMPARE: ['DASHBOARD'] COMPARE: ['DASHBOARD']
}, },
navViewName: 'FILES', navViewName: 'FILES',
isActive: null,
uploadModal: false, uploadModal: false,
}; };
}, },
@@ -113,8 +129,9 @@ export default {
return result; return result;
}, },
noShowSaveButton: function() { noShowSaveButton: function() {
return this.navViewName === 'UPLOAD' || this.navViewName === 'COMPARE' || this.isActive === 'PERFORMANCE' ? true : false; return this.navViewName === 'UPLOAD' || this.navViewName === 'COMPARE' || this.activePage === 'PERFORMANCE' ? true : false;
} },
...mapState(PageAdminStore, ['activePage', 'pendingActivePage']),
}, },
watch: { watch: {
'$route':'getNavViewName', '$route':'getNavViewName',
@@ -136,18 +153,20 @@ export default {
let type; let type;
let fileId; let fileId;
let isCheckPage; let isCheckPage;
const navItemCandidate = event.target.innerText;
this.setPendingActivePage(navItemCandidate);
this.isActive = event.target.innerText;
switch (this.navViewName) { switch (this.navViewName) {
case 'FILES': case 'FILES':
this.store.filesTag = event.target.innerText; this.store.filesTag = navItemCandidate;
break; break;
case 'DISCOVER': case 'DISCOVER':
type = this.$route.params.type; type = this.$route.params.type;
fileId = this.$route.params.fileId; fileId = this.$route.params.fileId;
isCheckPage = this.$route.name.includes('Check'); isCheckPage = this.$route.name.includes('Check');
switch (event.target.innerText) { switch (navItemCandidate) {
case 'MAP': case 'MAP':
if(isCheckPage) this.$router.push({name: 'CheckMap', params: { type: type, fileId: fileId }}); if(isCheckPage) this.$router.push({name: 'CheckMap', params: { type: type, fileId: fileId }});
else this.$router.push({name: 'Map', params: { type: type, fileId: fileId }}); else this.$router.push({name: 'Map', params: { type: type, fileId: fileId }});
@@ -166,40 +185,52 @@ export default {
break break
} }
}, },
/**
* Based on the route.name, decide the navViewName.
* @returns {string} the string of navigation name to return
*/
getNavViewName() { getNavViewName() {
let name = this.$route.name;
if(this.$route.name === 'NotFound404') return; let name = this.$route.name;
let valueToSet;
if(this.$route.name === 'NotFound404') {
return;
}
this.navViewName = this.$route.matched[1].name.toUpperCase(); this.navViewName = this.$route.matched[1].name.toUpperCase();
this.store.filesTag = 'ALL'; this.store.filesTag = 'ALL';
switch (this.navViewName) { switch (this.navViewName) {
case 'FILES': case 'FILES':
this.isActive = this.store.filesTag; valueToSet = this.navItemCandidate;
break; break;
case 'DISCOVER': case 'DISCOVER':
switch (name) { switch (name) {
case 'Map': case 'Map':
case 'CheckMap': case 'CheckMap':
this.isActive = 'MAP'; valueToSet = 'MAP';
break; break;
case 'Conformance': case 'Conformance':
case 'CheckConformance': case 'CheckConformance':
this.isActive = 'CONFORMANCE'; valueToSet = 'CONFORMANCE';
break; break;
case 'Performanc': case 'Performanc':
case 'CheckPerformanc': case 'CheckPerformanc':
this.isActive = 'PERFORMANCE'; valueToSet = 'PERFORMANCE';
break; break;
} }
break; break;
case 'COMPARE': case 'COMPARE':
switch(name) { switch(name) {
case 'CompareDashboard': case 'CompareDashboard':
this.isActive = 'DASHBOARD' valueToSet = 'DASHBOARD';
break; break;
} }
break; break;
} }
this.setPendingActivePage(valueToSet);
return valueToSet;
}, },
/** /**
* Save button' modal * Save button' modal
@@ -217,18 +248,24 @@ export default {
// 沒有 filter Id, 有暫存 tempFilterId Id 可以另存新檔 // 沒有 filter Id, 有暫存 tempFilterId Id 可以另存新檔
if(this.createFilterId) { if(this.createFilterId) {
await this.allMapDataStore.updataFilter(); await this.allMapDataStore.updataFilter();
if(this.isUpdataFilter) await savedSuccessfully(this.filterName); if(this.isUpdataFilter) {
await savedSuccessfully(this.filterName);
}
}else if(this.logId){ }else if(this.logId){
isSaved = await saveFilter(this.allMapDataStore.addFilterId); isSaved = await saveFilter(this.allMapDataStore.addFilterId);
// 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由 // 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) await this.$router.push(`/discover/filter/${this.createFilterId}/map`); if(isSaved) {
await this.$router.push(`/discover/filter/${this.createFilterId}/map`);
}
}; };
break; break;
case 'CheckMap': case 'CheckMap':
// 無論 parentLog, parentFilter做新 filter 皆另存新檔 // 無論 parentLog, parentFilter做新 filter 皆另存新檔
isSaved = await saveFilter(this.allMapDataStore.addFilterId); isSaved = await saveFilter(this.allMapDataStore.addFilterId);
// 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由 // 存檔後為 filterID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) await this.$router.push(`/discover/filter/${this.createFilterId}/map`); if(isSaved) {
await this.$router.push(`/discover/filter/${this.createFilterId}/map`);
}
break; break;
case 'Conformance': case 'Conformance':
case 'CheckConformance': case 'CheckConformance':
@@ -236,18 +273,25 @@ export default {
// 沒有 check Id, 有暫存 temp Id 可以另存新檔 // 沒有 check Id, 有暫存 temp Id 可以另存新檔
if(this.conformanceFilterCreateCheckId || this.conformanceLogCreateCheckId){ if(this.conformanceFilterCreateCheckId || this.conformanceLogCreateCheckId){
await this.conformanceStore.updataConformance(); await this.conformanceStore.updataConformance();
if(this.isUpdataConformance) await savedSuccessfully(this.conformanceFileName); if(this.isUpdataConformance) {
await savedSuccessfully(this.conformanceFileName);
}
} else { } else {
isSaved = await saveConformance(this.conformanceStore.addConformanceCreateCheckId); isSaved = await saveConformance(this.conformanceStore.addConformanceCreateCheckId);
// 存檔後為 checkID換網址不跳頁使用 push 記錄歷史路由 // 存檔後為 checkID換網址不跳頁使用 push 記錄歷史路由
if(isSaved) { if(isSaved) {
if(this.conformanceLogId) await this.$router.push(`/discover/conformance/log/${this.conformanceLogCreateCheckId}/conformance`); if(this.conformanceLogId) {
else if(this.conformanceFilterId) await this.$router.push(`/discover/conformance/filter/${this.conformanceFilterCreateCheckId}/conformance`); await this.$router.push(`/discover/conformance/log/${this.conformanceLogCreateCheckId}/conformance`);
}
else if(this.conformanceFilterId) {
await this.$router.push(`/discover/conformance/filter/${this.conformanceFilterCreateCheckId}/conformance`);
}
} }
} }
break; break;
} }
} },
...mapActions(PageAdminStore, ['setPendingActivePage', ],),
}, },
} }
</script> </script>

View File

@@ -2,6 +2,7 @@ import Swal from 'sweetalert2';
import AllMapDataStore from '@/stores/allMapData.js'; import AllMapDataStore from '@/stores/allMapData.js';
import ConformanceStore from '@/stores/conformance.js'; import ConformanceStore from '@/stores/conformance.js';
import FilesStore from '@/stores/files.js'; import FilesStore from '@/stores/files.js';
import PageAdminStore from '@/stores/pageAdmin.js';
const customClass = { const customClass = {
container: '!z-[99999]', container: '!z-[99999]',
@@ -78,6 +79,8 @@ export async function savedSuccessfully(value) {
*/ */
export async function leaveFilter(next, addFilterId, toPath, logOut) { export async function leaveFilter(next, addFilterId, toPath, logOut) {
const allMapDataStore = AllMapDataStore(); const allMapDataStore = AllMapDataStore();
const pageAdminStore = PageAdminStore();
const result = await Swal.fire({ const result = await Swal.fire({
title: 'SAVE YOUR FILTER?', title: 'SAVE YOUR FILTER?',
html: 'If you want to continue using this filter in any other page, please select [Yes].', html: 'If you want to continue using this filter in any other page, please select [Yes].',
@@ -89,22 +92,38 @@ export async function leaveFilter(next, addFilterId, toPath, logOut) {
showCancelButton: true, showCancelButton: true,
cancelButtonText: 'No', cancelButtonText: 'No',
cancelButtonColor: '#94a3b8', cancelButtonColor: '#94a3b8',
customClass: customClass customClass: customClass,
}) });
if(result.isConfirmed) { if(result.isConfirmed) {
if(allMapDataStore.createFilterId) { if(allMapDataStore.createFilterId) {
await allMapDataStore.updataFilter(); await allMapDataStore.updataFilter();
if(allMapDataStore.isUpdataFilter) await savedSuccessfully(allMapDataStore.filterName); if(allMapDataStore.isUpdataFilter) {
await savedSuccessfully(allMapDataStore.filterName);
}
} else { } else {
await saveFilter(addFilterId); await saveFilter(addFilterId);
} }
// Handle page admin issue
pageAdminStore.copyPendingPageToActivePage();
logOut ? logOut() : next(toPath); logOut ? logOut() : next(toPath);
} else if(result.dismiss === 'cancel') { } else if(result.dismiss === 'cancel') {
// Handle page admin issue
pageAdminStore.keepPreviousPage();
allMapDataStore.tempFilterId = null; allMapDataStore.tempFilterId = null;
logOut ? logOut() : next(toPath); logOut ? logOut() : next(toPath);
} else if(result.dismiss === 'backdrop') { } else if(result.dismiss === 'backdrop') {
// Handle page admin issue
pageAdminStore.keepPreviousPage();
logOut ? null : next(false); logOut ? null : next(false);
} }
// In any cases, execute the following
pageAdminStore.clearPendingActivePage();
}; };
/** /**
* Conformance Saved * Conformance Saved

73
src/stores/pageAdmin.js Normal file
View File

@@ -0,0 +1,73 @@
import { defineStore } from "pinia";
export default defineStore('pageAdminStore', {
state: () => ({
activePage: 'FILES',
activeSubPage: 'ALL',
previousPage: 'FILES',
previousSubPage: 'ALL',
pendingActivePage: '',
pendingActiveSubPage: '',
isPending: false,
}),
getters: {
},
actions: {
/**
* Set Active Page; the page which the user is currently visiting
* @param {string} activePage
* @param {string} activeSubPage
*/
setActivePage(activePage, activeSubpage) {
console.log("setActivePage:", activePage, activeSubPage);
this.activePage = activePage;
this.activeSubPage = activeSubPage;
},
/**
* Set the previous(usually current) page because the user might change her mind when navigating.
* @param {string} previoiusPage
* @param {string} previoiusSubPage
*/
setPrevioiusPage(previoiusPage, previousSubPage) {
this.previoiusPage = previoiusPage;
this.previoiusSubPage = previousSubPage;
},
/**
* Copy the value of pendingActivePage to activePage
*/
copyPendingPageToActivePage() {
console.log("Copy the value of pendingActivePage to activePage\nCopying:", this.pendingActivePage, this.pendingActiveSubPage)
this.activePage = this.pendingActivePage;
this.activeSubPage = this.pendingActiveSubPage;
},
/**
* Set Pending active Page, meaning we are not sure if user will chang her mind later on.
* Also, start pending state.
* Often, user triggers the modal and the pending state starts.
* @param {string} pendingActivePage
*/
setPendingActivePage(argPendingActivePage, argPendingActiveSubPage) {
this.pendingActivePage = argPendingActivePage;
this.pendingActiveSubPage = argPendingActiveSubPage;
this.isPending = true;
},
/**
* Set Pending active Page to empty string; we call this right after we just decide an activePage.
* Also, stop pending state.
*/
clearPendingActivePage(){
this.pendingActivePage = '';
this.pendingActiveSubPage = '';
this.isPending = false;
},
/**
* When user dismiss the popup modal, we don't apply the new page,
* instead, we apply the previous page.
*/
keepPreviousPage() {
this.activePage = this.previousPage;
this.activeSubPage = this.previousSubPage;
this.isPending = false;
}
},
})

View File

@@ -89,7 +89,9 @@ export default {
*/ */
changeHandler(event) { changeHandler(event) {
let inputValue = event.target.value; let inputValue = event.target.value;
if(inputValue !== '') this.isInvalid = false; if(inputValue !== '') {
this.isInvalid = false;
}
}, },
}, },
}; };

View File

@@ -10,7 +10,7 @@
</template> </template>
<script> <script>
import { storeToRefs } from 'pinia'; import { storeToRefs, mapActions, } from 'pinia';
import LoadingStore from '@/stores/loading.js'; import LoadingStore from '@/stores/loading.js';
import AllMapDataStore from '@/stores/allMapData.js'; import AllMapDataStore from '@/stores/allMapData.js';
import ConformanceStore from '@/stores/conformance.js'; import ConformanceStore from '@/stores/conformance.js';
@@ -18,6 +18,7 @@ import Header from "@/components/Header.vue";
import Navbar from "@/components/Navbar.vue"; import Navbar from "@/components/Navbar.vue";
import Loading from '@/components/Loading.vue'; import Loading from '@/components/Loading.vue';
import { leaveFilter, leaveConformance } from '@/module/alertModal.js'; import { leaveFilter, leaveConformance } from '@/module/alertModal.js';
import PageAdminStore from '@/stores/pageAdmin.js';
export default { export default {
name: 'MainContainer', name: 'MainContainer',
@@ -28,13 +29,21 @@ export default {
const { tempFilterId, createFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore); const { tempFilterId, createFilterId, temporaryData, postRuleData, ruleData } = storeToRefs(allMapDataStore);
const { conformanceLogTempCheckId, conformanceFilterTempCheckId } = storeToRefs(conformanceStore); const { conformanceLogTempCheckId, conformanceFilterTempCheckId } = storeToRefs(conformanceStore);
return { loadingStore, temporaryData, tempFilterId, createFilterId, postRuleData, ruleData, conformanceLogTempCheckId, conformanceFilterTempCheckId, allMapDataStore, conformanceStore }; return {
loadingStore, temporaryData, tempFilterId,
createFilterId, postRuleData, ruleData,
conformanceLogTempCheckId, conformanceFilterTempCheckId,
allMapDataStore, conformanceStore,
};
}, },
components: { components: {
Header, Header,
Navbar, Navbar,
Loading Loading
}, },
methods: {
...mapActions(PageAdminStore, ['copyPendingPageToActivePage',],),
},
created() { created() {
// Save token in Headers. // Save token in Headers.
const token = document.cookie.replace(/(?:(?:^|.*;\s*)luciaToken\s*\=\s*([^;]*).*$)|^.*$/, "$1"); const token = document.cookie.replace(/(?:(?:^|.*;\s*)luciaToken\s*\=\s*([^;]*).*$)|^.*$/, "$1");
@@ -46,9 +55,17 @@ export default {
// 傳給 Map通知 Sidebar 要關閉。 // 傳給 Map通知 Sidebar 要關閉。
this.$emitter.emit('leaveFilter', false); this.$emitter.emit('leaveFilter', false);
leaveFilter(next, this.allMapDataStore.addFilterId, to.path) leaveFilter(next, this.allMapDataStore.addFilterId, to.path)
} else if((this.$route.name === 'Conformance' || this.$route.name === 'CheckConformance') && (this.conformanceLogTempCheckId || this.conformanceFilterTempCheckId)) { } else if((this.$route.name === 'Conformance' || this.$route.name === 'CheckConformance')
&& (this.conformanceLogTempCheckId || this.conformanceFilterTempCheckId)) {
leaveConformance(next, this.conformanceStore.addConformanceCreateCheckId, to.path) leaveConformance(next, this.conformanceStore.addConformanceCreateCheckId, to.path)
} else next(); } else {
// In this else block:
// for those pages who don't need popup modals, we handle page administration right now.
// By calling the following code, we decide the next visiting page.
this.copyPendingPageToActivePage();
next();
};
}, },
}; };
</script> </script>