Issue #165: Done.
This commit is contained in:
@@ -102,6 +102,9 @@ export default {
|
||||
await this.allMapDataStore.addTempFilterId();
|
||||
await this.allMapDataStore.getAllMapData();
|
||||
await this.allMapDataStore.getAllTrace(); // SidebarTrace 要連動
|
||||
if(this.temporaryData[0]?.type) {
|
||||
this.allMapDataStore.traceId = await this.allMapDataStore.traces[0]?.id;
|
||||
}
|
||||
await this.$emit('submit-all');
|
||||
this.isLoading = false;
|
||||
this.$toast.success('Filter(s) applied.');
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
<div id="cyTrace" ref="cyTrace" class="h-full min-w-full relative"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto overflow-x-auto scrollbar h-[calc(100%_-_264px)]">
|
||||
<DataTable :value="cases" showGridlines tableClass="text-sm" breakpoint="0">
|
||||
<div class="overflow-y-auto overflow-x-auto scrollbar h-[calc(100%_-_264px)] infiniteTable" @scroll="handleScroll">
|
||||
<DataTable :value="infiniteData" showGridlines tableClass="text-sm" breakpoint="0">
|
||||
<Column field="id" header="Case ID" ></Column>
|
||||
<Column field="started_at" header="Start time" ></Column>
|
||||
<Column field="completed_at" header="End time" ></Column>
|
||||
@@ -72,10 +72,10 @@ export default {
|
||||
setup() {
|
||||
const allMapDataStore = AllMapDataStore();
|
||||
const loadingStore = LoadingStore();
|
||||
const { traces, traceTaskSeq, cases } = storeToRefs(allMapDataStore);
|
||||
const { infinit404, infiniteStart, traces, traceTaskSeq, cases } = storeToRefs(allMapDataStore);
|
||||
const { isLoading } = storeToRefs(loadingStore);
|
||||
|
||||
return {allMapDataStore, traces, traceTaskSeq, cases, isLoading}
|
||||
return {allMapDataStore, infinit404, infiniteStart, traces, traceTaskSeq, cases, isLoading}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -84,6 +84,8 @@ export default {
|
||||
edges:[],
|
||||
},
|
||||
showTraceId: null,
|
||||
infinitMaxItems: false,
|
||||
infiniteData: [],
|
||||
chartOptions: null,
|
||||
selectArea: [0, 1]
|
||||
}
|
||||
@@ -136,7 +138,14 @@ export default {
|
||||
selectArea: function(newValue) {
|
||||
let roundValue = Math.round(newValue[1].toFixed());
|
||||
if(newValue[1] !== roundValue) this.selectArea[1] = roundValue;
|
||||
}
|
||||
},
|
||||
infinite404: function(newValue) {
|
||||
if(newValue === 404) this.infinitMaxItems = true;
|
||||
},
|
||||
showTraceId: function(newValue, oldValue) {
|
||||
let isScrollTop = document.querySelector('.infiniteTable');
|
||||
if(isScrollTop && typeof isScrollTop.scrollTop !== 'undefined') if(newValue !== oldValue) isScrollTop.scrollTop = 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -210,9 +219,12 @@ export default {
|
||||
*/
|
||||
async switchCaseData(id, count) {
|
||||
if(count >= 1000) this.isLoading = true;
|
||||
this.infinit404 = null;
|
||||
this.infinitMaxItems = false;
|
||||
this.showTraceId = id;
|
||||
this.infiniteStart = 0;
|
||||
this.allMapDataStore.traceId = id;
|
||||
await this.allMapDataStore.getTraceDetail();
|
||||
this.infiniteData = await this.allMapDataStore.getTraceDetail();
|
||||
this.createCy();
|
||||
this.isLoading = false;
|
||||
},
|
||||
@@ -265,6 +277,30 @@ export default {
|
||||
this.setEdgesData();
|
||||
cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
||||
},
|
||||
/**
|
||||
* 無限滾動: 監聽 scroll 有沒有滾到底部
|
||||
* @param {element} event
|
||||
*/
|
||||
handleScroll(event) {
|
||||
if(this.infinitMaxItems || this.cases.length < 20) return;
|
||||
|
||||
const container = event.target;
|
||||
const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight;
|
||||
|
||||
if(overScrollHeight) this.fetchData();
|
||||
},
|
||||
/**
|
||||
* 無限滾動: 滾到底後,要載入數據
|
||||
*/
|
||||
async fetchData() {
|
||||
try {
|
||||
this.infiniteStart += 20;
|
||||
await this.allMapDataStore.getTraceDetail();
|
||||
this.infiniteData = [...this.infiniteData, ...this.cases];
|
||||
} catch(error) {
|
||||
console.error('Failed to load data:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setNodesData();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Sidebar :visible="sidebarFilter" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" :baseZIndex="15" class="!w-11/12 !bg-neutral-100" @hide="hide()">
|
||||
<Sidebar :visible="sidebarFilter" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" :baseZIndex="15" class="!w-11/12 !bg-neutral-100">
|
||||
<template #header>
|
||||
<ul class="flex space-x-4">
|
||||
<li class="h1 border-r-2 border-neutral-300 pr-4 cursor-pointer hover:text-neutral-900 hover:duration-700" @click="switchTab('filter')" :class="tab === 'filter'? 'text-neutral-900': 'text-neutral-500'" id="tabFilter">Filter</li>
|
||||
@@ -498,10 +498,12 @@ export default {
|
||||
}
|
||||
break;
|
||||
case 'Trace': // Filter Type 選 Trace 的行為
|
||||
let lowerIndex = this.$refs.filterTraceView.selectArea[0];
|
||||
let upperIndex = this.$refs.filterTraceView.selectArea[1]-1;
|
||||
data = {
|
||||
type: 'trace-freq',
|
||||
lower: this.$refs.filterTraceView.selectArea[0]+1,
|
||||
upper: this.$refs.filterTraceView.selectArea[1],
|
||||
lower: this.allMapDataStore.traces[lowerIndex].id,
|
||||
upper: this.allMapDataStore.traces[upperIndex].id,
|
||||
is_exclude: isExclude,
|
||||
};
|
||||
break;
|
||||
@@ -552,14 +554,6 @@ export default {
|
||||
sumbitAll() {
|
||||
this.$emit('submit-all');
|
||||
},
|
||||
/**
|
||||
* hide map
|
||||
*/
|
||||
hide() {
|
||||
// 因 trace api 連動,所以關閉側邊欄時讓數值歸 1
|
||||
this.allMapDataStore.traceId = 1;
|
||||
this.allMapDataStore.getTraceDetail();
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Sidebar :visible="sidebarTraces" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" class="!w-11/12" @show="show()" @hide="hide()">
|
||||
<Sidebar :visible="sidebarTraces" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" class="!w-11/12" @show="show()">
|
||||
<template #header>
|
||||
<p class="h1">Traces</p>
|
||||
</template>
|
||||
@@ -41,8 +41,8 @@
|
||||
<div id="cyTrace" ref="cyTrace" class="h-full min-w-full relative"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto overflow-x-auto scrollbar h-[calc(100%_-_264px)]">
|
||||
<DataTable :value="cases" showGridlines tableClass="text-sm" breakpoint="0">
|
||||
<div class="overflow-y-auto overflow-x-auto scrollbar h-[calc(100%_-_264px)] infiniteTable" @scroll="handleScroll">
|
||||
<DataTable :value="infiniteData" showGridlines tableClass="text-sm" breakpoint="0">
|
||||
<Column field="id" header="Case ID" ></Column>
|
||||
<Column field="started_at" header="Start time" ></Column>
|
||||
<Column field="completed_at" header="End time" ></Column>
|
||||
@@ -52,21 +52,17 @@
|
||||
</div>
|
||||
</Sidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import AllMapDataStore from '@/stores/allMapData.js';
|
||||
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
sidebarTraces: Boolean,
|
||||
traces: Array,
|
||||
traceTaskSeq: Array,
|
||||
cases: Array,
|
||||
},
|
||||
props: ['sidebarTraces'],
|
||||
setup() {
|
||||
const allMapDataStore = AllMapDataStore();
|
||||
return {allMapDataStore}
|
||||
const { infinit404, infiniteStart, traceId, traces, traceTaskSeq, cases, infiniteFirstCases } = storeToRefs(allMapDataStore);
|
||||
return {allMapDataStore, infinit404, infiniteStart, traceId, traces, traceTaskSeq, cases, infiniteFirstCases}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -74,7 +70,9 @@ export default {
|
||||
nodes:[],
|
||||
edges:[],
|
||||
},
|
||||
showTraceId: 1,
|
||||
showTraceId: null,
|
||||
infinitMaxItems: false,
|
||||
infiniteData: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -93,7 +91,25 @@ export default {
|
||||
ratio: this.getPercentLabel(trace.count / sum),
|
||||
};
|
||||
}).sort((x, y) => x.id - y.id);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
infinite404: function(newValue) {
|
||||
if(newValue === 404) this.infinitMaxItems = true;
|
||||
},
|
||||
traceId: {
|
||||
handler(newValue) {
|
||||
this.showTraceId = newValue;
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
showTraceId: function(newValue, oldValue) {
|
||||
let isScrollTop = document.querySelector('.infiniteTable');
|
||||
if(isScrollTop && typeof isScrollTop.scrollTop !== 'undefined') if(newValue !== oldValue) isScrollTop.scrollTop = 0;
|
||||
},
|
||||
infiniteFirstCases: function(newValue){
|
||||
if(this.infiniteFirstCases) this.infiniteData = JSON.parse(JSON.stringify(newValue));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
@@ -117,7 +133,11 @@ export default {
|
||||
* @param {number} id
|
||||
*/
|
||||
async switchCaseData(id, count) {
|
||||
if(count >= 1000) this.isLoading = true;
|
||||
this.infinit404 = null;
|
||||
this.infinitMaxItems = false;
|
||||
this.showTraceId = id;
|
||||
this.infiniteStart = 0;
|
||||
this.$emit('switch-Trace-Id', {id: this.showTraceId, count: count});
|
||||
},
|
||||
/**
|
||||
@@ -172,20 +192,43 @@ export default {
|
||||
/**
|
||||
* create map
|
||||
*/
|
||||
show() {
|
||||
async show() {
|
||||
// 因 trace api 連動,所以關閉側邊欄時讓數值歸 traces 第一筆 id
|
||||
this.showTraceId = await this.traces[0]?.id;
|
||||
this.infiniteStart = await 0;
|
||||
await this.allMapDataStore.getTraceDetail();
|
||||
this.setNodesData();
|
||||
this.setEdgesData();
|
||||
this.createCy();
|
||||
},
|
||||
/**
|
||||
* hide map
|
||||
* 無限滾動: 監聽 scroll 有沒有滾到底部
|
||||
* @param {element} event
|
||||
*/
|
||||
hide() {
|
||||
// 因 trace api 連動,所以關閉側邊欄時讓數值歸 1
|
||||
this.showTraceId = 1;
|
||||
this.allMapDataStore.getTraceDetail();
|
||||
handleScroll(event) {
|
||||
if(this.infinitMaxItems || this.cases.length < 20) return;
|
||||
|
||||
const container = event.target;
|
||||
const overScrollHeight = container.scrollTop + container.clientHeight >= container.scrollHeight;
|
||||
|
||||
if(overScrollHeight) this.fetchData();
|
||||
},
|
||||
/**
|
||||
* 無限滾動: 滾到底後,要載入數據
|
||||
*/
|
||||
async fetchData() {
|
||||
try {
|
||||
this.infiniteStart += 20;
|
||||
await this.allMapDataStore.getTraceDetail();
|
||||
this.infiniteData = [...this.infiniteData, ...this.cases];
|
||||
} catch(error) {
|
||||
console.error('Failed to load data:', error);
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.allMapDataStore.getTraceDetail();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ export default defineStore('allMapDataStore', {
|
||||
allFunnelData: [],
|
||||
isUpdataFilter: false, // 是否成功儲存 Filter 檔
|
||||
selectTimeFrame: [], // user select time start and end
|
||||
infinite404: null, // 無限滾動式是否到底要換頁
|
||||
infiniteStart: 0, // 無限滾動 case 開始的數字
|
||||
}),
|
||||
getters: {
|
||||
processMap: state => {
|
||||
@@ -58,6 +60,9 @@ export default defineStore('allMapDataStore', {
|
||||
cases: state => {
|
||||
return state.allCase;
|
||||
},
|
||||
infiniteFirstCases: state => {
|
||||
if(state.infiniteStart === 0) return state.allCase;
|
||||
},
|
||||
traceTaskSeq: state => {
|
||||
return state.allTraceTaskSeq;
|
||||
},
|
||||
@@ -153,12 +158,14 @@ export default defineStore('allMapDataStore', {
|
||||
let traceId = this.traceId;
|
||||
let tempFilterId = this.tempFilterId;
|
||||
let createfilterId = this.createFilterId;
|
||||
let start = this.infiniteStart;
|
||||
let api = '';
|
||||
|
||||
|
||||
// 先判斷暫存 再判斷 filter 最後 log
|
||||
if(tempFilterId != null) api = `/api/temp-filters/${tempFilterId}/traces/${traceId}`;
|
||||
else if(createfilterId!= null) api = `/api/filters/${createfilterId}/traces/${traceId}`;
|
||||
else api = `/api/logs/${logId}/traces/${traceId}`;
|
||||
if(tempFilterId != null) api = `/api/temp-filters/${tempFilterId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
else if(createfilterId!= null) api = `/api/filters/${createfilterId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
else api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
@@ -169,9 +176,12 @@ export default defineStore('allMapDataStore', {
|
||||
c.completed_at = moment(c.completed_at).format('YYYY-MM-DD HH:MM');
|
||||
return this.allCase;
|
||||
});
|
||||
return this.allCase;
|
||||
|
||||
// if(this.httpStatus < 300) loading.isLoading = false;
|
||||
} catch(error) {
|
||||
if(error.response.status === 404) this.infinite404 = 404;
|
||||
else {
|
||||
this.httpStatus = error.request.status;
|
||||
await delay();
|
||||
loading.isLoading = true;
|
||||
@@ -179,6 +189,7 @@ export default defineStore('allMapDataStore', {
|
||||
loading.isLoading = false;
|
||||
await delay(500);
|
||||
$toast.default('Failed to load the Trace Detail.',{position: 'bottom'});
|
||||
}
|
||||
};
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<!-- Sidebar Model -->
|
||||
<SidebarView v-model:visible="sidebarView" @switch-map-type="switchMapType" @switch-curve-styles="switchCurveStyles" @switch-rank="switchRank" @switch-data-layer-type="switchDataLayerType" ></SidebarView>
|
||||
<SidebarState v-model:visible="sidebarState" :insights="insights" :stats="stats"></SidebarState>
|
||||
<SidebarTraces v-model:visible="sidebarTraces" :traces="traces" :cases="cases" :traceTaskSeq="traceTaskSeq" @switch-Trace-Id="switchTraceId" ref="tracesView"></SidebarTraces>
|
||||
<SidebarTraces v-model:visible="sidebarTraces" @switch-Trace-Id="switchTraceId" ref="tracesView"></SidebarTraces>
|
||||
<SidebarFilter v-model:visible="sidebarFilter" :filterTasks="filterTasks" :filterStartToEnd="filterStartToEnd" :filterEndToStart="filterEndToStart" :filterTimeframe="filterTimeframe" :filterTrace="filterTrace"
|
||||
@submit-all="createCy(mapType)" @switch-Trace-Id="switchTraceId" ref="sidevarFilterRef"></SidebarFilter>
|
||||
|
||||
@@ -68,9 +68,9 @@ export default {
|
||||
const loadingStore = LoadingStore();
|
||||
const allMapDataStore = AllMapDataStore();
|
||||
const { isLoading } = storeToRefs(loadingStore);
|
||||
const { processMap, bpmn, stats, insights, traceId, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, createFilterId } = storeToRefs(allMapDataStore);
|
||||
const { processMap, bpmn, stats, insights, traceId, traces, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, createFilterId } = storeToRefs(allMapDataStore);
|
||||
|
||||
return { isLoading, processMap, bpmn, stats, insights, traceId, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
||||
return { isLoading, processMap, bpmn, stats, insights, traceId, traces, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
||||
},
|
||||
components: {
|
||||
SidebarView,
|
||||
@@ -102,6 +102,7 @@ export default {
|
||||
sidebarState: false, // SideBar: Summary & Insight
|
||||
sidebarTraces: false, // SideBar: Traces
|
||||
sidebarFilter: false, // SideBar: Filter
|
||||
infiniteFirstCases: null,
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
@@ -311,7 +312,6 @@ export default {
|
||||
await this.allMapDataStore.getAllMapData();
|
||||
await this.allMapDataStore.getAllTrace();
|
||||
this.traceId = await this.traces[0]?.id; // log、filter 檔切換過程中, trace id 不同,將初始 trace id 設定為該檔案的 trace 幣一筆資料的 id。
|
||||
await this.allMapDataStore.getTraceDetail();
|
||||
this.createCy(this.mapType);
|
||||
await this.allMapDataStore.getFilterParams();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user