Discover: sidebarFilter toggle button done.

This commit is contained in:
chiayin
2023-04-24 12:30:29 +08:00
parent 3d5dba4c42
commit 0cff786e9a
8 changed files with 165 additions and 145 deletions

View File

@@ -7,7 +7,7 @@
</ul>
</template>
<!-- header: filter -->
<div v-if="tab === 'filter'" class="pt-4 bg-neutral-100 flex w-full h-full">
<div v-if="tab === 'filter'" class="pt-4 flex w-full h-full">
<!-- title: filter silect -->
<div class="space-y-2 mr-4 w-56 text-sm">
<div>
@@ -24,7 +24,7 @@
<label :for="item + index" class="ml-2">{{ item }}</label>
</div>
</div>
<div v-show="selectValue[1] === 'Start activity & end activity'">
<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" />
@@ -68,11 +68,11 @@
<!-- 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>
<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>
<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 ">
<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>
@@ -83,63 +83,45 @@
<!-- Button -->
<div class="float-right space-x-4 px-4 py-2">
<button class="btn btn-sm btn-neutral" @click="reset">Clear</button>
<button class="btn btn-sm btn-neutral" @click="submit">Apply</button>
<button type="button" class="btn btn-sm btn-neutral" @click="reset">Clear</button>
<button type="button" class="btn btn-sm btn-neutral" @click="submit">Apply</button>
</div>
</div>
</div>
<!-- header: funnel -->
<div v-if="tab === 'funnel'" class="bg-neutral-10 w-full h-full">
<div class="h-[calc(100%_-_58px)] border-b border-neutral-300 mb-2">
<div v-if="temporaryData.length === 0" class="h-full flex justify-center items-center">
<div v-if="tab === 'funnel'" class=" w-full h-full">
<div class="h-[calc(100%_-_58px)] border-b border-neutral-400 mb-2 overflow-y-auto overflow-x-auto scrollbar">
<div v-if="this.temporaryData.length === 0" class="h-full flex justify-center items-center">
<span class="text-neutral-500">No Filter.</span>
</div>
<div v-else>
temporaryData:{{ temporaryData }}
<Timeline :value="events">
<template #content="slotProps">
{{ slotProps.item.status }}
<Timeline :value="ruleData">
<template #content="rule">
<div class="border-b border-neutral-300 flex justify-between items-center space-x-2">
<!-- content -->
<div class="pl-2 mb-2">
<p class="text-sm font-medium leading-5">{{ rule.item.type }}:&nbsp;<span class="text-neutral-500">{{ rule.item.label }}</span></p>
<!-- <p class="text-sm font-medium mb-5">{{ rule.item.type }}</p>
<p class="text-sm text-neutral-500 mb-2">{{ rule.item.label }}</p> -->
</div>
<!-- button -->
<div class="min-w-fit">
<InputSwitch v-model="rule.item.toggle" @input="isRule($event, rule.index)"/>
<button type="button" class="m-2 focus:ring focus:ring-danger/20 text-neutral-500 hover:text-danger" @click.stop="deleteRule(rule.index)">
<span class="material-symbols-outlined">delete</span>
</button>
</div>
</div>
</template>
</Timeline>
<!-- <Timeline :value="events" align="alternate" class="customized-timeline">
<template #marker="slotProps">
<span class="!flex !w-2rem !h-2rem !align-items-center !justify-content-center !text-white !border-circle !z-1 !shadow-1" :style="{ backgroundColor: slotProps.item.color }">
<i :class="slotProps.item.icon"></i>
</span>
</template>
<template #content="slotProps">
{{ slotProps.item.status }}
<Card>
<template #title>
{{ slotProps.item.status }}
</template>
<template #subtitle>
{{ slotProps.item.date }}
</template>
<template #content>
<img v-if="slotProps.item.image" :src="`https://primefaces.org/cdn/primevue/images/product/${slotProps.item.image}`" :alt="slotProps.item.name" width="200" class="shadow-1" />
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore sed consequuntur error repudiandae numquam deserunt quisquam repellat libero asperiores earum nam nobis, culpa ratione quam perferendis esse, cupiditate
neque quas!
</p>
<Button label="Read more" text></Button>
</template>
</Card>
</template>
</Timeline> -->
</Timeline>
</div>
</div>
<!-- Button -->
<div class="">
<div class="float-right space-x-4 px-4 py-2">
<button class="btn btn-sm btn-neutral" @click="deleteAll">Delete All</button>
<button class="btn btn-sm btn-neutral" @click="submitAll">Apply All</button>
<button type="button" class="btn btn-sm " :class="[ temporaryData.length === 0 ? 'btn-disable' : 'btn-neutral']" :disabled="temporaryData.length === 0" @click="deleteRule('all')">Delete All</button>
<button type="button" class="btn btn-sm" :class="[ temporaryData.length === 0 ? 'btn-disable' : 'btn-neutral']" :disabled="temporaryData.length === 0" @click="submitAll">Apply All</button>
</div>
</div>
</div>
@@ -186,21 +168,15 @@ export default {
const loadingStore = LoadingStore();
const allMapDataStore = AllMapDataStore();
const { isLoading } = storeToRefs(loadingStore);
const { hasResultRule, postRuleData} = storeToRefs(allMapDataStore);
const { hasResultRule, temporaryData, postRuleData} = storeToRefs(allMapDataStore);
return { isLoading, hasResultRule, postRuleData, allMapDataStore }
return { isLoading, hasResultRule, temporaryData, postRuleData, allMapDataStore }
},
data() {
return {
events: [
{ status: 'Ordered', date: '15/10/2020 10:30', icon: 'pi pi-shopping-cart', color: '#9C27B0'},
{ status: 'Processing', date: '15/10/2020 14:00', icon: 'pi pi-cog', color: '#673AB7' },
{ status: 'Shipped', date: '15/10/2020 16:15', icon: 'pi pi-shopping-cart', color: '#FF9800' },
{ status: 'Delivered', date: '16/10/2020 10:00', icon: 'pi pi-check', color: '#607D8B' }
],
selectFilter: {
'Filter Type': ['Sequence', 'Attributes', 'Trace', 'Timeframes'],
'Activity Sequence':['Have activity(s)', 'Start activity & end activity', 'Sequence'],
'Activity Sequence':['Have activity(s)', 'Start activity / end activity', 'Sequence'],
'Start & End': ['Start', 'End', 'Start & End'],
'Mode': ['Directly follows', 'Eventually follows'],
'ModeAtt': ['Case', 'Activity'],
@@ -208,7 +184,6 @@ export default {
'Containment': ['Contained in', 'Started in', 'End in', 'Activity in', 'Trim'],
},
tab: 'filter', // filter | funnel
// selectValue: ['Sequence', 'Have activity(s)', 'Start', 'Directly follows', 'Case', 'Include', 'Contained in'],
selectValue: {
0: 'Sequence',
1: 'Have activity(s)',
@@ -229,7 +204,8 @@ export default {
isEndSelected: null,
isActAllTask: true,
rowData: [],
temporaryData: [],
ruleData: [],
isRuleData: [], // toggle button data
}
},
components: {
@@ -257,12 +233,25 @@ export default {
}
},
methods: {
/**
* @param {string} switch Summary or Insight
*/
switchTab(tab) {
this.tab = tab;
},
/**
* @param {boolean} e ture | false
* @param {numble} index rule's index
*/
isRule(e, index){
let rule = this.isRuleData[index];
// 先取得 rule object
// 為了讓 data 順序不亂掉,將值指向 0submitAll 時再刪掉
if(!e) this.temporaryData[index] = 0;
else this.temporaryData[index] = rule;
},
/**
* Number to percentage
* @param {number} val
@@ -379,6 +368,59 @@ export default {
occurrence_ratio: this.getPercentLabel(item.occurrence_ratio),
}));
},
/**
* @param {object} e task's object
*/
setRule(e) {
let label = "";
let type = "";
let includeStr = e.is_exclude?" Exclude ":" Include ";
switch(e.type){
case "contains-task":
label = `${includeStr} ${e.task}`
type = "Sequence"
break
case "starts-with":
label = `Start with ${e.task} ${includeStr}`
type = "Sequence"
break
case "ends-with":
label = `End with ${e.task} ${includeStr}`
type = "Sequence"
break
case "start-end":
label = `Start with ${e.starts_with}, End with ${e.ends_with} ${includeStr}`
type = "Sequence"
break
case "directly-follows":
label = `Directly-follows ${e.task_seq.join(' -> ')}${includeStr}`
type = "Sequence"
break
case "eventually-follows":
label = `Eventually-follows ${e.task_seq.join(' -> ')}${includeStr}`
type = "Sequence"
break
case "occurred-in":
case "started-in":
case "completed-in":
case "occurred-around":
label = `${e.type} from ${moment(e.start).format("YYYY-MM-DD HH:mm:ss")} to ${moment(e.end).format("YYYY-MM-DD HH:mm:ss")} ${includeStr}`
type = "Timeframe"
break
case "trace-freq":
label = `from ${e.lower} to ${e.upper} ${includeStr}`
type = "Trace"
break
default:
break
}
return {
type:type,
label:label,
toggle:true,
}
},
/**
* 清空選項
*/
@@ -415,7 +457,7 @@ export default {
}
})
};
}else if(sele[1] === 'Start activity & end activity') { // Activity Sequence 選 Start activity & end activity 的行為
}else if(sele[1] === 'Start activity / end activity') { // Activity Sequence 選 Start activity & end activity 的行為
if(sele[2] === 'Start') {
if(this.selectFilterStart === null || this.selectFilterStart.length === 0) return this.$toast.error('Not selected');
else {
@@ -429,7 +471,7 @@ export default {
if(this.selectFilterEnd === null || this.selectFilterEnd.length === 0) return this.$toast.error('Not selected');
else {
data = {
type: 'starts-with',
type: 'ends-with',
task: this.selectFilterEnd.label,
is_exclude: isExclude,
}
@@ -468,6 +510,8 @@ export default {
if(this.hasResultRule === null) return;
else if(this.hasResultRule) {
this.temporaryData.push(...postData);
this.isRuleData = Array.from(this.temporaryData);
this.ruleData = this.temporaryData.map(e => this.setRule(e));
this.reset(false);
this.isLoading = true;
await new Promise(resolve => setTimeout(resolve, 1000));
@@ -482,21 +526,30 @@ export default {
};
},
// header:Funnel 刪除全部的 Funnel
deleteAll() {
this.temporaryData = [];
this.$toast.success('All deleted.');
deleteRule(index) {
if(index === 'all') {
this.temporaryData = [];
this.isRuleData = [];
this.$toast.success('All deleted.');
}else{
this.$toast.success(`Delete ${this.ruleData[index].label}.`);
this.temporaryData.splice(index, 1);
this.isRuleData.splice(index, 1);
this.ruleData.splice(index, 1);
}
},
// header:Funnel 發送暫存的選取資料
async submitAll() {
if(this.temporaryData.length === 0) return this.$toast.error('No Filter.');
this.postRuleData = this.temporaryData;
this.postRuleData = this.temporaryData; // 取得 submit 的資料
this.postRuleData = this.postRuleData.filter(item => item !== 0); // 有 toggle button 的話,找出並刪除陣列中為 0 的項目
await this.allMapDataStore.checkHasResult();
if(this.hasResultRule === null) return;
else if(this.hasResultRule) {
this.isLoading = true;
await this.allMapDataStore.addTempFilterId();
await this.allMapDataStore.getAllMapData();
await this.$emit('submit-all');
this.isLoading = false;
this.$toast.success('Filter Success. View the Map.');
}else {
@@ -517,10 +570,22 @@ export default {
}
/* TimeLine */
:deep(.p-timeline) {
@apply leading-none my-4
}
:deep(.p-timeline-event-opposite) {
@apply hidden
}
:deep(.p-timeline-event-separator) {
@apply mx-4
}
:deep(.p-timeline-event-marker) {
@apply !bg-primary !border-primary !h-2 !w-2
@apply !bg-primary !border-primary !w-2 !h-2
}
:deep(.p-timeline-event-connector) {
@apply !bg-primary my-2 !w-[1px]
}
:deep(.p-timeline-event-content) {
@apply !px-0
}
</style>