Discover: sidebarFilter Funnel to be decided.

This commit is contained in:
chiayin
2023-04-17 13:38:28 +08:00
parent aa52c4bce1
commit 2d48c244a1
4 changed files with 119 additions and 21 deletions

View File

@@ -83,7 +83,7 @@
<!-- 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" @click="reset">Clear</button>
<button class="btn btn-sm btn-neutral" @click="submit">Apply</button>
</div>
</div>
@@ -94,7 +94,55 @@
<!-- header: funnel -->
<div v-if="tab === 'funnel'">temporaryData:{{ temporaryData }}</div>
<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">
<span class="text-neutral-500">No Filter.</span>
</div>
<div v-else>
temporaryData:{{ temporaryData }}
<Timeline :value="events">
<template #content="slotProps">
{{ slotProps.item.status }}
</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> -->
</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>
</div>
</div>
</div>
</Sidebar>
</template>
@@ -102,6 +150,7 @@
<script>
import { storeToRefs } from 'pinia';
import LoadingStore from '@/stores/loading.js';
import AllMapDataStore from '@/stores/allMapData.js';
import ActOccCase from '@/components/Discover/table/actOccCase.vue';
import ActOcc from '@/components/Discover/table/actOcc.vue';
import ActAndSeq from '@/components/Discover/table/actAndSeq.vue';
@@ -135,11 +184,20 @@ export default {
},
setup() {
const loadingStore = LoadingStore();
const allMapDataStore = AllMapDataStore();
const { isLoading } = storeToRefs(loadingStore);
return { isLoading }
const { tempFilterId } = storeToRefs(allMapDataStore);
return { isLoading, tempFilterId, 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'],
@@ -171,7 +229,7 @@ export default {
isEndSelected: null,
isActAllTask: true,
rowData: [],
temporaryData: null,
temporaryData: [],
}
},
components: {
@@ -324,7 +382,7 @@ export default {
/**
* 清空選項
*/
reset() {
reset(massage) {
this.selectFilterTask = null;
this.selectFilterStart = null;
this.selectFilterEnd = null;
@@ -334,9 +392,9 @@ export default {
this.isStartSelected = null;
this.isEndSelected = null;
this.isActAllTask = true;
this.$toast.success('Reset Success.');
massage ? this.$toast.success('Reset Success.') : null;
},
// 發送選取的資料
// header:Filter 發送選取的資料
submit(){
let data;
let sele = this.selectValue;
@@ -346,7 +404,7 @@ export default {
// 若陣列為空,則跳出警告訊息
if(sele[0] === 'Sequence'){
if(sele[1] === 'Have activity(s)'){ // Activity Sequence 選 Have activity(s) 的行為
if(this.selectFilterTask === null || this.selectFilterTask.length === 0) return this.$toast.error('未選擇');
if(this.selectFilterTask === null || this.selectFilterTask.length === 0) return this.$toast.error('Not selected');
else {
// 將多選的 task 拆成一包包 obj
data = this.selectFilterTask.map(task => {
@@ -359,7 +417,7 @@ export default {
};
}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('未選擇');
if(this.selectFilterStart === null || this.selectFilterStart.length === 0) return this.$toast.error('Not selected');
else {
data = {
type: 'starts-with',
@@ -368,7 +426,7 @@ export default {
}
};
}else if(sele[2] === 'End') {
if(this.selectFilterEnd === null || this.selectFilterEnd.length === 0) return this.$toast.error('未選擇');
if(this.selectFilterEnd === null || this.selectFilterEnd.length === 0) return this.$toast.error('Not selected');
else {
data = {
type: 'starts-with',
@@ -377,7 +435,7 @@ export default {
}
};
}else if(sele[2] === 'Start & End') {
if(this.selectFilterStartToEnd === null || this.selectFilterStartToEnd.length === 0 || this.selectFilterEndToStart === null || this.selectFilterEndToStart.length === 0 ) return this.$toast.error('未選擇');
if(this.selectFilterStartToEnd === null || this.selectFilterStartToEnd.length === 0 || this.selectFilterEndToStart === null || this.selectFilterEndToStart.length === 0 ) return this.$toast.error('Both Start and End must be selected.');
else {
data = {
type: 'start-end',
@@ -388,31 +446,53 @@ export default {
}
};
}else if(sele[1] === 'Sequence'){ // Activity Sequence 選 Sequence 的行為
if(this.listSeq.length < 2) return this.$toast.error('未選擇');
if(this.listSeq.length < 2) return this.$toast.error('Select two or more.');
else {
data = {
type: sele[3] === 'Directly follows' ? 'directly-follows' : 'eventually-follows',
task: this.listSeq.map(task => task.label),
task_seq: this.listSeq.map(task => task.label),
is_exclude: isExclude,
}
};
}
}
// 將資料指向 Vue dat 雙向綁定
this.temporaryData = data;
// 將資料指向 Vue data 雙向綁定
const postData = Array.isArray(data) ? data : [data];
this.temporaryData.push(...postData);
// 結束後要清空資料
this.reset();
this.reset(false);
// 發送時isLoading
this.isLoading = true;
// 結束後,要跳出傳送成功的訊息
// 跳轉 this.tab = 'funnel';
setTimeout(() => {
this.isLoading = false;
this.$toast.success('Filter Success');
this.tab = 'funnel';
this.$toast.success('Filter Success. Click on Funnel to view the configuration result.');
}, 1000);
// 快速檢查每一 filter 規則是否為空集合
let logId = this.$route.params.logId;
this.axios.post(`/api/filters/has-result?log_id=${logId}`, postData)
.then(res=>{
res.data.result ? null : this.$toast.warning('No result.');
}).catch(err=>{
})
},
// header:Funnel 刪除全部的 Funnel
deleteAll() {
this.temporaryData = [];
this.$toast.success('All deleted.');
},
// header:Funnel 發送暫存的選取資料
submitAll() {
let logId = this.$route.params.logId;
this.axios.post(`/api/temp-filters?log_id=${logId}`, this.temporaryData)
.then(res=>{
console.log(res);
this.tempFilterId = res.data.id;
}).catch(err=>{
console.log(err);
})
}
},
}
</script>
@@ -422,4 +502,14 @@ export default {
#searchFiles::-webkit-search-cancel-button{
appearance: none;
}
/* TimeLine */
:deep(.p-timeline-event-marker) {
@apply !bg-primary !border-primary !h-2 !w-2
/* @apply !bg-primary !border-primary */
}
:deep(.p-timeline-event-connector) {
@apply !bg-primary my-2 !w-[1px]
/* @apply !bg-primary my-2 */
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="w-full h-full fixed inset-0 m-auto flex justify-center items-center bg-gradient-to-tr from-neutral-500/50 to-neutral-900/50 z-20">
<div class="w-full h-full fixed inset-0 m-auto flex justify-center items-center bg-gradient-to-tr from-neutral-500/50 to-neutral-900/50 z-50">
<span class="loader block"></span>
</div>
</template>

View File

@@ -35,6 +35,7 @@ import ColumnGroup from 'primevue/columngroup'; // optional
import Row from 'primevue/row'; // optional
import RadioButton from 'primevue/radiobutton';
import PickList from 'primevue/picklist';
import Timeline from 'primevue/timeline';
const emitter = mitt();
const app = createApp(App);
@@ -60,6 +61,7 @@ app.use(pinia);
app.use(router);
app.use(VueAxios, axios);
app.use(ToastPlugin, { // use `this.$toast` in Vue.js
position: 'bottom',
duration: 5000,
});
app.use(PrimeVue);
@@ -76,6 +78,7 @@ app.component('ColumnGroup', ColumnGroup);
app.component('Row', Row);
app.component('RadioButton', RadioButton);
app.component('PickList', PickList);
app.component('Timeline', Timeline);
app.component('Draggable', draggable); // 拖曳
app.mount("#app");

View File

@@ -14,6 +14,7 @@ export default defineStore('allMapDataStore', {
state: () => ({
logId: null,
traceId: 1,
tempFilterId: null,
allProcessMap: {},
allBpmn: {},
allStats: {},
@@ -75,7 +76,11 @@ export default defineStore('allMapDataStore', {
*/
async getAllMapData() {
let logId = this.logId;
const api = `/api/logs/${logId}/discover`;
let tempFilterId = this.tempFilterId;
let api = tempFilterId !== null ? `/api/temp-filters/${tempFilterId}/discover` : `/api/logs/${logId}/discover`;
console.log(tempFilterId);
console.log(logId);
// const api = `/api/logs/${logId}/discover`;
try {
const response = await this.$axios.get(api);