Discover: sidebarFilter layout done
This commit is contained in:
32
package-lock.json
generated
32
package-lock.json
generated
@@ -25,7 +25,8 @@
|
|||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-axios": "^3.5.2",
|
"vue-axios": "^3.5.2",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue-toast-notification": "^3.0.4"
|
"vue-toast-notification": "^3.0.4",
|
||||||
|
"vuedraggable": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.1.4",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
@@ -5236,6 +5237,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sortablejs": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
@@ -6011,6 +6017,17 @@
|
|||||||
"vue": "^3.0"
|
"vue": "^3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vuedraggable": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
|
||||||
|
"dependencies": {
|
||||||
|
"sortablejs": "1.14.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/w3c-xmlserializer": {
|
"node_modules/w3c-xmlserializer": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||||
@@ -10107,6 +10124,11 @@
|
|||||||
"is-fullwidth-code-point": "^3.0.0"
|
"is-fullwidth-code-point": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"sortablejs": {
|
||||||
|
"version": "1.14.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
|
||||||
|
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
|
||||||
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
@@ -10622,6 +10644,14 @@
|
|||||||
"integrity": "sha512-rEhLtcKg8SVdBpdN7PrNst5nmY8dw0j3NkNImqurhlGurqR/QDKoou0t2PuCReEOCTKqHvfLCle2I3kwQWDWDQ==",
|
"integrity": "sha512-rEhLtcKg8SVdBpdN7PrNst5nmY8dw0j3NkNImqurhlGurqR/QDKoou0t2PuCReEOCTKqHvfLCle2I3kwQWDWDQ==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
"vuedraggable": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
|
||||||
|
"requires": {
|
||||||
|
"sortablejs": "1.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"w3c-xmlserializer": {
|
"w3c-xmlserializer": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-axios": "^3.5.2",
|
"vue-axios": "^3.5.2",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue-toast-notification": "^3.0.4"
|
"vue-toast-notification": "^3.0.4",
|
||||||
|
"vuedraggable": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.1.4",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
|
|||||||
347
src/components/Discover/sidebarFilter.vue
Normal file
347
src/components/Discover/sidebarFilter.vue
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
<template>
|
||||||
|
<Sidebar :visible="sidebarFilter" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" 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'">Filter</li>
|
||||||
|
<li class="h1 border-r-2 border-neutral-300 pr-4 cursor-pointer hover:text-neutral-900 hover:duration-700" @click="switchTab('funnel')" :class="tab === 'funnel'? 'text-neutral-900': 'text-neutral-500'">Funnel</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
<!-- header: filter -->
|
||||||
|
<div v-if="tab === 'filter'" class="pt-4 bg-neutral-100 flex w-full h-full">
|
||||||
|
<!-- title: filter silect -->
|
||||||
|
<div class="space-y-2 mr-4 w-56">
|
||||||
|
<div>
|
||||||
|
<p class="h2">Filter Type</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Filter Type']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[0]" :inputId="item + index" name="Filter Type" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="selectValue[0] === 'Sequence'">
|
||||||
|
<p class="h2">Activity Sequence</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Activity Sequence']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[1]" :inputId="item + index" name="Activity Sequence" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="selectValue[1] === 'Start activity & end activity'">
|
||||||
|
<p class="h2">Start & End</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Start & End']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[2]" :inputId="item + index" name="Start & End" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="selectValue[0] === 'Sequence' && selectValue[1] === 'Sequence'">
|
||||||
|
<p class="h2">Mode</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Mode']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[3]" :inputId="item + index" name="Mode" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="selectValue[0] === 'Attributes'">
|
||||||
|
<p class="h2">Mode</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['ModeAtt']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[4]" :inputId="item + index" name="ModeAtt" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="h2">Refine</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Refine']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[5]" :inputId="item + index" name="Refinee" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-show="selectValue[0] === 'Timeframes'">
|
||||||
|
<p class="h2">Containment</p>
|
||||||
|
<div v-for="(item, index) in selectFilter['Containment']" :key="index" class="flex align-items-center">
|
||||||
|
<RadioButton v-model="selectValue[6]" :inputId="item + index" name="Containment" :value="item" />
|
||||||
|
<label :for="item + index" class="ml-2">{{ item }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- title: Activity Select -->
|
||||||
|
<div class="space-y-2 w-[calc(100%_-_240px)] h-[calc(100%_-_106px)]">
|
||||||
|
<p class="h2 ml-1">Activity Select</p>
|
||||||
|
|
||||||
|
<!-- Filter task Data-->
|
||||||
|
<ActOccCase v-if="selectValue[0] === 'Sequence' && selectValue[1] === 'Have activity(s)'" :tableTitle="'Activity List'" :tableData="filterTaskData" :tableSelect="selectFilterTask" :progressWidth ="progressWidth" @on-row-select="onRowAct"></ActOccCase>
|
||||||
|
<!-- Filter Start Data -->
|
||||||
|
<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>
|
||||||
|
<!-- Filter End Data -->
|
||||||
|
<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 Start And End Data -->
|
||||||
|
<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 ">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<!-- Button -->
|
||||||
|
<div class="float-right space-x-4 px-4 py-2">
|
||||||
|
<button class="btn btn-sm btn-neutral" @click="reset">Reset</button>
|
||||||
|
<button class="btn btn-sm btn-neutral">Apply</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- header: funnel -->
|
||||||
|
<div v-if="tab === 'funnel'"></div>
|
||||||
|
|
||||||
|
</Sidebar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ActOccCase from '@/components/Discover/table/actOccCase.vue';
|
||||||
|
import ActOcc from '@/components/Discover/table/actOcc.vue';
|
||||||
|
import ActAndSeq from '@/components/Discover/table/actAndSeq.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
sidebarFilter: {
|
||||||
|
type: Boolean,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
filterTasks: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
filterStartToEnd: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
filterEndToStart: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
filterTimeframe: {
|
||||||
|
type: Object,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
filterTrace: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectFilter: {
|
||||||
|
'Filter Type': ['Sequence', 'Attributes', 'Trace', 'Timeframes'],
|
||||||
|
'Activity Sequence':['Have activity(s)', 'Start activity & end activity', 'Sequence'],
|
||||||
|
'Start & End': ['Start', 'End', 'Start & End'],
|
||||||
|
'Mode': ['Directly follows', 'Eventually follows'],
|
||||||
|
'ModeAtt': ['Case', 'Activity'],
|
||||||
|
'Refine': ['Include', 'Exclude'],
|
||||||
|
'Containment': ['Contained in', 'Started in', 'End in', 'Activity in', 'Trim'],
|
||||||
|
},
|
||||||
|
tab: 'filter',
|
||||||
|
selectValue: ['Sequence', 'Have activity(s)', 'Start', 'Directly follows', 'Case', 'Include', 'Contained in'],
|
||||||
|
selectFilterTask: null,
|
||||||
|
selectFilterStart: null,
|
||||||
|
selectFilterEnd: null,
|
||||||
|
selectFilterStartToEnd: null,
|
||||||
|
selectFilterEndToStart: null,
|
||||||
|
listSeq: [],
|
||||||
|
//若第一次選擇 start, 則 end 連動改變,若第一次選擇 end, 則 start 連動改變
|
||||||
|
isStartSelected: null,
|
||||||
|
isEndSelected: null,
|
||||||
|
rowData: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
ActOccCase,
|
||||||
|
ActOcc,
|
||||||
|
ActAndSeq,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// All Task
|
||||||
|
filterTaskData: function() {
|
||||||
|
let list = [];
|
||||||
|
this.filterTasks.forEach((task, index) => {
|
||||||
|
let data = {
|
||||||
|
label: task.label,
|
||||||
|
occ_value: Number(task.occurrence_ratio * 100),
|
||||||
|
occurrences: Number(task.occurrences).toLocaleString('en-US'),
|
||||||
|
occurrence_ratio: this.getPercentLabel(task.occurrence_ratio),
|
||||||
|
case_value: Number(task.case_ratio * 100),
|
||||||
|
cases: task.cases.toLocaleString('en-US'),
|
||||||
|
case_ratio: this.getPercentLabel(task.case_ratio),
|
||||||
|
};
|
||||||
|
list.push(data);
|
||||||
|
});
|
||||||
|
list.sort((x, y) => y.occurrences - x.occurrences);
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
// Start and End Task
|
||||||
|
filterStartData: function() {
|
||||||
|
return this.setActData(this.filterStartToEnd);
|
||||||
|
},
|
||||||
|
filterEndData: function() {
|
||||||
|
return this.setActData(this.filterEndToStart);
|
||||||
|
},
|
||||||
|
filterStartToEndData: function() {
|
||||||
|
return this.isEndSelected ? this.setStartAndEndData(this.filterEndToStart, this.rowData, 'sources') : this.setActData(this.filterStartToEnd);
|
||||||
|
},
|
||||||
|
filterEndToStartData: function() {
|
||||||
|
return this.isStartSelected ? this.setStartAndEndData(this.filterStartToEnd, this.rowData, 'sinks') : this.setActData(this.filterEndToStart);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* @param {string} switch Summary or Insight
|
||||||
|
*/
|
||||||
|
switchTab(tab) {
|
||||||
|
this.tab = tab;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Number to percentage
|
||||||
|
* @param {number} val
|
||||||
|
* @returns {string} 轉換完成的百分比字串
|
||||||
|
*/
|
||||||
|
getPercentLabel(val){
|
||||||
|
return (val * 100 === 100) ? `${val * 100}%` : `${(val * 100).toFixed(1)}%`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* set progress bar width
|
||||||
|
* @param {number} value
|
||||||
|
* @returns {string} 樣式的寬度設定
|
||||||
|
*/
|
||||||
|
progressWidth(value){
|
||||||
|
return `width:${value}%;`
|
||||||
|
},
|
||||||
|
// 調整 filterStartData / filterEndData / filterStartToEndData / filterEndToStartData 的內容
|
||||||
|
/**
|
||||||
|
* @param {array} array filterStartToEnd / filterEndToStart
|
||||||
|
*/
|
||||||
|
setActData(array) {
|
||||||
|
let list = [];
|
||||||
|
array.forEach((task, index) => {
|
||||||
|
let data = {
|
||||||
|
label: task.label,
|
||||||
|
occ_value: Number(task.occurrence_ratio * 100),
|
||||||
|
occurrences: Number(task.occurrences).toLocaleString('en-US'),
|
||||||
|
occurrence_ratio: this.getPercentLabel(task.occurrence_ratio),
|
||||||
|
};
|
||||||
|
list.push(data);
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {array} select select Have activity(s) rows
|
||||||
|
*/
|
||||||
|
onRowAct(select){
|
||||||
|
this.selectFilterTask = select;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {object} e select Start rows
|
||||||
|
*/
|
||||||
|
onRowStart(e){
|
||||||
|
this.selectFilterStart = e.data;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {object} e select End rows
|
||||||
|
*/
|
||||||
|
onRowEnd(e){
|
||||||
|
this.selectFilterEnd = e.data;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {array} e Update List Seq
|
||||||
|
*/
|
||||||
|
onUpdateListSeq(listSeq) {
|
||||||
|
console.log(this.listSeq);
|
||||||
|
this.listSeq = listSeq;
|
||||||
|
},
|
||||||
|
// 在 Start & End 若第一次選擇 start, 則 end 連動改變,若第一次選擇 end, 則 start 連動改變
|
||||||
|
/**
|
||||||
|
* @param {object} e object contains selected row's data
|
||||||
|
*/
|
||||||
|
startRow(e){
|
||||||
|
this.selectFilterStartToEnd = e.data;
|
||||||
|
if(this.isStartSelected === null || this.isStartSelected === true){
|
||||||
|
this.isStartSelected = true;
|
||||||
|
this.isEndSelected = false;
|
||||||
|
this.rowData = e.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
endRow(e) {
|
||||||
|
this.selectFilterEndToStart = e.data;
|
||||||
|
if(this.isEndSelected === null || this.isEndSelected === true){
|
||||||
|
this.isEndSelected = true;
|
||||||
|
this.isStartSelected = false;
|
||||||
|
this.rowData = e.data;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 重新設定連動的 filterStartToEndData / filterEndToStartData 內容
|
||||||
|
/**
|
||||||
|
* @param {array} eventData Start or End List
|
||||||
|
* @param {object} rowData 所選擇的 row's data
|
||||||
|
* @param {string} event sinks / sources
|
||||||
|
*/
|
||||||
|
setStartAndEndData(eventData, rowData, event){
|
||||||
|
const filterData = event === 'sinks' ? this.filterEndToStart : this.filterStartToEnd;
|
||||||
|
const relatedItems = eventData
|
||||||
|
.find(task => task.label === rowData.label)
|
||||||
|
?.[event]?.filter(item => filterData.some(ele => ele.label === item))
|
||||||
|
?.map(item => filterData.find(ele => ele.label === item));
|
||||||
|
|
||||||
|
if (!relatedItems) return [];
|
||||||
|
return relatedItems.map(item => ({
|
||||||
|
label: item.label,
|
||||||
|
occ_value: Number(item.occurrence_ratio * 100),
|
||||||
|
occurrences: Number(item.occurrences).toLocaleString('en-US'),
|
||||||
|
occurrence_ratio: this.getPercentLabel(item.occurrence_ratio),
|
||||||
|
}));
|
||||||
|
// 以下是優化前的程式碼:
|
||||||
|
// let list = [];
|
||||||
|
// eventData.forEach((task) => {
|
||||||
|
// if(task.label === rowData.label) {
|
||||||
|
// task[event].forEach(item => {
|
||||||
|
// const filterData = event === 'sinks' ? this.filterEndToStart : this.filterStartToEnd;
|
||||||
|
// const element = filterData.find(ele => ele.label === item);
|
||||||
|
// if (element !== undefined) {
|
||||||
|
// const data = {
|
||||||
|
// label: element.label,
|
||||||
|
// occ_value: Number(element.occurrence_ratio * 100),
|
||||||
|
// occurrences: Number(element.occurrences).toLocaleString('en-US'),
|
||||||
|
// occurrence_ratio: this.getPercentLabel(element.occurrence_ratio),
|
||||||
|
// };
|
||||||
|
// list.push(data);
|
||||||
|
// };
|
||||||
|
// })
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
// return list;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 清空選項
|
||||||
|
*/
|
||||||
|
reset() {
|
||||||
|
this.selectFilterTask = null;
|
||||||
|
this.selectFilterStart = null;
|
||||||
|
this.selectFilterEnd = null;
|
||||||
|
this.selectFilterStartToEnd = null;
|
||||||
|
this.selectFilterEndToStart = null;
|
||||||
|
this.listSeq = [];
|
||||||
|
this.isStartSelected = null;
|
||||||
|
this.isEndSelected = null;
|
||||||
|
// this.rowData = [];
|
||||||
|
console.log('reset');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#searchFiles::-webkit-search-cancel-button{
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(trace, key) in traceList" :key="key" class=" cursor-pointer hover:text-primary" @dblclick="switchCaseData(trace.id)">
|
<tr v-for="(trace, key) in traceList" :key="key" class=" cursor-pointer hover:text-primary" @click="switchCaseData(trace.id)">
|
||||||
<td class="text-xs p-2">#{{ trace.id }}</td>
|
<td class="text-xs p-2">#{{ trace.id }}</td>
|
||||||
<td class="text-xs p-2 w-24">
|
<td class="text-xs p-2 w-24">
|
||||||
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
<section class="pl-4 h-full w-[calc(100%_-_320px)]">
|
<section class="pl-4 h-full w-[calc(100%_-_320px)]">
|
||||||
<p class="h2 mb-2">Trace #{{ showTraceId }}</p>
|
<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-52 w-full px-2 mb-2 border border-neutral-300 rounded">
|
||||||
<div class="h-full w-full scrollbar overflow-x-auto">
|
<div class="h-full w-full">
|
||||||
<div id="cyTrace" ref="cyTrace" class="h-full min-w-full relative"></div>
|
<div id="cyTrace" ref="cyTrace" class="h-full min-w-full relative"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
86
src/components/Discover/table/actAndSeq.vue
Normal file
86
src/components/Discover/table/actAndSeq.vue
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<!-- Activity List -->
|
||||||
|
<div class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full">
|
||||||
|
<div class="flex justify-between items-center my-2 flex-wrap">
|
||||||
|
<p class="h2">Activity List ({{ data.length }})</p>
|
||||||
|
</div>
|
||||||
|
<!-- Table -->
|
||||||
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_64px)]">
|
||||||
|
<table class="border-separate border-spacing-x-2 table-auto min-w-full" :class="data.length === 0? 'h-full': null">
|
||||||
|
<thead class="sticky top-0 left-0 z-10 bg-neutral-10">
|
||||||
|
<tr>
|
||||||
|
<th class="text-start text-base font-semibold leading-10 px-2 border-b border-neutral-500">Activity</th>
|
||||||
|
<th class="text-base font-semibold leading-10 px-2 border-b border-neutral-500 text-start" colspan="3">Occurrences</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<Draggable :list="data" group="people" itemKey="name" tag="tbody" animation="300" @end="onEnd">
|
||||||
|
<template #item="{ element, index }">
|
||||||
|
<tr>
|
||||||
|
<td class="px-4 py-2">{{ element.label }}</td>
|
||||||
|
<td class="px-4 py-2 w-24">
|
||||||
|
<div class="h-4 min-w-[96px] bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(element.occ_value)"></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2 text-right">{{ element.occurrences }}</td>
|
||||||
|
<td class="px-4 py-2 text-right">{{ element.occurrence_ratio }}</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</Draggable>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Sequence -->
|
||||||
|
<div class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 pb-4 w-full h-full relative">
|
||||||
|
<p class="h2 border-b border-500 my-2">Sequence ({{ listSeq.length }})</p>
|
||||||
|
<!-- No Data -->
|
||||||
|
<div v-if="listSequence.length === 0" class="p-4 w-[calc(100%_-_32px)] h-5/6 flex justify-center items-center absolute">
|
||||||
|
<p class="text-neutral-500">Please drag and drop activity(s) here and sort.</p>
|
||||||
|
</div>
|
||||||
|
<!-- Have Data -->
|
||||||
|
<div class="py-4 m-auto w-full h-[calc(100%_-_56px)]">
|
||||||
|
<div class="w-full h-full overflow-y-auto overflow-x-auto scrollbar px-4 text-center">
|
||||||
|
<draggable class="h-full" :list="listSequence" group="people" itemKey="name" animation="300" @end="onEnd">
|
||||||
|
<template #item="{ element, index }">
|
||||||
|
<div>
|
||||||
|
<div class="w-full p-2 border border-primary rounded text-primary">
|
||||||
|
<span>{{ element.label }}</span>
|
||||||
|
</div>
|
||||||
|
<span v-show="index !== listSeq.length - 1" class="pi pi-chevron-down !text-lg inline-block py-2 "></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
filterTaskData: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
progressWidth: {
|
||||||
|
type: Function,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
listSeq: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
listSequence: this.listSeq,
|
||||||
|
data: this.filterTaskData,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onEnd() {
|
||||||
|
this.$emit('update:listSeq', this.listSequence);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
71
src/components/Discover/table/actOcc.vue
Normal file
71
src/components/Discover/table/actOcc.vue
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full">
|
||||||
|
<div class="flex justify-between items-center my-2 flex-wrap">
|
||||||
|
<p class="h2">{{ tableTitle }} ({{ tableData.length }})</p>
|
||||||
|
<!-- Search -->
|
||||||
|
<!-- <Search></Search> -->
|
||||||
|
</div>
|
||||||
|
<!-- Table -->
|
||||||
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_64px)]">
|
||||||
|
<DataTable v-model:selection="select" :value="tableData" dataKey="label" tableClass="w-full !border-separate !border-spacing-x-2 !table-auto" @row-select="onRowSelect">
|
||||||
|
<ColumnGroup type="header">
|
||||||
|
<Row>
|
||||||
|
<Column selectionMode="single" headerClass="w-8 !p-2 !bg-neutral-10 !border-neutral-500 sticky top-0 left-0 z-10 bg-neutral-10"></Column>
|
||||||
|
<Column field="label" header="Activity" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable />
|
||||||
|
<Column field="occ_value" header="Occurrences" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable :colspan="3" />
|
||||||
|
</Row>
|
||||||
|
</ColumnGroup>
|
||||||
|
<Column selectionMode="single" bodyClass="!p-2 !border-0"></Column>
|
||||||
|
<Column field="label" header="Activity" bodyClass="break-words !py-2 !border-0"></Column>
|
||||||
|
<Column header="進度條" bodyClass="!py-2 !border-0 min-w-[96px]">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(slotProps.data.occ_value)"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="occurrences" header="Occurrences" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
<Column field="occurrence_ratio" header="Occurrence Ratio" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Search from '@/components/Search.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
tableTitle: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
tableSelect: {
|
||||||
|
type: [Object, Array],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
progressWidth: {
|
||||||
|
type: Function,
|
||||||
|
required: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
select: this.tableSelect,
|
||||||
|
metaKey: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Search,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRowSelect(e) {
|
||||||
|
this.$emit('on-row-select', e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
92
src/components/Discover/table/actOccCase.vue
Normal file
92
src/components/Discover/table/actOccCase.vue
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<template>
|
||||||
|
<div class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 h-full">
|
||||||
|
<div class="flex justify-between items-center my-2">
|
||||||
|
<p class="h2">{{ tableTitle }} ({{ data.length }})</p>
|
||||||
|
<!-- Search -->
|
||||||
|
<!-- <Search></Search> -->
|
||||||
|
</div>
|
||||||
|
<!-- Table -->
|
||||||
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_64px)]">
|
||||||
|
<DataTable v-model:selection="select" :value="data" tableClass="w-full !border-separate !border-spacing-x-2 !table-auto" @row-select="onRowSelect" @row-unselect="onRowUnselect" @row-select-all="onRowSelectAll" @row-unselect-all="onRowUnelectAll">
|
||||||
|
<ColumnGroup type="header">
|
||||||
|
<Row>
|
||||||
|
<Column selectionMode="multiple" headerClass="w-8 !p-2 !bg-neutral-10 !border-neutral-500 sticky top-0 left-0 z-10 bg-neutral-10"></Column>
|
||||||
|
<Column field="label" header="Activity" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable />
|
||||||
|
<Column field="occ_value" header="Occurrences" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable :colspan="3" />
|
||||||
|
<Column field="case_value" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" header="Cases with Activity" sortable :colspan="3" />
|
||||||
|
</Row>
|
||||||
|
</ColumnGroup>
|
||||||
|
<Column selectionMode="multiple" bodyClass="!p-2 !border-0"></Column>
|
||||||
|
<Column field="label" header="Activity" bodyClass="break-words !py-2 !border-0"></Column>
|
||||||
|
<Column header="進度條" bodyClass="!py-2 !border-0 min-w-[96px]">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(slotProps.data.occ_value)"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="occurrences" header="Occurrences" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
<Column field="occurrence_ratio" header="O2" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
<Column header="進度條" bodyClass="!py-2 !border-0 min-w-[96px]">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(slotProps.data.case_value)"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="cases" header="Cases with Activity" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
<Column field="case_ratio" header="C2" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Search from '@/components/Search.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
tableTitle: {
|
||||||
|
type: String,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
tableSelect: {
|
||||||
|
type: Array,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
progressWidth: {
|
||||||
|
type: Function,
|
||||||
|
require: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
select: this.tableSelect,
|
||||||
|
data: this.tableData
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Search,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRowSelect() {
|
||||||
|
this.$emit('on-row-select', this.select);
|
||||||
|
},
|
||||||
|
onRowUnselect() {
|
||||||
|
this.$emit('on-row-select', this.select);
|
||||||
|
},
|
||||||
|
onRowSelectAll(e) {
|
||||||
|
this.select = e.data;
|
||||||
|
this.$emit('on-row-select', this.select);
|
||||||
|
},
|
||||||
|
onRowUnelectAll(e) {
|
||||||
|
this.select = null;
|
||||||
|
this.$emit('on-row-select', this.select)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<span class="absolute top-2 bottom-1.5 right-0.5 flex justify-center items-center gap-2">
|
<span class="absolute top-2 bottom-1.5 right-0.5 flex justify-center items-center gap-2">
|
||||||
<IconSetting class="w-6 h-6 cursor-pointer"></IconSetting>
|
<IconSetting class="w-6 h-6 cursor-pointer"></IconSetting>
|
||||||
<span class="w-px h-6 block after:border after:border-neutral-300 after:content-['']"></span>
|
<span class="w-px h-6 block after:border after:border-neutral-300 after:content-['']"></span>
|
||||||
<button class="pr-2 py-1 rounded-r-full">
|
<button class="pr-2">
|
||||||
<IconSearch class="w-6 h-6"></IconSearch>
|
<IconSearch class="w-6 h-6"></IconSearch>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import filesStore from '@/stores/files.js';
|
import filesStore from '@/stores/files.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';
|
||||||
|
|
||||||
|
|||||||
26
src/components/Search.vue
Normal file
26
src/components/Search.vue
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<form role="search">
|
||||||
|
<label for="searchFiles" class="mr-4 relative">
|
||||||
|
<input type="search" id="searchFiles" placeholder="Search Activity" class="px-5 py-2 w-52 rounded-full text-sm align-middle duration-300 border bg-neutral-100 border-neutral-300 hover:border-neutral-500 focus:outline-none focus:ring focus:border-neutral-500">
|
||||||
|
<span class="absolute top-2 bottom-0.5 right-0.5 flex justify-center items-center gap-2">
|
||||||
|
<IconSetting class="w-6 h-6 cursor-pointer"></IconSetting>
|
||||||
|
<span class="w-px h-6 block after:border after:border-neutral-300 after:content-['']"></span>
|
||||||
|
<button class="pr-2">
|
||||||
|
<IconSearch class="w-6 h-6"></IconSearch>
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import IconSearch from '@/components/icons/IconSearch.vue';
|
||||||
|
import IconSetting from '@/components/icons/IconSetting.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
IconSearch,
|
||||||
|
IconSetting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -11,6 +11,7 @@ import ToastPlugin from 'vue-toast-notification';
|
|||||||
import cytoscape from 'cytoscape';
|
import cytoscape from 'cytoscape';
|
||||||
import dagre from 'cytoscape-dagre';
|
import dagre from 'cytoscape-dagre';
|
||||||
import popper from 'cytoscape-popper';
|
import popper from 'cytoscape-popper';
|
||||||
|
import draggable from 'vuedraggable';
|
||||||
|
|
||||||
// import CSS
|
// import CSS
|
||||||
import "./assets/main.css";
|
import "./assets/main.css";
|
||||||
@@ -31,7 +32,9 @@ import TabPanel from 'primevue/tabpanel';
|
|||||||
import DataTable from 'primevue/datatable';
|
import DataTable from 'primevue/datatable';
|
||||||
import Column from 'primevue/column';
|
import Column from 'primevue/column';
|
||||||
import ColumnGroup from 'primevue/columngroup'; // optional
|
import ColumnGroup from 'primevue/columngroup'; // optional
|
||||||
import Row from 'primevue/row';
|
import Row from 'primevue/row'; // optional
|
||||||
|
import RadioButton from 'primevue/radiobutton';
|
||||||
|
import PickList from 'primevue/picklist';
|
||||||
|
|
||||||
const emitter = mitt();
|
const emitter = mitt();
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
@@ -71,5 +74,8 @@ app.component('DataTable', DataTable);
|
|||||||
app.component('Column', Column);
|
app.component('Column', Column);
|
||||||
app.component('ColumnGroup', ColumnGroup);
|
app.component('ColumnGroup', ColumnGroup);
|
||||||
app.component('Row', Row);
|
app.component('Row', Row);
|
||||||
|
app.component('RadioButton', RadioButton);
|
||||||
|
app.component('PickList', PickList);
|
||||||
|
app.component('Draggable', draggable); // 拖曳
|
||||||
|
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ export default defineStore('allMapDataStore', {
|
|||||||
allTrace: [],
|
allTrace: [],
|
||||||
allCase: [],
|
allCase: [],
|
||||||
allTraceTaskSeq: [],
|
allTraceTaskSeq: [],
|
||||||
|
allFilterTask: [],
|
||||||
|
allFilterStartToEnd: [],
|
||||||
|
allFilterEndToStart: [],
|
||||||
|
allFilterTimeframe: {},
|
||||||
|
allFilterTrace: [],
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
@@ -44,7 +49,25 @@ export default defineStore('allMapDataStore', {
|
|||||||
},
|
},
|
||||||
traceTaskSeq: state => {
|
traceTaskSeq: state => {
|
||||||
return state.allTraceTaskSeq;
|
return state.allTraceTaskSeq;
|
||||||
}
|
},
|
||||||
|
// All tasks
|
||||||
|
filterTasks: state => {
|
||||||
|
return state.allFilterTask;
|
||||||
|
},
|
||||||
|
// form start to end tasks
|
||||||
|
filterStartToEnd: state => {
|
||||||
|
return state.allFilterStartToEnd;
|
||||||
|
},
|
||||||
|
// form end to start tasks
|
||||||
|
filterEndToStart: state => {
|
||||||
|
return state.allFilterEndToStart;
|
||||||
|
},
|
||||||
|
filterTimeframe: state => {
|
||||||
|
return state.allFilterTimeframe;
|
||||||
|
},
|
||||||
|
filterTrace: state => {
|
||||||
|
return state.allFilterTrace;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
/**
|
/**
|
||||||
@@ -80,12 +103,10 @@ export default defineStore('allMapDataStore', {
|
|||||||
*/
|
*/
|
||||||
async getAllTrace() {
|
async getAllTrace() {
|
||||||
let logId = this.logId;
|
let logId = this.logId;
|
||||||
// const api = `/api/filters/params?log_id=${logId}`;
|
|
||||||
const api = `/api/logs/${logId}/traces`;
|
const api = `/api/logs/${logId}/traces`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await this.$axios.get(api);
|
||||||
console.log(response);
|
|
||||||
this.allTrace = response.data;
|
this.allTrace = response.data;
|
||||||
|
|
||||||
if(this.httpStatus < 300) loading.isLoading = false;
|
if(this.httpStatus < 300) loading.isLoading = false;
|
||||||
@@ -134,5 +155,34 @@ export default defineStore('allMapDataStore', {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* fetch Filter Parameters api.
|
||||||
|
*/
|
||||||
|
async getFilterParams() {
|
||||||
|
let logId = this.logId;
|
||||||
|
const api = `/api/filters/params?log_id=${logId}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await this.$axios.get(api);
|
||||||
|
this.allFilterTask = response.data.tasks;
|
||||||
|
this.allFilterStartToEnd = response.data.sources;
|
||||||
|
this.allFilterEndToStart = response.data.sinks;
|
||||||
|
this.allFilterTimeframe = response.data.timeframe;
|
||||||
|
this.allFilterTrace = response.data.trace;
|
||||||
|
|
||||||
|
if(this.httpStatus < 300) loading.isLoading = false;
|
||||||
|
} catch(error) {
|
||||||
|
this.httpStatus = error.request.status;
|
||||||
|
delay().then(() =>{
|
||||||
|
loading.isLoading = true;
|
||||||
|
return delay(1000);
|
||||||
|
}).then(()=>{
|
||||||
|
loading.isLoading = false;
|
||||||
|
return delay(500);
|
||||||
|
}).then(() => {
|
||||||
|
$toast.default('Failed to load the Filter Parameters.');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- Sidebar: Switch data type -->
|
<!-- Sidebar: Switch data type -->
|
||||||
<div class="flex flex-col justify-between py-4 w-14 h-screen-main absolute bottom-0 left-0 z-10" :class="sidebarLeftValue? 'bg-neutral-100':''">
|
<div class="flex flex-col justify-between py-4 w-14 h-screen-main absolute bottom-0 left-0 z-10" :class="sidebarLeftValue? 'bg-neutral-50':''">
|
||||||
<ul class="space-y-4 flex flex-col justify-center items-center">
|
<ul class="space-y-4 flex flex-col justify-center items-center">
|
||||||
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-100 drop-shadow hover:border-primary" @click="sidebarView = true" :class="{'border-primary': sidebarView}">
|
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-50 drop-shadow hover:border-primary" @click="sidebarView = true" :class="{'border-primary': sidebarView}">
|
||||||
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarView ? 'text-primary' : 'text-neutral-500']">
|
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarView ? 'text-primary' : 'text-neutral-500']">
|
||||||
track_changes
|
track_changes
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-100 drop-shadow hover:border-primary" @click="sidebarFilter = true" :class="{'border-primary': sidebarFilter}">
|
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-50 drop-shadow hover:border-primary" @click="sidebarFilter = true" :class="{'border-primary': sidebarFilter}">
|
||||||
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarFilter ? 'text-primary' : 'text-neutral-500']">
|
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarFilter ? 'text-primary' : 'text-neutral-500']">
|
||||||
tornado
|
tornado
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-100 drop-shadow hover:border-primary" @click="sidebarTraces = true" :class="{'border-primary': sidebarTraces}">
|
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-50 drop-shadow hover:border-primary" @click="sidebarTraces = true" :class="{'border-primary': sidebarTraces}">
|
||||||
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarTraces ? 'text-primary' : 'text-neutral-500']">
|
<span class="material-symbols-outlined text-2xl hover:text-primary p-1.5" :class="[sidebarTraces ? 'text-primary' : 'text-neutral-500']">
|
||||||
rebase
|
rebase
|
||||||
</span>
|
</span>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="flex flex-col justify-center items-center">
|
<ul class="flex flex-col justify-center items-center">
|
||||||
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-100 drop-shadow hover:border-primary">
|
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-50 drop-shadow hover:border-primary">
|
||||||
<span class="material-symbols-outlined text-2xl text-neutral-500 hover:text-primary p-1.5">
|
<span class="material-symbols-outlined text-2xl text-neutral-500 hover:text-primary p-1.5">
|
||||||
highlight
|
highlight
|
||||||
</span>
|
</span>
|
||||||
@@ -29,14 +29,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Cytoscape Map -->
|
<!-- Cytoscape Map -->
|
||||||
<div class="min-w-full h-screen-main bg-neutral-100 -z-40">
|
<div class="min-w-full h-screen-main bg-neutral-50 -z-40">
|
||||||
<div id="cy" class="min-w-full h-screen-main"></div>
|
<div id="cy" class="min-w-full h-screen-main"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sidebar: State -->
|
<!-- Sidebar: State -->
|
||||||
<div class="bg-transparent py-4 w-14 h-screen-main z-10 bottom-0 right-0 absolute">
|
<div class="bg-transparent py-4 w-14 h-screen-main z-10 bottom-0 right-0 absolute">
|
||||||
<ul class="flex flex-col justify-center items-center">
|
<ul class="flex flex-col justify-center items-center">
|
||||||
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-100 drop-shadow hover:border-primary" @click="sidebarState = true" :class="{'border-primary': sidebarState}">
|
<li class="inline-flex items-center justify-center border border-neutral-500 rounded-full w-9 h-9 cursor-pointer bg-neutral-50 drop-shadow hover:border-primary" @click="sidebarState = true" :class="{'border-primary': sidebarState}">
|
||||||
<span class="material-symbols-outlined text-2xl text-neutral-500 hover:text-primary p-1.5" :class="[sidebarState ? 'text-primary' : 'text-neutral-500']">
|
<span class="material-symbols-outlined text-2xl text-neutral-500 hover:text-primary p-1.5" :class="[sidebarState ? 'text-primary' : 'text-neutral-500']">
|
||||||
info
|
info
|
||||||
</span>
|
</span>
|
||||||
@@ -48,34 +48,8 @@
|
|||||||
<SidebarView v-model:visible="sidebarView" @switch-map-type="switchMapType" @switch-curve-styles="switchCurveStyles" @switch-rank="switchRank" @switch-data-layer-type="switchDataLayerType" ></SidebarView>
|
<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>
|
<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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Sidebar v-model:visible="sidebarFilter" :closeIcon="'pi pi-chevron-left'" :modal="false" position="left" :dismissable="true" class="!w-11/12">
|
|
||||||
<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': ''">Filter</li>
|
|
||||||
<li class="h1 border-r-2 border-neutral-300 pr-4 cursor-pointer hover:text-neutral-900 hover:duration-700" @click="switchTab('funnel')" :class="tab === 'funnel'? 'text-neutral-900': ''">Funnel</li>
|
|
||||||
</ul>
|
|
||||||
</template>
|
|
||||||
<!-- header: filter -->
|
|
||||||
<div v-if="tab === 'filter'" class="pt-4 bg-neutral-100">
|
|
||||||
<!-- filter silect -->
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<p class="h2">Filter Type</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- header: funnel -->
|
|
||||||
<div v-if="tab === 'funnel'"></div>
|
|
||||||
</Sidebar>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -86,21 +60,22 @@ import cytoscapeMap from '@/module/cytoscapeMap.js';
|
|||||||
import SidebarView from '@/components/Discover/sidebarView.vue';
|
import SidebarView from '@/components/Discover/sidebarView.vue';
|
||||||
import SidebarState from '@/components/Discover/sidebarState.vue';
|
import SidebarState from '@/components/Discover/sidebarState.vue';
|
||||||
import SidebarTraces from '@/components/Discover/sidebarTraces.vue';
|
import SidebarTraces from '@/components/Discover/sidebarTraces.vue';
|
||||||
|
import SidebarFilter from '@/components/Discover/sidebarFilter.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
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 } = storeToRefs(allMapDataStore);
|
const { processMap, bpmn, stats, insights, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
return { isLoading, processMap, bpmn, stats, insights, traces, traceTaskSeq,cases, allMapDataStore,}
|
return { isLoading, processMap, bpmn, stats, insights, traces, traceTaskSeq, cases, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, allMapDataStore}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
SidebarView,
|
SidebarView,
|
||||||
SidebarState,
|
SidebarState,
|
||||||
SidebarTraces,
|
SidebarTraces,
|
||||||
// SidebarFilter,
|
SidebarFilter,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -126,8 +101,6 @@ export default {
|
|||||||
sidebarState: false, // SideBar: Summary & Insight
|
sidebarState: false, // SideBar: Summary & Insight
|
||||||
sidebarTraces: false, // SideBar: Traces
|
sidebarTraces: false, // SideBar: Traces
|
||||||
sidebarFilter: false, // SideBar: Filter
|
sidebarFilter: false, // SideBar: Filter
|
||||||
|
|
||||||
tab: 'filter',
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed:{
|
computed:{
|
||||||
@@ -137,12 +110,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
|
||||||
* @param {string} switch Summary or Insight
|
|
||||||
*/
|
|
||||||
switchTab(tab) {
|
|
||||||
this.tab = tab;
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* switch map type
|
* switch map type
|
||||||
* @param {string} type processMap | bpmn
|
* @param {string} type processMap | bpmn
|
||||||
@@ -333,6 +300,8 @@ export default {
|
|||||||
await this.allMapDataStore.getTraceDetail();
|
await this.allMapDataStore.getTraceDetail();
|
||||||
|
|
||||||
this.createCy(this.mapType);
|
this.createCy(this.mapType);
|
||||||
|
|
||||||
|
this.allMapDataStore.getFilterParams();
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// this.isLoading = false;
|
// this.isLoading = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user