Discover: sideFilter Trace Slider done.
This commit is contained in:
30
package-lock.json
generated
30
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
"chart.js": "^4.3.0",
|
||||||
"cytoscape": "^3.23.0",
|
"cytoscape": "^3.23.0",
|
||||||
"cytoscape-dagre": "^2.5.0",
|
"cytoscape-dagre": "^2.5.0",
|
||||||
"cytoscape-popper": "^2.0.0",
|
"cytoscape-popper": "^2.0.0",
|
||||||
@@ -600,6 +601,11 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@kurkle/color": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -1715,6 +1721,17 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chart.js": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": ">=7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/check-error": {
|
"node_modules/check-error": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
@@ -6676,6 +6693,11 @@
|
|||||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@kurkle/color": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||||
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@@ -7572,6 +7594,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chart.js": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-ynG0E79xGfMaV2xAHdbhwiPLczxnNNnasrmPEXriXsPJGjmhOBYzFVEsB65w2qMDz+CaBJJuJD0inE/ab/h36g==",
|
||||||
|
"requires": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"check-error": {
|
"check-error": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
|
"chart.js": "^4.3.0",
|
||||||
"cytoscape": "^3.23.0",
|
"cytoscape": "^3.23.0",
|
||||||
"cytoscape-dagre": "^2.5.0",
|
"cytoscape-dagre": "^2.5.0",
|
||||||
"cytoscape-popper": "^2.0.0",
|
"cytoscape-popper": "^2.0.0",
|
||||||
|
|||||||
263
src/components/Discover/Filter/Trace.vue
Normal file
263
src/components/Discover/Filter/Trace.vue
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex justify-between items-start bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full">
|
||||||
|
|
||||||
|
<!-- Range Selection -->
|
||||||
|
<section>
|
||||||
|
<p class="h2">Range Selection</p>
|
||||||
|
<div class="text-primary h2 flex items-center justify-start">
|
||||||
|
<span class="material-symbols-outlined m-2">info</span>
|
||||||
|
<p>Select a percentage range.</p>
|
||||||
|
</div>
|
||||||
|
<Chart type="line" :data="chartData" :options="chartOptions" class="h-30rem" />
|
||||||
|
<p class="my-6">Select percentage of case <span class=" float-right">{{ caseTotalPercent }}%</span></p>
|
||||||
|
<Slider v-model="selectArea" :step="1" :min="1" :max="traceTotal" range class="w-14rem" />
|
||||||
|
</section>
|
||||||
|
<!-- Trace List -->
|
||||||
|
<section class="h-full">
|
||||||
|
<p class="h2 px-2 mb-2">Trace List ({{ traceTotal }})</p>
|
||||||
|
<p class="text-primary h2 flex items-center justify-start">
|
||||||
|
<span class="material-symbols-outlined m-2">info</span>Click trace number to see more.
|
||||||
|
</p>
|
||||||
|
<div class="overflow-y-scroll overflow-x-hidden scrollbar mx-[-8px] max-h-[calc(100%_-_96px)]" >
|
||||||
|
<table class="border-separate border-spacing-x-2 text-sm">
|
||||||
|
<thead class="sticky top-0 z-10 bg-neutral-10">
|
||||||
|
<tr>
|
||||||
|
<th class="h2 px-2 border-b border-neutral-500">Trace</th>
|
||||||
|
<th class="h2 px-2 border-b border-neutral-500 text-start" colspan="3">Occurrences</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(trace, key) in traceList" :key="key" class=" cursor-pointer hover:text-primary" @click="switchCaseData(trace.id)">
|
||||||
|
<td class="p-2">#{{ trace.id }}</td>
|
||||||
|
<td class="p-2 w-24">
|
||||||
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(trace.value)"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="py-2 text-right">{{ trace.count }}</td>
|
||||||
|
<td class="p-2">{{ trace.ratio }}%</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Trace item Table -->
|
||||||
|
<section v-show="showTraceId" class="pl-4 h-full w-[calc(100%_-_320px)]">
|
||||||
|
<p class="h2 mb-2">Trace #{{ showTraceId }}</p>
|
||||||
|
<div class="h-52 w-full px-2 mb-2 border border-neutral-300 rounded">
|
||||||
|
<div class="h-full w-full">
|
||||||
|
<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">
|
||||||
|
<Column field="id" header="Case ID" sortable></Column>
|
||||||
|
<Column field="started_at" header="Start time" sortable></Column>
|
||||||
|
<Column field="completed_at" header="End time" sortable></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
|
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const allMapDataStore = AllMapDataStore();
|
||||||
|
const { traces, traceTaskSeq, cases } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
|
return {allMapDataStore, traces, traceTaskSeq, cases}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
processMap:{
|
||||||
|
nodes:[],
|
||||||
|
edges:[],
|
||||||
|
},
|
||||||
|
showTraceId: null,
|
||||||
|
|
||||||
|
chartData: null,
|
||||||
|
chartOptions: null,
|
||||||
|
selectArea: [1, 1]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
traceTotal: function() {
|
||||||
|
return this.traces.length;
|
||||||
|
},
|
||||||
|
traceList: function() {
|
||||||
|
return this.traces.map(trace => {
|
||||||
|
return {
|
||||||
|
id: trace.id,
|
||||||
|
value: Number((trace.ratio * 100).toFixed(1)),
|
||||||
|
count: trace.count,
|
||||||
|
ratio: this.getPercentLabel(trace.ratio),
|
||||||
|
};
|
||||||
|
}).sort((x, y) => x.id - y.id)
|
||||||
|
.slice(this.selectArea[0]-1, this.selectArea[1]);
|
||||||
|
},
|
||||||
|
caseTotalPercent: function() {
|
||||||
|
let sum = 0;
|
||||||
|
this.traceList.forEach(trace => sum += Number(trace.ratio));
|
||||||
|
|
||||||
|
let str = sum.toFixed(1).toString();
|
||||||
|
let lastDigit = str[str.length - 1]; // 取得小數點後的第一位數字
|
||||||
|
|
||||||
|
return lastDigit === '0' ? sum.toFixed(0) : sum.toFixed(1)
|
||||||
|
// return sum.toFixed(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setChartData() {
|
||||||
|
const documentStyle = getComputedStyle(document.documentElement);
|
||||||
|
|
||||||
|
return {
|
||||||
|
// 要呈現的資料
|
||||||
|
labels: ['', '', '', '', '', '', ''], // 水平軸
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Trace List', // 資料的標題標籤
|
||||||
|
data: [12, 51, 62, 33, 21, 100, 45],
|
||||||
|
fill: true,
|
||||||
|
borderColor: documentStyle.getPropertyValue('--orange-500'),
|
||||||
|
tension: 0.4,
|
||||||
|
backgroundColor: 'rgba(255,167,38,0.2)'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
setChartOptions() {
|
||||||
|
return {
|
||||||
|
// 自訂屬性設定
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
aspectRatio: 0.6,
|
||||||
|
plugins: {
|
||||||
|
legend: { // 圖例
|
||||||
|
display: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
display: false, // 隱藏 x 軸
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
ticks: { // 設定間隔數值
|
||||||
|
display: false, // 隱藏數值,只顯示格線
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
stepSize: 25,
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Number to percentage
|
||||||
|
* @param {number} val
|
||||||
|
* @returns {string} 轉換完成的百分比字串
|
||||||
|
*/
|
||||||
|
getPercentLabel(val){
|
||||||
|
// return (val * 100 === 100) ? `${val * 100}%` : `${(val * 100).toFixed(1)}%`;
|
||||||
|
return (val * 100 === 100) ? val * 100 : (val * 100).toFixed(1);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* set progress bar width
|
||||||
|
* @param {number} value
|
||||||
|
* @returns {string} 樣式的寬度設定
|
||||||
|
*/
|
||||||
|
progressWidth(value){
|
||||||
|
return `width:${value}%;`
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* switch case data
|
||||||
|
* @param {number} id
|
||||||
|
*/
|
||||||
|
async switchCaseData(id) {
|
||||||
|
this.showTraceId = id;
|
||||||
|
this.allMapDataStore.traceId = id;
|
||||||
|
await this.allMapDataStore.getTraceDetail();
|
||||||
|
this.createCy();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 將 trace element nodes 資料彙整
|
||||||
|
*/
|
||||||
|
setNodesData(){
|
||||||
|
// 避免每次渲染都重複累加
|
||||||
|
this.processMap.nodes = [];
|
||||||
|
// 將 api call 回來的資料帶進 node
|
||||||
|
this.traceTaskSeq.forEach((node, index) => {
|
||||||
|
this.processMap.nodes.push({
|
||||||
|
data: {
|
||||||
|
id: index,
|
||||||
|
label: node,
|
||||||
|
backgroundColor: '#CCE5FF',
|
||||||
|
bordercolor: '#003366',
|
||||||
|
shape: 'round-rectangle',
|
||||||
|
height: 80,
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 將 trace edge line 資料彙整
|
||||||
|
*/
|
||||||
|
setEdgesData(){
|
||||||
|
this.processMap.edges = [];
|
||||||
|
this.traceTaskSeq.forEach((edge, index) => {
|
||||||
|
this.processMap.edges.push({
|
||||||
|
data: {
|
||||||
|
source: `${index}`,
|
||||||
|
target: `${index + 1}`,
|
||||||
|
lineWidth: 1,
|
||||||
|
style: 'solid'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 關係線數量筆節點少一個
|
||||||
|
this.processMap.edges.pop();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* create trace cytoscape's map
|
||||||
|
*/
|
||||||
|
createCy(){
|
||||||
|
let graphId = this.$refs.cyTrace;
|
||||||
|
|
||||||
|
this.setNodesData();
|
||||||
|
this.setEdgesData();
|
||||||
|
cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setNodesData();
|
||||||
|
this.setEdgesData();
|
||||||
|
this.createCy();
|
||||||
|
this.chartData = this.setChartData();
|
||||||
|
this.chartOptions = this.setChartOptions();
|
||||||
|
this.selectArea = [1, this.traceTotal]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 進度條顏色 */
|
||||||
|
:deep(.p-progressbar .p-progressbar-value) {
|
||||||
|
@apply bg-primary
|
||||||
|
}
|
||||||
|
/* Table set */
|
||||||
|
:deep(.p-datatable-thead th) {
|
||||||
|
@apply sticky top-0 left-0 z-10 bg-neutral-10
|
||||||
|
}
|
||||||
|
:deep(.p-datatable .p-datatable-thead > tr > th) {
|
||||||
|
@apply !border-y-0 border-neutral-500 bg-neutral-100 after:absolute after:left-0 after:w-full after:h-full after:block after:top-0 after:border-b after:border-t after:border-neutral-500
|
||||||
|
}
|
||||||
|
:deep(.p-datatable .p-datatable-tbody > tr > td) {
|
||||||
|
@apply border-neutral-500 !border-t-0
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Sidebar :visible="sidebarFilter" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" :baseZIndex="15" class="!w-11/12 !bg-neutral-100">
|
<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()">
|
||||||
<template #header>
|
<template #header>
|
||||||
<ul class="flex space-x-4">
|
<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>
|
<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>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<!-- header: filter -->
|
<!-- header: filter -->
|
||||||
<div v-if="tab === 'filter'" class="pt-4 flex w-full h-full">
|
<div v-if="tab === 'filter'" class="pt-4 flex w-full h-full">
|
||||||
<!-- title: filter silect -->
|
<!-- title: filter silect -->
|
||||||
<div class="space-y-2 mr-4 w-56 text-sm">
|
<div class="space-y-2 mr-4 w-48 text-sm">
|
||||||
<div>
|
<div>
|
||||||
<p class="h2">Filter Type</p>
|
<p class="h2">Filter Type</p>
|
||||||
<div v-for="(item, index) in selectFilter['Filter Type']" :key="index" class="flex align-items-center">
|
<div v-for="(item, index) in selectFilter['Filter Type']" :key="index" class="flex align-items-center">
|
||||||
@@ -60,24 +60,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- title: Activity Select -->
|
<!-- Fiter content -->
|
||||||
<div class="space-y-2 w-[calc(100%_-_240px)] h-[calc(100%_-_106px)]">
|
<div class="w-[calc(100%_-_208px)] h-full">
|
||||||
<p class="h2 ml-1">Activity Select</p>
|
|
||||||
<!-- Filter task Data-->
|
<!-- Filter titles -->
|
||||||
<ActOccCase v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Have activity(s)'" :tableTitle="'Activity List'" :tableData="filterAllTaskData" :tableSelect="selectFilterTask" :progressWidth ="progressWidth" @on-row-select="onRowAct"></ActOccCase>
|
<div class="space-y-2 w-full h-[calc(100%_-_48px)]">
|
||||||
<!-- Filter Start Data -->
|
<!-- title: Activity Select -->
|
||||||
<ActOcc v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'Start'" :tableTitle="'Start activity'" :tableData="filterStartData" :tableSelect="selectFilterStart" :progressWidth ="progressWidth" @on-row-select="onRowStart"></ActOcc>
|
<div class="w-full h-[calc(100%_-_48px)]" v-if="selectValue[0] === 'Sequence'">
|
||||||
<!-- Filter End Data -->
|
<p class="h2 ml-1">Activity Select</p>
|
||||||
<ActOcc v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'End'" :tableTitle="'End activity'" :tableData="filterEndData" :tableSelect="selectFilterEnd" :progressWidth ="progressWidth" @on-row-select="onRowEnd"></ActOcc>
|
<!-- Filter task Data-->
|
||||||
<!-- Filter Start And End Data -->
|
<ActOccCase v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Have activity(s)'" :tableTitle="'Activity List'" :tableData="filterAllTaskData" :tableSelect="selectFilterTask" :progressWidth ="progressWidth" @on-row-select="onRowAct"></ActOccCase>
|
||||||
<div v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'Start & End'" class="flex justify-between items-center w-full h-full space-x-4 ">
|
<!-- Filter Start Data -->
|
||||||
<ActOcc :tableTitle="'Start activity'" :tableData="filterStartToEndData" :tableSelect="selectFilterStartToEnd" :progressWidth ="progressWidth" class="w-1/2" @on-row-select="startRow"></ActOcc>
|
<ActOcc v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'Start'" :tableTitle="'Start activity'" :tableData="filterStartData" :tableSelect="selectFilterStart" :progressWidth ="progressWidth" @on-row-select="onRowStart"></ActOcc>
|
||||||
<ActOcc :tableTitle="'End activity'" :tableData="filterEndToStartData" :tableSelect="selectFilterEndToStart" :progressWidth ="progressWidth" class="w-1/2" @on-row-select="endRow"></ActOcc>
|
<!-- Filter End Data -->
|
||||||
</div>
|
<ActOcc v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'End'" :tableTitle="'End activity'" :tableData="filterEndData" :tableSelect="selectFilterEnd" :progressWidth ="progressWidth" @on-row-select="onRowEnd"></ActOcc>
|
||||||
<!-- Filter Sequence -->
|
<!-- Filter Start And End Data -->
|
||||||
<div v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Sequence'" class="flex justify-between items-center w-full h-full space-x-4">
|
<div v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Start activity / end activity' && selectValue[2] === 'Start & End'" class="flex justify-between items-center w-full h-full space-x-4 ">
|
||||||
<ActAndSeq :filterTaskData="filterTaskData" :progressWidth ="progressWidth" :listSeq="listSeq" @update:listSeq="onUpdateListSeq"></ActAndSeq>
|
<ActOcc :tableTitle="'Start activity'" :tableData="filterStartToEndData" :tableSelect="selectFilterStartToEnd" :progressWidth ="progressWidth" class="w-1/2" @on-row-select="startRow"></ActOcc>
|
||||||
|
<ActOcc :tableTitle="'End activity'" :tableData="filterEndToStartData" :tableSelect="selectFilterEndToStart" :progressWidth ="progressWidth" class="w-1/2" @on-row-select="endRow"></ActOcc>
|
||||||
|
</div>
|
||||||
|
<!-- Filter Sequence -->
|
||||||
|
<div v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Sequence'" class="flex justify-between items-center w-full h-full space-x-4">
|
||||||
|
<ActAndSeq :filterTaskData="filterTaskData" :progressWidth ="progressWidth" :listSeq="listSeq" @update:listSeq="onUpdateListSeq"></ActAndSeq>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- title: Trace -->
|
||||||
|
<Trace v-if="selectValue[0] === 'Trace'"></Trace>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Button -->
|
<!-- Button -->
|
||||||
<div class="float-right space-x-4 px-4 py-2">
|
<div class="float-right space-x-4 px-4 py-2">
|
||||||
<button type="button" class="btn btn-sm btn-neutral" @click="reset">Clear</button>
|
<button type="button" class="btn btn-sm btn-neutral" @click="reset">Clear</button>
|
||||||
@@ -86,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- header: funnel -->
|
<!-- header: funnel -->
|
||||||
<Funnel v-if="tab === 'funnel'" @submit-all="sumbitAll" :setRule="setRule"></Funnel>
|
<Funnel v-if="tab === 'funnel'" @submit-all="sumbitAll" :setRule="setRule" ref="filterTrace"></Funnel>
|
||||||
</Sidebar>
|
</Sidebar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -98,6 +108,7 @@ import ActOccCase from '@/components/Discover/Filter/ActOccCase.vue';
|
|||||||
import ActOcc from '@/components/Discover/Filter/ActOcc.vue';
|
import ActOcc from '@/components/Discover/Filter/ActOcc.vue';
|
||||||
import ActAndSeq from '@/components/Discover/Filter/ActAndSeq.vue';
|
import ActAndSeq from '@/components/Discover/Filter/ActAndSeq.vue';
|
||||||
import Funnel from '@/components/Discover/Filter/Funnel.vue';
|
import Funnel from '@/components/Discover/Filter/Funnel.vue';
|
||||||
|
import Trace from '@/components/Discover/Filter/Trace.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['sidebarFilter', 'filterTasks', 'filterStartToEnd', 'filterEndToStart', 'filterTimeframe', 'filterTrace'],
|
props: ['sidebarFilter', 'filterTasks', 'filterStartToEnd', 'filterEndToStart', 'filterTimeframe', 'filterTrace'],
|
||||||
@@ -148,6 +159,7 @@ export default {
|
|||||||
ActOcc,
|
ActOcc,
|
||||||
ActAndSeq,
|
ActAndSeq,
|
||||||
Funnel,
|
Funnel,
|
||||||
|
Trace,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
// All Task
|
// All Task
|
||||||
@@ -459,6 +471,14 @@ export default {
|
|||||||
*/
|
*/
|
||||||
sumbitAll() {
|
sumbitAll() {
|
||||||
this.$emit('submit-all');
|
this.$emit('submit-all');
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* hide map
|
||||||
|
*/
|
||||||
|
hide() {
|
||||||
|
// 因 trace api 連動,所以關閉側邊欄時讓數值歸 1
|
||||||
|
this.allMapDataStore.traceId = 1;
|
||||||
|
this.allMapDataStore.getTraceDetail();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Sidebar :visible="sidebarTraces" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" class="!w-11/12" @show="show()">
|
<Sidebar :visible="sidebarTraces" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" class="!w-11/12" @show="show()" @hide="hide()">
|
||||||
<template #header>
|
<template #header>
|
||||||
<p class="h1">Traces</p>
|
<p class="h1">Traces</p>
|
||||||
</template>
|
</template>
|
||||||
@@ -55,13 +55,21 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
sidebarTraces: Boolean,
|
sidebarTraces: Boolean,
|
||||||
traces: Array,
|
traces: Array,
|
||||||
traceTaskSeq: Array,
|
traceTaskSeq: Array,
|
||||||
cases: Array
|
cases: Array,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const allMapDataStore = AllMapDataStore();
|
||||||
|
// const { traces, traceTaskSeq, cases } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
|
return {allMapDataStore}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -77,20 +85,6 @@ export default {
|
|||||||
return this.traces.length;
|
return this.traces.length;
|
||||||
},
|
},
|
||||||
traceList: function() {
|
traceList: function() {
|
||||||
// let list = [];
|
|
||||||
|
|
||||||
// this.traces.forEach((trace, index) => {
|
|
||||||
// let data = {
|
|
||||||
// id: trace.id,
|
|
||||||
// value: Number((trace.ratio * 100).toFixed(1)),
|
|
||||||
// count: trace.count,
|
|
||||||
// ratio: this.getPercentLabel(trace.ratio),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// list.push(data);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return list;
|
|
||||||
return this.traces.map(trace => {
|
return this.traces.map(trace => {
|
||||||
return {
|
return {
|
||||||
id: trace.id,
|
id: trace.id,
|
||||||
@@ -175,17 +169,23 @@ export default {
|
|||||||
this.setEdgesData();
|
this.setEdgesData();
|
||||||
cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* create map
|
||||||
|
*/
|
||||||
show() {
|
show() {
|
||||||
this.setNodesData();
|
this.setNodesData();
|
||||||
this.setEdgesData();
|
this.setEdgesData();
|
||||||
this.createCy();
|
this.createCy();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* hide map
|
||||||
|
*/
|
||||||
|
hide() {
|
||||||
|
// 因 trace api 連動,所以關閉側邊欄時讓數值歸 1
|
||||||
|
this.showTraceId = 1;
|
||||||
|
this.allMapDataStore.getTraceDetail();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created(){
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import RadioButton from 'primevue/radiobutton';
|
|||||||
import PickList from 'primevue/picklist';
|
import PickList from 'primevue/picklist';
|
||||||
import Timeline from 'primevue/timeline';
|
import Timeline from 'primevue/timeline';
|
||||||
import InputSwitch from 'primevue/inputswitch';
|
import InputSwitch from 'primevue/inputswitch';
|
||||||
|
import Chart from 'primevue/chart';
|
||||||
|
import Slider from 'primevue/slider';
|
||||||
|
|
||||||
const emitter = mitt();
|
const emitter = mitt();
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
@@ -84,6 +86,8 @@ app.component('RadioButton', RadioButton);
|
|||||||
app.component('PickList', PickList);
|
app.component('PickList', PickList);
|
||||||
app.component('Timeline', Timeline);
|
app.component('Timeline', Timeline);
|
||||||
app.component('InputSwitch', InputSwitch);
|
app.component('InputSwitch', InputSwitch);
|
||||||
|
app.component('Chart', Chart);
|
||||||
|
app.component('Slider', Slider);
|
||||||
app.component('Draggable', draggable); // 拖曳
|
app.component('Draggable', draggable); // 拖曳
|
||||||
|
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
<SidebarState v-model:visible="sidebarState" :insights="insights" :stats="stats"></SidebarState>
|
<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" :traces="traces" :cases="cases" :traceTaskSeq="traceTaskSeq" @switch-Trace-Id="switchTraceId" ref="tracesView"></SidebarTraces>
|
||||||
<SidebarFilter v-model:visible="sidebarFilter" :filterTasks="filterTasks" :filterStartToEnd="filterStartToEnd" :filterEndToStart="filterEndToStart" :filterTimeframe="filterTimeframe" :filterTrace="filterTrace"
|
<SidebarFilter v-model:visible="sidebarFilter" :filterTasks="filterTasks" :filterStartToEnd="filterStartToEnd" :filterEndToStart="filterEndToStart" :filterTimeframe="filterTimeframe" :filterTrace="filterTrace"
|
||||||
@submit-all="createCy(mapType)" ref="sidevarFilterRef"></SidebarFilter>
|
@submit-all="createCy(mapType)" @switch-Trace-Id="switchTraceId" ref="sidevarFilterRef"></SidebarFilter>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -68,9 +68,9 @@ export default {
|
|||||||
const loadingStore = LoadingStore();
|
const loadingStore = LoadingStore();
|
||||||
const allMapDataStore = AllMapDataStore();
|
const allMapDataStore = AllMapDataStore();
|
||||||
const { isLoading } = storeToRefs(loadingStore);
|
const { isLoading } = storeToRefs(loadingStore);
|
||||||
const { processMap, bpmn, stats, insights, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, createFilterId } = storeToRefs(allMapDataStore);
|
const { processMap, bpmn, stats, insights, traceId, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, createFilterId } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
return { isLoading, processMap, bpmn, stats, insights, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
return { isLoading, processMap, bpmn, stats, insights, traceId, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
SidebarView,
|
SidebarView,
|
||||||
@@ -151,7 +151,7 @@ export default {
|
|||||||
* @param {string} id
|
* @param {string} id
|
||||||
*/
|
*/
|
||||||
async switchTraceId(id) {
|
async switchTraceId(id) {
|
||||||
this.allMapDataStore.traceId = id;
|
this.traceId = id;
|
||||||
await this.allMapDataStore.getTraceDetail();
|
await this.allMapDataStore.getTraceDetail();
|
||||||
this.$refs.tracesView.createCy();
|
this.$refs.tracesView.createCy();
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user