fix: dotted solid edge style bug

This commit is contained in:
Cindy Chang
2024-09-05 17:49:01 +08:00
parent 8635c8d3e2
commit 5b3c0050b9
3 changed files with 370 additions and 353 deletions

View File

@@ -14,288 +14,287 @@ const ImgCapsulesGlow = [ImgCapsuleGlow1, ImgCapsuleGlow2, ImgCapsuleGlow3, ImgC
const ImgCapsules = [ImgCapsule1, ImgCapsule2, ImgCapsule3, ImgCapsule4];
export default defineStore('useMapPathStore', {
state: () => ({
clickedPath: [],
insights: {},
insightWithPath: {},
cytoscape: {
process:
{
curved:{
horizontal:null,
vertical:null,
},
elbow:{
horizontal:null,
vertical:null,
}
},
bpmn: {
curved:{
horizontal:null,
vertical:null,
},
elbow:{
horizontal:null,
vertical:null,
}
}
state: () => ({
clickedPath: [],
insights: {},
insightWithPath: {},
cytoscape: {
process:
{
curved: {
horizontal: null,
vertical: null,
},
processOrBPMN: 'process',
curveType: 'curved',
directionType: 'horizontal',
allPaths: [],
allPathsByEdge: [],
startNode: null,
mapGraphPathToInsight: {},
activeTrace: 0,
activeListIndex: 0,
lastClickedNode: null,
isBPMNOn: false,
}),
actions: {
async setCytoscape(cytoscape, processOrBPMN = 'process', curveType = 'curved', directionType = 'horizontal') {
this.processOrBPMN = processOrBPMN;
this.curveType = curveType;
this.directionType = directionType;
this.cytoscape[processOrBPMN][curveType][directionType] = cytoscape;
await this.createInsightWithPath();
if(processOrBPMN === 'process') {
await this.highlightMostFrequentPath();
}
elbow: {
horizontal: null,
vertical: null,
}
},
async createInsightWithPath() {
const { insights } = AllMapData();
this.insights = {...insights};
this.startNode = this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes()
.filter(function(elem) {
bpmn: {
curved: {
horizontal: null,
vertical: null,
},
elbow: {
horizontal: null,
vertical: null,
}
}
},
processOrBPMN: 'process',
curveType: 'curved',
directionType: 'horizontal',
allPaths: [],
allPathsByEdge: [],
startNode: null,
mapGraphPathToInsight: {},
activeTrace: 0,
activeListIndex: 0,
lastClickedNode: null,
isBPMNOn: false,
}),
actions: {
async setCytoscape(cytoscape, processOrBPMN = 'process', curveType = 'curved', directionType = 'horizontal') {
this.processOrBPMN = processOrBPMN;
this.curveType = curveType;
this.directionType = directionType;
this.cytoscape[processOrBPMN][curveType][directionType] = cytoscape;
await this.createInsightWithPath();
if (processOrBPMN === 'process') {
await this.highlightMostFrequentPath();
}
},
async createInsightWithPath() {
const { insights } = AllMapData();
this.insights = { ...insights };
this.startNode = this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes()
.filter(function (elem) {
return elem.data('label').toLocaleLowerCase() === 'start';
});
for(let i = 0; i < INSIGHTS_FIELDS_AND_LABELS.length; i++) {
const curButton = this.insights[INSIGHTS_FIELDS_AND_LABELS[i][0]];
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]] = {}; // first layer index
for (let i = 0; i < INSIGHTS_FIELDS_AND_LABELS.length; i++) {
const curButton = this.insights[INSIGHTS_FIELDS_AND_LABELS[i][0]];
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]] = {}; // first layer index
for(let listIndex = 0; listIndex < curButton.length; listIndex++) {
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex] = {
edges: [],
nodes: [],
}; // second layer index
for (let listIndex = 0; listIndex < curButton.length; listIndex++) {
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex] = {
edges: [],
nodes: [],
}; // second layer index
let curGraphNode, prevGraphNode, curEdge; // 配對 curGraphNode 與 nodeIndex 指向的 node
for(let nodeIndex = 0; nodeIndex < curButton[listIndex].length; nodeIndex++){
if(nodeIndex === 0) { // special case, initialize curGraphNode
curGraphNode = this.startNode.outgoers('node').filter(neighborOfStart =>
neighborOfStart.data('label') === curButton[listIndex][nodeIndex]
let curGraphNode, prevGraphNode, curEdge; // 配對 curGraphNode 與 nodeIndex 指向的 node
for (let nodeIndex = 0; nodeIndex < curButton[listIndex].length; nodeIndex++) {
if (nodeIndex === 0) { // special case, initialize curGraphNode
curGraphNode = this.startNode.outgoers('node').filter(neighborOfStart =>
neighborOfStart.data('label') === curButton[listIndex][nodeIndex]
);
curEdge = this.startNode.edgesTo(curGraphNode);
} else {
if (prevGraphNode) {
curGraphNode = prevGraphNode.outgoers('node').filter(neighbor =>
neighbor.data('label') === curButton[listIndex][nodeIndex]
);
curEdge = this.startNode.edgesTo(curGraphNode);
} else {
if(prevGraphNode){
curGraphNode = prevGraphNode.outgoers('node').filter(neighbor =>
neighbor.data('label') === curButton[listIndex][nodeIndex]
);
curEdge = prevGraphNode.edgesWith(curGraphNode);
}
curEdge = prevGraphNode.edgesWith(curGraphNode);
}
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].nodes.push(curGraphNode);
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].edges.push(curEdge);
// 特殊狀況在for迴圈之外額外插入最後一條線段
if(nodeIndex === curButton[listIndex].length - 1){
const endNode = curGraphNode.outgoers('node').filter(neighbor =>
neighbor.data('label').toLocaleLowerCase() === 'end'
);
const lastEdge = curGraphNode.edgesWith(endNode);
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].edges.push(lastEdge);
}
prevGraphNode = curGraphNode;
}
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].nodes.push(curGraphNode);
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].edges.push(curEdge);
// 特殊狀況在for迴圈之外額外插入最後一條線段
if (nodeIndex === curButton[listIndex].length - 1) {
const endNode = curGraphNode.outgoers('node').filter(neighbor =>
neighbor.data('label').toLocaleLowerCase() === 'end'
);
const lastEdge = curGraphNode.edgesWith(endNode);
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[i][0]][listIndex].edges.push(lastEdge);
}
prevGraphNode = curGraphNode;
}
}
},
async createPaths() {
this.startNode = this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes()
.filter(function(elem) {
}
},
async createPaths() {
this.startNode = this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes()
.filter(function (elem) {
return elem.data('label').toLocaleLowerCase() === 'start';
});
// Depth First Search from the starting node
await this.depthFirstSearchCreatePath(this.startNode, [this.startNode], []);
const { insights } = AllMapData();
this.insights = {...insights};
await this.matchGraphPathWithInsightsPath();
},
/** 從start節點開始建立所有的path
* 於第二個參數逐漸推入節點,於第三個參數逐漸推入線段
*/
depthFirstSearchCreatePath(node, currentPathByNode, curPathByEdge){
const outgoingEdges = node.outgoers('edge');
if (outgoingEdges.length === 0) {
// 表示已經遇到尾聲
this.allPaths.push([...currentPathByNode]);
this.allPathsByEdge.push([...curPathByEdge])
} else {
outgoingEdges.targets().forEach((targetNode) => {
if (!currentPathByNode.includes(targetNode)) {
const connectingEdge = targetNode.edgesWith(currentPathByNode[currentPathByNode.length - 1]);
// 避免loop只有當目標節點不在當前路徑中之時才繼續
this.depthFirstSearchCreatePath(targetNode, [...currentPathByNode, targetNode],
[...curPathByEdge, connectingEdge]
);
}
});
}
},
/**
* 比對兩條Paths是否相等。
* 第一條path是透過depthFirstSearchCreatePath所建立
* 而第二條path是從後端給的insights物件而來其資料結構是簡單的array而已。
* 在每條path沿路據節點上的label之
* 字串來匹配這個path是屬於insights物件的哪一條path
* 其中用curButton去記憶住insights[INSIGHTS_FIELDS_AND_LABELS[i][0]]內文
* 而curButton[listIndex][nodeIndex]是用來確認是否跟depthFirstSearchCreatePath內的
* node.data('label')字串完全相等,也就是 activity 節點的文字
*/
matchGraphPathWithInsightsPath(){
for(let whichPath = 0; whichPath < this.allPaths.length; whichPath++) {
const curPath = this.allPaths[whichPath];
const curPathByEdge = this.allPathsByEdge[whichPath];
// 針對這個path的第一個節點找到它在insights中是對應到哪一個起點
for(let i = 0; i < INSIGHTS_FIELDS_AND_LABELS.length; i++) {
const curButton = this.insights[INSIGHTS_FIELDS_AND_LABELS[i][0]];
for(let listIndex = 0; listIndex < curButton.length; listIndex++) {
for(let nodeIndex = 0; nodeIndex < curButton[listIndex].length; nodeIndex++){
if(curPath[1].data('label') === curButton[listIndex][nodeIndex]){
// 從 1 開始而不是從 0 開始是因為 0 的label是start字串
const matchResult = this.depthFirstSearchMatchTwoPaths(curPath, 1, curButton, listIndex, nodeIndex)
if(matchResult){
this.mapGraphPathToInsight[i] = {
[listIndex] : {
pathByNode: [...curPath],
pathByEdge: [...curPathByEdge],
pathType: INSIGHTS_FIELDS_AND_LABELS[i][0],
}
// Depth First Search from the starting node
await this.depthFirstSearchCreatePath(this.startNode, [this.startNode], []);
const { insights } = AllMapData();
this.insights = { ...insights };
await this.matchGraphPathWithInsightsPath();
},
/** 從start節點開始建立所有的path
* 於第二個參數逐漸推入節點,於第三個參數逐漸推入線段
*/
depthFirstSearchCreatePath(node, currentPathByNode, curPathByEdge) {
const outgoingEdges = node.outgoers('edge');
if (outgoingEdges.length === 0) {
// 表示已經遇到尾聲
this.allPaths.push([...currentPathByNode]);
this.allPathsByEdge.push([...curPathByEdge])
} else {
outgoingEdges.targets().forEach((targetNode) => {
if (!currentPathByNode.includes(targetNode)) {
const connectingEdge = targetNode.edgesWith(currentPathByNode[currentPathByNode.length - 1]);
// 避免loop只有當目標節點不在當前路徑中之時才繼續
this.depthFirstSearchCreatePath(targetNode, [...currentPathByNode, targetNode],
[...curPathByEdge, connectingEdge]
);
}
});
}
},
/**
* 比對兩條Paths是否相等。
* 第一條path是透過depthFirstSearchCreatePath所建立
* 而第二條path是從後端給的insights物件而來其資料結構是簡單的array而已。
* 在每條path沿路據節點上的label之
* 字串來匹配這個path是屬於insights物件的哪一條path
* 其中用curButton去記憶住insights[INSIGHTS_FIELDS_AND_LABELS[i][0]]內文
* 而curButton[listIndex][nodeIndex]是用來確認是否跟depthFirstSearchCreatePath內的
* node.data('label')字串完全相等,也就是 activity 節點的文字
*/
matchGraphPathWithInsightsPath() {
for (let whichPath = 0; whichPath < this.allPaths.length; whichPath++) {
const curPath = this.allPaths[whichPath];
const curPathByEdge = this.allPathsByEdge[whichPath];
// 針對這個path的第一個節點找到它在insights中是對應到哪一個起點
for (let i = 0; i < INSIGHTS_FIELDS_AND_LABELS.length; i++) {
const curButton = this.insights[INSIGHTS_FIELDS_AND_LABELS[i][0]];
for (let listIndex = 0; listIndex < curButton.length; listIndex++) {
for (let nodeIndex = 0; nodeIndex < curButton[listIndex].length; nodeIndex++) {
if (curPath[1].data('label') === curButton[listIndex][nodeIndex]) {
// 從 1 開始而不是從 0 開始是因為 0 的label是start字串
const matchResult = this.depthFirstSearchMatchTwoPaths(curPath, 1, curButton, listIndex, nodeIndex)
if (matchResult) {
this.mapGraphPathToInsight[i] = {
[listIndex]: {
pathByNode: [...curPath],
pathByEdge: [...curPathByEdge],
pathType: INSIGHTS_FIELDS_AND_LABELS[i][0],
}
} // end if
}
} // end fourth for
} // end third for
} // end second for
} // end first for
},
depthFirstSearchMatchTwoPaths(curPath, curPathIndex, curButton, listIndex, nodeIndex){
if(listIndex >= curButton.length) { // 邊界條件檢查,防止超出範圍
return; // nodeIndex表示是當選訂了五顆按鈕之一之後清單上的第幾個path
}
} // end if
}
} // end fourth for
} // end third for
} // end second for
} // end first for
},
depthFirstSearchMatchTwoPaths(curPath, curPathIndex, curButton, listIndex, nodeIndex) {
if (listIndex >= curButton.length) { // 邊界條件檢查,防止超出範圍
return; // nodeIndex表示是當選訂了五顆按鈕之一之後清單上的第幾個path
}
if (nodeIndex >= curButton[listIndex]) { // 邊界條件檢查,防止超出範圍
return; // 表示清單上這個path上的第幾個節點
}
// 如果 `curPath` 和 `curButton[listIndex]` 完全匹配
if (curPathIndex === curPath.length || nodeIndex === curButton[listIndex].length) {
return true;
}
// 邊界條件檢查,防止超出範圍
if (curPathIndex >= curPath.length || nodeIndex >= curButton[listIndex].length) {
return;
}
const nodeLabel = curPath[curPathIndex].data('label');
// 如果當前節點匹配
if (nodeLabel === curButton[listIndex][nodeIndex]) {
if (nodeIndex === curButton[listIndex].length - 1) {
return true; // Reach
}
if(nodeIndex >= curButton[listIndex]) { // 邊界條件檢查,防止超出範圍
return; // 表示清單上這個path上的第幾個節點
}
// 如果 `curPath` 和 `curButton[listIndex]` 完全匹配
if (curPathIndex === curPath.length || nodeIndex === curButton[listIndex].length) {
//從以下兩個選項選出答案可能是true的。但也可能答案都是false
// 選項一是遞增insights的第一層的指標。這裡必須遞增path的指標
if (this.depthFirstSearchMatchTwoPaths(curPath, curPathIndex + 1, curButton, listIndex + 1, nodeIndex)) {
return true;
}
// 邊界條件檢查,防止超出範圍
if (curPathIndex >= curPath.length || nodeIndex >= curButton[listIndex].length) {
return;
// 選項二是遞增insights的第一層的指標。這裡必須遞增path的指標
if (this.depthFirstSearchMatchTwoPaths(curPath, curPathIndex + 1, curButton, listIndex, nodeIndex + 1)) {
return true;
}
const nodeLabel = curPath[curPathIndex].data('label');
// 如果當前節點匹配
if (nodeLabel === curButton[listIndex][nodeIndex]) {
if(nodeIndex === curButton[listIndex].length - 1) {
return true; // Reach
}
//從以下兩個選項選出答案可能是true的。但也可能答案都是false
// 選項一是遞增insights的第一層的指標。這裡必須遞增path的指標
if(this.depthFirstSearchMatchTwoPaths(curPath, curPathIndex + 1, curButton, listIndex + 1, nodeIndex)) {
return true;
}
// 選項二是遞增insights的第一層的指標。這裡必須遞增path的指標
if(this.depthFirstSearchMatchTwoPaths(curPath, curPathIndex + 1, curButton, listIndex, nodeIndex + 1)) {
return true;
}
}
return false; // 當前節點不匹配時返回 false
},
highlightClickedPath(clickedActiveTraceIndex: number, clickedPathListIndex: number){
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[clickedActiveTraceIndex][0]][clickedPathListIndex].edges.forEach(edgeToHighlight => {
edgeToHighlight.addClass('highlight-edge');
});
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[clickedActiveTraceIndex][0]][clickedPathListIndex].nodes.forEach(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
},
highlightClickedPathUnused(clickedActiveTraceIndex: number, clickedPathListIndex: number) {
this.activeTrace = clickedActiveTraceIndex;
this.activeListIndex = clickedPathListIndex;
this.mapGraphPathToInsight[clickedActiveTraceIndex][clickedPathListIndex].pathByEdge
.forEach(pathToHighlight => {
pathToHighlight.addClass('highlight-edge');
});
this.mapGraphPathToInsight[clickedActiveTraceIndex][clickedPathListIndex].pathByNode
.forEach(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
})
},
clearAllHighlight() {
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.edges().removeClass('highlight-edge');
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes().removeClass('highlight-node');
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes().forEach(nodeToReset => {
nodeToReset.data('nodeImageUrl', ImgCapsules[nodeToReset.data('level')])
});
},
onNodeClickHighlightEdges(clickedNode) {
this.clearAllHighlight();
clickedNode.addClass('highlight-node');
clickedNode.data('nodeImageUrl', ImgCapsulesGlow[clickedNode.data('level')]);
clickedNode.outgoers('edge').forEach(edgeToHighlight => edgeToHighlight.addClass('highlight-edge'));
clickedNode.incomers('edge').forEach(edgeToHighlight => edgeToHighlight.addClass('highlight-edge'));
this.lastClickedNode = clickedNode;
},
onEdgeClickHighlightNodes(clickedEdge) {
this.clearAllHighlight();
const sourceNode = clickedEdge.source();
const targetNode = clickedEdge.target();
sourceNode.addClass('highlight-node');
targetNode.addClass('highlight-node');
sourceNode.data('nodeImageUrl', ImgCapsulesGlow[sourceNode.data('level')]);
targetNode.data('nodeImageUrl', ImgCapsulesGlow[targetNode.data('level')]);
clickedEdge.addClass('highlight-edge');
},
async highlightMostFrequentPath() {
console.log('highlightMostFrequentPath', this.insightWithPath['most_freq_traces'][0]);
const LIST_INDEX = 0;
this.insightWithPath['most_freq_traces'][LIST_INDEX].nodes.map(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
this.insightWithPath['most_freq_traces'][LIST_INDEX].edges.map(edgeToHighlight =>
edgeToHighlight.addClass('highlight-edge'));
},
async highlightMostFrequentPathUnused() {
for(let buttonIter = 0; buttonIter < INSIGHTS_FIELDS_AND_LABELS.length; buttonIter++) {
// 有可能遇到兩個以上的most frequent paths然而我們只取一個path點亮
if (this.mapGraphPathToInsight[buttonIter]) {
const keyLength = Object.keys(this.mapGraphPathToInsight[buttonIter]).length;
for(let i = 0; i < keyLength; i++) {
if(this.mapGraphPathToInsight[buttonIter][i]?.pathType === 'most_freq_traces'){
await this.mapGraphPathToInsight[buttonIter][i].pathByNode.map(async(nodeToHighlight) => {
await nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
await this.mapGraphPathToInsight[buttonIter][i].pathByEdge.map(
async(edgeToHighlight) => {
await edgeToHighlight.addClass('highlight-edge');
});
return; // 之所以要此時就立刻return是因為要避免第二個以上的most freq path也被點亮
}
break;
}
}
}
},
setIsBPMNOn(isOn: boolean) {
this.isBPMNOn = isOn;
},
}
return false; // 當前節點不匹配時返回 false
},
highlightClickedPath(clickedActiveTraceIndex: number, clickedPathListIndex: number) {
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[clickedActiveTraceIndex][0]][clickedPathListIndex].edges.forEach(edgeToHighlight => {
edgeToHighlight.addClass('highlight-edge');
});
this.insightWithPath[INSIGHTS_FIELDS_AND_LABELS[clickedActiveTraceIndex][0]][clickedPathListIndex].nodes.forEach(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
},
highlightClickedPathUnused(clickedActiveTraceIndex: number, clickedPathListIndex: number) {
this.activeTrace = clickedActiveTraceIndex;
this.activeListIndex = clickedPathListIndex;
this.mapGraphPathToInsight[clickedActiveTraceIndex][clickedPathListIndex].pathByEdge
.forEach(pathToHighlight => {
pathToHighlight.addClass('highlight-edge');
});
this.mapGraphPathToInsight[clickedActiveTraceIndex][clickedPathListIndex].pathByNode
.forEach(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
})
},
clearAllHighlight() {
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.edges().removeClass('highlight-edge');
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes().removeClass('highlight-node');
this.cytoscape[this.processOrBPMN][this.curveType][this.directionType]?.nodes().forEach(nodeToReset => {
nodeToReset.data('nodeImageUrl', ImgCapsules[nodeToReset.data('level')])
});
},
onNodeClickHighlightEdges(clickedNode) {
this.clearAllHighlight();
clickedNode.addClass('highlight-node');
clickedNode.data('nodeImageUrl', ImgCapsulesGlow[clickedNode.data('level')]);
clickedNode.outgoers('edge').forEach(edgeToHighlight => edgeToHighlight.addClass('highlight-edge'));
clickedNode.incomers('edge').forEach(edgeToHighlight => edgeToHighlight.addClass('highlight-edge'));
this.lastClickedNode = clickedNode;
},
onEdgeClickHighlightNodes(clickedEdge) {
this.clearAllHighlight();
const sourceNode = clickedEdge.source();
const targetNode = clickedEdge.target();
sourceNode.addClass('highlight-node');
targetNode.addClass('highlight-node');
sourceNode.data('nodeImageUrl', ImgCapsulesGlow[sourceNode.data('level')]);
targetNode.data('nodeImageUrl', ImgCapsulesGlow[targetNode.data('level')]);
clickedEdge.addClass('highlight-edge');
},
async highlightMostFrequentPath() {
const LIST_INDEX = 0;
this.insightWithPath['most_freq_traces'][LIST_INDEX].nodes.map(nodeToHighlight => {
nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
this.insightWithPath['most_freq_traces'][LIST_INDEX].edges.map(edgeToHighlight =>
edgeToHighlight.addClass('highlight-edge'));
},
async highlightMostFrequentPathUnused() {
for (let buttonIter = 0; buttonIter < INSIGHTS_FIELDS_AND_LABELS.length; buttonIter++) {
// 有可能遇到兩個以上的most frequent paths然而我們只取一個path點亮
if (this.mapGraphPathToInsight[buttonIter]) {
const keyLength = Object.keys(this.mapGraphPathToInsight[buttonIter]).length;
for (let i = 0; i < keyLength; i++) {
if (this.mapGraphPathToInsight[buttonIter][i]?.pathType === 'most_freq_traces') {
await this.mapGraphPathToInsight[buttonIter][i].pathByNode.map(async (nodeToHighlight) => {
await nodeToHighlight.data('nodeImageUrl', ImgCapsulesGlow[nodeToHighlight.data('level')]);
});
await this.mapGraphPathToInsight[buttonIter][i].pathByEdge.map(
async (edgeToHighlight) => {
await edgeToHighlight.addClass('highlight-edge');
});
return; // 之所以要此時就立刻return是因為要避免第二個以上的most freq path也被點亮
}
break;
}
}
}
},
setIsBPMNOn(isOn: boolean) {
this.isBPMNOn = isOn;
},
},
});