feature: remember node positions after refreshing pages
This commit is contained in:
@@ -8,6 +8,8 @@ export const MODAL_ACCT_EDIT = 'MODAL_ACCT_EDIT';
|
|||||||
export const MODAL_ACCT_INFO = 'MODAL_ACCT_INFO';
|
export const MODAL_ACCT_INFO = 'MODAL_ACCT_INFO';
|
||||||
export const MODAL_DELETE = 'MODAL_DELETE';
|
export const MODAL_DELETE = 'MODAL_DELETE';
|
||||||
|
|
||||||
|
export const SAVE_KEY_NAME = 'CYTOSCAPE_NODE_POSTITION';
|
||||||
|
|
||||||
export const JUST_CREATE_ACCOUNT_HOT_DURATION_MINS = 2;
|
export const JUST_CREATE_ACCOUNT_HOT_DURATION_MINS = 2;
|
||||||
|
|
||||||
export const knownLayoutChartOption = {
|
export const knownLayoutChartOption = {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import 'tippy.js/dist/tippy.css';
|
|||||||
import Gradient from 'javascript-color-gradient'; // 多個色階產生器
|
import Gradient from 'javascript-color-gradient'; // 多個色階產生器
|
||||||
import { getTimeLabel } from '@/module/timeLabel.js'; // 時間格式轉換器
|
import { getTimeLabel } from '@/module/timeLabel.js'; // 時間格式轉換器
|
||||||
import CytoscapeStore from '@/stores/cytoscapeStore';
|
import CytoscapeStore from '@/stores/cytoscapeStore';
|
||||||
|
import { SAVE_KEY_NAME } from '@/constants/constants.js';
|
||||||
|
|
||||||
|
|
||||||
cytoscape.use( dagre );
|
cytoscape.use( dagre );
|
||||||
|
|
||||||
@@ -227,19 +229,29 @@ export default function cytoscapeMap(mapData, dataLayerType, dataLayerOption, cu
|
|||||||
const cytoscapeStore = CytoscapeStore();
|
const cytoscapeStore = CytoscapeStore();
|
||||||
|
|
||||||
cy.ready(() => {
|
cy.ready(() => {
|
||||||
cytoscapeStore.nodePositions.forEach(pos => {
|
cytoscapeStore.loadPositionsFromStorage();
|
||||||
const node = cy.getElementById(pos.id);
|
// 判斷localStorage是否儲存過拜訪資訊
|
||||||
if (node) {
|
// 若曾經儲存過拜訪後的座標位置,則restore位置來渲染出來
|
||||||
node.position(pos.position);
|
if(localStorage.getItem(SAVE_KEY_NAME) && JSON.parse(localStorage.getItem(SAVE_KEY_NAME))) {
|
||||||
}
|
const allGraphsRemembered = JSON.parse(localStorage.getItem(SAVE_KEY_NAME));
|
||||||
|
const currentGraphNodesRemembered = allGraphsRemembered[cytoscapeStore.currentGraphId];
|
||||||
|
currentGraphNodesRemembered.forEach(nodeRemembered => {
|
||||||
|
const nodeToDecide = cy.getElementById(nodeRemembered.id);
|
||||||
|
if (nodeToDecide) {
|
||||||
|
nodeToDecide.position(nodeRemembered.position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//存下此刻剛進入畫面時當前所有節點的座標位置
|
||||||
|
const allNodes = cy.nodes();
|
||||||
|
allNodes.map(nodeFirstlySave => {
|
||||||
|
cytoscapeStore.saveNodePosition(nodeFirstlySave.id(), nodeFirstlySave.position);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 在改變節點位置後,盡可能地記錄節點線條的位置情報
|
// 在改變節點位置後,盡可能地記錄節點線條的位置情報
|
||||||
cy.on('dragfree', 'node', (event) => {
|
cy.on('dragfree', 'node', (event) => {
|
||||||
const node = event.target;
|
const nodeToSave = event.target;
|
||||||
const position = node.position();
|
cytoscapeStore.saveNodePosition(nodeToSave.id(), nodeToSave.position());
|
||||||
cytoscapeStore.saveNodePosition(node.id(), position);
|
|
||||||
cytoscapeStore.savePositionsToStorage();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,60 +1,51 @@
|
|||||||
|
import { el } from 'date-fns/locale';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
// interface NodePosition {
|
import { SAVE_KEY_NAME } from '@/constants/constants.js';
|
||||||
// id: string;
|
import { printObject } from '@/utils/jsUtils';
|
||||||
// position: { x: number; y: number };
|
|
||||||
// graphId: string;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default defineStore('useCytoscapeStore', {
|
export default defineStore('useCytoscapeStore', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
nodePositions: [],
|
nodePositions: {},
|
||||||
currentGraphId: "",
|
currentGraphId: "",
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
/**
|
||||||
* 儲存或更新單個節點的位置資訊。
|
* 儲存或更新單個節點的位置資訊。
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {object} position {x, y}
|
* @param {object} position {x, y} position有兩個值,x與y
|
||||||
* @param {string} graphId
|
|
||||||
*/
|
*/
|
||||||
saveNodePosition(id, position) {
|
saveNodePosition(nodeId, position) {
|
||||||
const existingNode = this.nodePositions.find(node => node.id === id && node.graphId === this.currentGraphId);
|
// 若是資訊曾經存在這張圖於localStorage中
|
||||||
if (existingNode) { // 如果存在,更新位置資訊
|
if (localStorage.getItem(SAVE_KEY_NAME) && JSON.parse(localStorage.getItem(SAVE_KEY_NAME))[this.currentGraphId]) {
|
||||||
existingNode.position = position;
|
const nodeToSave = this.nodePositions[this.currentGraphId].find(node => node.id === nodeId);
|
||||||
} else { // 如果不存在,新增一個新的位置資訊
|
if(nodeToSave) {
|
||||||
this.nodePositions.push({
|
nodeToSave.position = position;
|
||||||
id,
|
} else {
|
||||||
position,
|
this.nodePositions[this.currentGraphId] = [... this.nodePositions[this.currentGraphId],
|
||||||
graphId: this.currentGraphId,
|
{id: nodeId, position: position}]
|
||||||
});
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
this.savePositionsToStorage();
|
||||||
/**
|
|
||||||
* 根據節點 ID 獲取該節點的位置資訊
|
|
||||||
* @param {string} id
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
getNodePosition(id) { // 返回該節點的位置資訊,如果不存在則返回 undefined
|
|
||||||
return this.nodePositions.find(node => node.id === id)?.position;
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 從本地存儲中加載節點位置資訊。
|
* 從本地存儲中加載節點位置資訊。
|
||||||
*/
|
*/
|
||||||
loadPositionsFromStorage() {
|
loadPositionsFromStorage() {
|
||||||
const storedPositions = localStorage.getItem('cy-node-positions');
|
if (localStorage.getItem(SAVE_KEY_NAME)) {
|
||||||
if (storedPositions) {
|
this.nodePositions[this.currentGraphId] = JSON.parse(localStorage.getItem(SAVE_KEY_NAME))[this.currentGraphId];
|
||||||
this.nodePositions = JSON.parse(storedPositions);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 將節點位置資訊儲存到本地存儲中。
|
* 將節點位置資訊儲存到本地存儲中。
|
||||||
*/
|
*/
|
||||||
savePositionsToStorage() {
|
savePositionsToStorage() {
|
||||||
localStorage.setItem('cy-node-positions', JSON.stringify(this.nodePositions));
|
localStorage.setItem(SAVE_KEY_NAME, JSON.stringify(this.nodePositions));
|
||||||
},
|
},
|
||||||
setCurrentGraphId(currentGraphId) {
|
setCurrentGraphId(currentGraphId) {
|
||||||
this.currentGraphId = currentGraphId;
|
this.currentGraphId = currentGraphId;
|
||||||
|
this.nodePositions[currentGraphId] = [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
15
src/utils/jsUtils.js
Normal file
15
src/utils/jsUtils.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export const printObject = (obj, indent = 0) => {
|
||||||
|
const padding = ' '.repeat(indent);
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (obj.hasOwnProperty(key)) {
|
||||||
|
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||||
|
console.log(`${padding}${key}: {`);
|
||||||
|
printObject(obj[key], indent + 2);
|
||||||
|
console.log(`${padding}}`);
|
||||||
|
} else {
|
||||||
|
console.log(`${padding}${key}: ${obj[key]}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -110,7 +110,7 @@ export default {
|
|||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
const loginStore = LoginStore();
|
const loginStore = LoginStore();
|
||||||
|
|
||||||
if (!getCookie("isLuciaLoggedIn")) {
|
if (!getCookie("isLuciaLoggedIn")) { //這裡不要用pinia的isLoggedIn來檢查,因為會有重新整理時撈不到Persisted value的值的bug
|
||||||
if (getCookie('luciaRefreshToken')) {
|
if (getCookie('luciaRefreshToken')) {
|
||||||
await loginStore.refreshToken();
|
await loginStore.refreshToken();
|
||||||
loginStore.setIsLoggedIn(true);
|
loginStore.setIsLoggedIn(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user