Map Attributes: type 'boolean' layout done.
This commit is contained in:
136
src/components/Discover/Map/Filter/Attributes.vue
Normal file
136
src/components/Discover/Map/Filter/Attributes.vue
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<section class="h-full">
|
||||||
|
<p class="h2 ml-1 mb-2">Activity Select</p>
|
||||||
|
<!-- selectedAttName: {{ selectedAttName }} -->
|
||||||
|
<!-- selectedAttRange: {{ selectedAttRange }} -->
|
||||||
|
<div class="flex flex-row justify-between items-start gap-4 w-full h-[calc(100%_-_48px)]">
|
||||||
|
<!-- Attribute Name -->
|
||||||
|
<div class="basis-1/3 bg-neutral-10 border border-neutral-300 rounded-xl px-4 pb-4 w-full h-full relative text-sm">
|
||||||
|
<p class="h2 border-b border-500 my-2">Attribute Name (13)</p>
|
||||||
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_56px)]">
|
||||||
|
<DataTable v-model:selection="selectedAttName" :value="filterAttrs" dataKey="key" breakpoint="0" :tableClass="tableClass">
|
||||||
|
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
||||||
|
<Column field="key" header="Activity" :headerClass="headerClass" :bodyClass="bodyClass" sortable></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Range Selection -->
|
||||||
|
<div class="basis-2/3 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">Range Selection</p>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_70px)]">
|
||||||
|
<div v-if="selectedAttName?.type === 'boolean'">
|
||||||
|
<DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="id" breakpoint="0" :tableClass="tableClass" @row-select="onRowSelect">
|
||||||
|
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
||||||
|
<Column field="label" header="Activity" :headerClass="headerClass" :bodyClass="bodyClass"></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="selectedAttName?.type === 'string'">
|
||||||
|
string
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
other
|
||||||
|
</div>
|
||||||
|
<!-- <DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="label" breakpoint="0" tableClass="w-full !border-separate !border-spacing-x-2 !table-auto text-sm" @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="occurrences_base" 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>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup() {
|
||||||
|
const allMapDataStore = AllMapDataStore();
|
||||||
|
const { filterAttrs } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
|
return { filterAttrs }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedAttName: null,
|
||||||
|
selectedAttRange: null,
|
||||||
|
tableClass: 'w-full h-full !border-separate !border-spacing-x-2 !table-auto text-sm',
|
||||||
|
headerModeClass: 'w-8 !p-2 !bg-neutral-10 !border-neutral-500 sticky top-0 left-0 z-10 bg-neutral-10',
|
||||||
|
headerClass: '!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10',
|
||||||
|
bodyModeClass: '!p-2 !border-0',
|
||||||
|
bodyClass: 'break-words !py-2 !border-0',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
attRangeData: function() {
|
||||||
|
let data = [];
|
||||||
|
const type = this.selectedAttName.type;
|
||||||
|
const valueTypes = ['int', 'float', 'date'];
|
||||||
|
const classTypes = ['boolean', 'string'];
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'boolean':
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
key: this.selectedAttName.key,
|
||||||
|
type: 'boolean',
|
||||||
|
value: true,
|
||||||
|
label: 'Yes'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
key: this.selectedAttName.key,
|
||||||
|
type: 'boolean',
|
||||||
|
value: false,
|
||||||
|
label: 'No'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
return data;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(valueTypes.includes(type)){
|
||||||
|
// data = {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }else if(classTypes.includes(type)){
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onRowSelect(e) {
|
||||||
|
// this.$emit('on-row-select', e)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* set progress bar width
|
||||||
|
* @param {number} value
|
||||||
|
* @returns {string} 樣式的寬度設定
|
||||||
|
*/
|
||||||
|
progressWidth(value){
|
||||||
|
return `width:${value}%;`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -38,13 +38,14 @@
|
|||||||
<label :for="item + index">{{ item }}</label>
|
<label :for="item + index">{{ item }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-show="selectValue[0] === 'Attributes'">
|
<!-- 目前只有 case -->
|
||||||
|
<!-- <div v-show="selectValue[0] === 'Attributes'">
|
||||||
<p class="h2">Mode</p>
|
<p class="h2">Mode</p>
|
||||||
<div v-for="(item, index) in selectFilter['ModeAtt']" :key="index">
|
<div v-for="(item, index) in selectFilter['ModeAtt']" :key="index">
|
||||||
<RadioButton v-model="selectValue[4]" :inputId="item + index" name="ModeAtt" :value="item" class="mb-1 mr-2"/>
|
<RadioButton v-model="selectValue[4]" :inputId="item + index" name="ModeAtt" :value="item" class="mb-1 mr-2"/>
|
||||||
<label :for="item + index">{{ item }}</label>
|
<label :for="item + index">{{ item }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
<div>
|
<div>
|
||||||
<p class="h2">Refine</p>
|
<p class="h2">Refine</p>
|
||||||
<div v-for="(item, index) in selectFilter['Refine']" :key="index">
|
<div v-for="(item, index) in selectFilter['Refine']" :key="index">
|
||||||
@@ -63,10 +64,10 @@
|
|||||||
<!-- Fiter content -->
|
<!-- Fiter content -->
|
||||||
<div class="w-[calc(100%_-_208px)] h-full">
|
<div class="w-[calc(100%_-_208px)] h-full">
|
||||||
<!-- Filter titles -->
|
<!-- Filter titles -->
|
||||||
<div class="space-y-2 w-full h-[calc(100%_-_48px)]">
|
<div class="w-full h-[calc(100%_-_56px)] mb-2">
|
||||||
<!-- title: Activity Select -->
|
<!-- title: Activity Select -->
|
||||||
<div class="w-full h-[calc(100%_-_40px)]" v-if="selectValue[0] === 'Sequence'">
|
<div class="w-full h-[calc(100%_-_48px)]" v-if="selectValue[0] === 'Sequence'">
|
||||||
<p class="h2 ml-1">Activity Select</p>
|
<p class="h2 ml-1 mb-2">Activity Select</p>
|
||||||
<!-- Filter task Data-->
|
<!-- Filter task 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>
|
<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>
|
||||||
<!-- Filter Start Data -->
|
<!-- Filter Start Data -->
|
||||||
@@ -83,6 +84,8 @@
|
|||||||
<ActAndSeq :filterTaskData="filterTaskData" :progressWidth ="progressWidth" :listSeq="listSeq" @update:listSeq="onUpdateListSeq"></ActAndSeq>
|
<ActAndSeq :filterTaskData="filterTaskData" :progressWidth ="progressWidth" :listSeq="listSeq" @update:listSeq="onUpdateListSeq"></ActAndSeq>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- title: Attributes -->
|
||||||
|
<Attributes v-if="selectValue[0] === 'Attributes'"></Attributes>
|
||||||
<!-- title: Trace -->
|
<!-- title: Trace -->
|
||||||
<Trace v-if="selectValue[0] === 'Trace'" ref="filterTraceView"></Trace>
|
<Trace v-if="selectValue[0] === 'Trace'" ref="filterTraceView"></Trace>
|
||||||
<!-- title: Timeframes -->
|
<!-- title: Timeframes -->
|
||||||
@@ -109,6 +112,7 @@ import AllMapDataStore from '@/stores/allMapData.js';
|
|||||||
import ActOccCase from '@/components/Discover/Map/Filter/ActOccCase.vue';
|
import ActOccCase from '@/components/Discover/Map/Filter/ActOccCase.vue';
|
||||||
import ActOcc from '@/components/Discover/Map/Filter/ActOcc.vue';
|
import ActOcc from '@/components/Discover/Map/Filter/ActOcc.vue';
|
||||||
import ActAndSeq from '@/components/Discover/Map/Filter/ActAndSeq.vue';
|
import ActAndSeq from '@/components/Discover/Map/Filter/ActAndSeq.vue';
|
||||||
|
import Attributes from '@/components/Discover/Map/Filter/Attributes.vue';
|
||||||
import Funnel from '@/components/Discover/Map/Filter/Funnel.vue';
|
import Funnel from '@/components/Discover/Map/Filter/Funnel.vue';
|
||||||
import Trace from '@/components/Discover/Map/Filter/Trace.vue';
|
import Trace from '@/components/Discover/Map/Filter/Trace.vue';
|
||||||
import Timeframes from '@/components/Discover/Map/Filter/Timeframes.vue';
|
import Timeframes from '@/components/Discover/Map/Filter/Timeframes.vue';
|
||||||
@@ -127,8 +131,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectFilter: {
|
selectFilter: {
|
||||||
// 'Filter Type': ['Sequence', 'Attributes', 'Trace', 'Timeframes'],
|
'Filter Type': ['Sequence', 'Attributes', 'Trace', 'Timeframes'],
|
||||||
'Filter Type': ['Sequence', 'Trace', 'Timeframes'],
|
// 'Filter Type': ['Sequence', 'Trace', 'Timeframes'],
|
||||||
'Activity Sequence':['Have activity(s)', 'Start & End', 'Sequence'],
|
'Activity Sequence':['Have activity(s)', 'Start & End', 'Sequence'],
|
||||||
'Start & End': ['Start', 'End', 'Start & End'],
|
'Start & End': ['Start', 'End', 'Start & End'],
|
||||||
'Mode': ['Directly follows', 'Eventually follows'],
|
'Mode': ['Directly follows', 'Eventually follows'],
|
||||||
@@ -164,6 +168,7 @@ export default {
|
|||||||
ActOccCase,
|
ActOccCase,
|
||||||
ActOcc,
|
ActOcc,
|
||||||
ActAndSeq,
|
ActAndSeq,
|
||||||
|
Attributes,
|
||||||
Funnel,
|
Funnel,
|
||||||
Trace,
|
Trace,
|
||||||
Timeframes,
|
Timeframes,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
allFilterEndToStart: [],
|
allFilterEndToStart: [],
|
||||||
allFilterTimeframe: {},
|
allFilterTimeframe: {},
|
||||||
allFilterTrace: [],
|
allFilterTrace: [],
|
||||||
|
allFilterAttrs: [],
|
||||||
hasResultRule: null, // click Apply 後檢查是否有 Data
|
hasResultRule: null, // click Apply 後檢查是否有 Data
|
||||||
temporaryData: [], // 沒被 apply all 的 Data
|
temporaryData: [], // 沒被 apply all 的 Data
|
||||||
postRuleData: [], // has-result API & temp-filters API 的 Data
|
postRuleData: [], // has-result API & temp-filters API 的 Data
|
||||||
@@ -93,6 +94,9 @@ export default defineStore('allMapDataStore', {
|
|||||||
filterTrace: state => {
|
filterTrace: state => {
|
||||||
return state.allFilterTrace;
|
return state.allFilterTrace;
|
||||||
},
|
},
|
||||||
|
filterAttrs: state => {
|
||||||
|
return state.allFilterAttrs;
|
||||||
|
},
|
||||||
allFunnels: state => {
|
allFunnels: state => {
|
||||||
return state.allFunnelData;
|
return state.allFunnelData;
|
||||||
},
|
},
|
||||||
@@ -217,6 +221,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
this.allFilterEndToStart = response.data.sinks;
|
this.allFilterEndToStart = response.data.sinks;
|
||||||
this.allFilterTimeframe = response.data.timeframe;
|
this.allFilterTimeframe = response.data.timeframe;
|
||||||
this.allFilterTrace = response.data.trace;
|
this.allFilterTrace = response.data.trace;
|
||||||
|
this.allFilterAttrs = response.data.attrs;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to load the Filter Parameters.');
|
apiError(error, 'Failed to load the Filter Parameters.');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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, traceId, traces, baseTraces, baseTraceId, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, createFilterId } = storeToRefs(allMapDataStore);
|
const { processMap, bpmn, stats, insights, traceId, traces, baseTraces, baseTraceId, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, temporaryData, isRuleData, ruleData, logId, baseLogId, createFilterId } = storeToRefs(allMapDataStore);
|
||||||
|
|
||||||
return { isLoading, processMap, bpmn, stats, insights, traceId, traces, baseTraces, baseTraceId, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
return { isLoading, processMap, bpmn, stats, insights, traceId, traces, baseTraces, baseTraceId, filterTasks, filterStartToEnd, filterEndToStart, filterTimeframe, filterTrace, logId, baseLogId, createFilterId, temporaryData, isRuleData, ruleData, allMapDataStore}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
SidebarView,
|
SidebarView,
|
||||||
@@ -299,6 +299,7 @@ export default {
|
|||||||
// 先 loading 再執行以下程式
|
// 先 loading 再執行以下程式
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
// Log 檔前往 Map Log 頁, Filter 檔前往 Map Filter 頁
|
// Log 檔前往 Map Log 頁, Filter 檔前往 Map Filter 頁
|
||||||
|
this.baseLogId = this.$route.params.fileId;
|
||||||
if(this.$route.params.type === 'log'){
|
if(this.$route.params.type === 'log'){
|
||||||
this.logId = this.$route.params.fileId;
|
this.logId = this.$route.params.fileId;
|
||||||
}else if(this.$route.params.type === 'filter') {
|
}else if(this.$route.params.type === 'filter') {
|
||||||
|
|||||||
Reference in New Issue
Block a user