Conformance: Activity sequence Short loop(s) done.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<section class="p-4 mr-0.5 space-y-2 h-full w-[calc(100vw_-_316px)] overflow-y-auto scrollbar float-right">
|
||||
<!-- cover plate -->
|
||||
<div v-show="isCoverPlate" class="w-[calc(100vw_-_300px)] h-screen-main fixed bottom-0 right-0 bg-gradient-to-tr from-neutral-500/50 to-neutral-900/50 z-[1]">
|
||||
</div>
|
||||
<!-- title -->
|
||||
@@ -97,9 +96,38 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Loop group -->
|
||||
<section>
|
||||
<div v-if="data.loops == null"></div>
|
||||
<div v-else>
|
||||
<p class="h2 text-base">Loop List</p>
|
||||
<div class="border rounded border-neutral-300 p-2 bg-neutral-10 w-full">
|
||||
<p class="h2 pl-2 mb-2">Short Loop(s)</p>
|
||||
<table class="text-sm min-w-full table-fixed">
|
||||
<tbody>
|
||||
<tr v-for="(trace, key) in data.loops" :key="key">
|
||||
<td class="p-2 pl-6 truncate max-w-0 w-1/3">
|
||||
<span class="material-symbols-outlined disc text-sm align-middle mr-1">fiber_manual_record</span>{{ trace.label }}
|
||||
</td>
|
||||
<td class="p-2 min-w-[96px] w-2/5">
|
||||
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||
<div class="h-full bg-primary" :style="trace.value"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="p-2 text-right truncate">{{ trace.count }}</td>
|
||||
<td class="p-2 text-center">{{ trace.ratio }}%</td>
|
||||
<td class="p-2 text-center">
|
||||
<div class="btn btn-sm btn-c-primary cursor-pointer" @click="openLoopMore(trace.no)">More</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- Issues group -->
|
||||
<section>
|
||||
<div v-if="data.issues == ''"></div>
|
||||
<div v-if="data.issues == null"></div>
|
||||
<div v-else>
|
||||
<p class="h2 text-base">Non-conformance Issues</p>
|
||||
<div class="flex gap-4 w-full">
|
||||
@@ -117,7 +145,7 @@
|
||||
<tbody>
|
||||
<tr v-for="(trace, key) in data.issues" :key="key">
|
||||
<td class="p-2 pl-6 truncate max-w-0 w-1/3">
|
||||
<span class="material-symbols-outlined disc text-sm align-middle mr-1">fiber_manual_record</span>{{ trace.issue }}
|
||||
<span class="material-symbols-outlined disc text-sm align-middle mr-1">fiber_manual_record</span>{{ trace.label }}
|
||||
</td>
|
||||
<td class="p-2 min-w-[96px] w-2/5">
|
||||
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||
@@ -136,7 +164,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<MoreModal :issusModal="issusModal" @update:visible="issusModal = $event" :issueTraces="issueTraces" :issusNo="issusNo" :traceId="traceId" :firstCases="firstCases" ref="moreModal"></MoreModal>
|
||||
<MoreModal :listModal="issuesModal" @update:visible="issusModal = $event" :listTraces="issueTraces" :taskSeq="taskSeq" :cases="cases" :listNo="issuesNo" :traceId="traceId" :firstCases="firstCases" :category="'issue'"></MoreModal>
|
||||
<MoreModal :listModal="loopModal" @update:visible="loopModal = $event" :listTraces="loopTraces" :taskSeq="loopTaskSeq" :cases="loopCases" :listNo="loopNo" :traceId="looptraceId" :firstCases="loopFirstCases" :category="'loop'"></MoreModal>
|
||||
</section>
|
||||
</template>
|
||||
<script>
|
||||
@@ -152,9 +181,9 @@ import getMoment from 'moment';
|
||||
export default {
|
||||
setup() {
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { conformanceTempReportData, issueTraces, taskSeq, } = storeToRefs(conformanceStore);
|
||||
const { conformanceTempReportData, issueTraces, taskSeq, cases, loopTraces, loopTaskSeq, loopCases } = storeToRefs(conformanceStore);
|
||||
|
||||
return { conformanceTempReportData, issueTraces, taskSeq, conformanceStore }
|
||||
return { conformanceTempReportData, issueTraces, taskSeq, cases, loopTraces, loopTaskSeq, loopCases, conformanceStore }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -180,17 +209,22 @@ export default {
|
||||
time: null,
|
||||
tasks: null,
|
||||
},
|
||||
loops: null,
|
||||
issues: 'reset'
|
||||
},
|
||||
isCoverPlate: false,
|
||||
issusModal: false,
|
||||
issuesModal: false,
|
||||
loopModal: false,
|
||||
rateChartData: null,
|
||||
rateChartOptions: null,
|
||||
casesChartData: null,
|
||||
casesChartOptions: null,
|
||||
issusNo: null,
|
||||
issuesNo: null,
|
||||
traceId: null,
|
||||
firstCases: null,
|
||||
loopNo: null,
|
||||
looptraceId: null,
|
||||
loopFirstCases: null,
|
||||
tooltip: {
|
||||
results: {
|
||||
value: 'This page will perform a conformance check based on the filtering results of the map.',
|
||||
@@ -208,7 +242,6 @@ export default {
|
||||
watch: {
|
||||
conformanceTempReportData: {
|
||||
handler: function(newValue) {
|
||||
// this.data = newValue;
|
||||
this.data = this.setConformanceTempReportData(newValue);
|
||||
},
|
||||
}
|
||||
@@ -238,14 +271,29 @@ export default {
|
||||
convertSecToDay(sec) {
|
||||
return (sec / 86400)
|
||||
},
|
||||
/**
|
||||
* Open Issues Modal.
|
||||
* @param {number} no trace no
|
||||
*/
|
||||
async openMore(no) {
|
||||
// async await 解決非同步資料延遲傳遞導致未讀取到而出錯的問題
|
||||
this.issusNo = no;
|
||||
this.issuesNo = no;
|
||||
await this.conformanceStore.getLogConformanceIssue(no);
|
||||
this.traceId = await this.issueTraces[0].id;
|
||||
this.firstCases = await this.conformanceStore.getLogConformanceTraceDetail(no, this.issueTraces[0].id, 0);
|
||||
this.issusModal = await true;
|
||||
await this.$refs.moreModal.createCy()
|
||||
this.issuesModal = await true;
|
||||
},
|
||||
/**
|
||||
* Open Loop Modal.
|
||||
* @param {number} no trace no
|
||||
*/
|
||||
async openLoopMore(no) {
|
||||
// async await 解決非同步資料延遲傳遞導致未讀取到而出錯的問題
|
||||
this.loopNo = no;
|
||||
await this.conformanceStore.getLogConformanceLoop(no);
|
||||
this.looptraceId = await this.loopTraces[0].id;
|
||||
this.loopFirstCases = await this.conformanceStore.getLogConformanceLoopsTraceDetail(no, this.loopTraces[0].id, 0);
|
||||
this.loopModal = await true;
|
||||
},
|
||||
/**
|
||||
* set conformance report data
|
||||
@@ -256,6 +304,16 @@ export default {
|
||||
let rate = ((data.counts.conforming / sum) * 100).toFixed(1);
|
||||
let isNullTime = value => value === null ? null : getNumberLabel((value / 86400).toFixed(1));
|
||||
let isNullCase = value => value === null ? null : getNumberLabel(value.toFixed(1));
|
||||
let setListData = value => value.map(item => {
|
||||
return {
|
||||
no: item.no,
|
||||
label: item.description,
|
||||
value: `width:${this.getPercentLabel(item.count / sum)}%;`,
|
||||
count: item.count,
|
||||
ratio: this.getPercentLabel(item.count / sum),
|
||||
}
|
||||
});
|
||||
let isNullLists = value => value === null ? null : setListData(value);
|
||||
|
||||
let result = {
|
||||
counts: {
|
||||
@@ -294,15 +352,8 @@ export default {
|
||||
difference: isNullCase(data.effect.tasks.conforming - data.effect.tasks.not_conforming),
|
||||
},
|
||||
},
|
||||
issues: data.issues.map(item => {
|
||||
return {
|
||||
no: item.no,
|
||||
issue: item.description,
|
||||
value: `width:${this.getPercentLabel(item.count / sum)}%;`,
|
||||
count: item.count,
|
||||
ratio: this.getPercentLabel(item.count / sum),
|
||||
}
|
||||
})
|
||||
loops: isNullLists(data.loops),
|
||||
issues: isNullLists(data.issues),
|
||||
};
|
||||
this.setRateChartData(result.charts.rate.data); // 建立圖表 Rate Chart.js
|
||||
this.setCasesChartData(result.charts.cases.data.conforming, result.charts.cases.data.not_conforming, data.charts.cases.x_axis.max, data.charts.cases.x_axis.min); // 建立圖表 Cases Chart.js
|
||||
|
||||
@@ -144,7 +144,7 @@ export default {
|
||||
isMode = 'eventually-follows';
|
||||
break;
|
||||
case 'Short loop(s)':
|
||||
isMode = 'b';
|
||||
isMode = 'short-loops';
|
||||
break;
|
||||
case 'Self loop(s)':
|
||||
isMode = 'c';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog :visible="issusModal" @update:visible="$emit('update:isVisible', $event)" modal :style="{ width: '90vw', height: '90vh' }" :contentClass="contentClass">
|
||||
<Dialog :visible="listModal" @update:visible="$emit('update:isVisible', $event)" modal :style="{ width: '90vw', height: '90vh' }" :contentClass="contentClass">
|
||||
<template #header>
|
||||
<div class=" py-5">
|
||||
<p class="text-base font-bold">Non-conformance Issue</p>
|
||||
@@ -60,12 +60,12 @@ import ConformanceStore from '@/stores/conformance.js';
|
||||
import cytoscapeMapTrace from '@/module/cytoscapeMapTrace.js';
|
||||
|
||||
export default {
|
||||
props: ['issusModal', 'issusNo', 'traceId', 'firstCases'],
|
||||
props: ['listModal', 'listNo', 'traceId', 'firstCases', 'listTraces', 'taskSeq', 'cases', 'category'],
|
||||
setup() {
|
||||
const conformanceStore = ConformanceStore();
|
||||
const { issueTraces, taskSeq, cases, infinite404 } = storeToRefs(conformanceStore);
|
||||
const { infinite404 } = storeToRefs(conformanceStore);
|
||||
|
||||
return { issueTraces, taskSeq, cases, infinite404, conformanceStore }
|
||||
return { infinite404, conformanceStore }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -85,9 +85,9 @@ export default {
|
||||
return this.traceList.length;
|
||||
},
|
||||
traceList: function() {
|
||||
let sum = this.issueTraces.map(trace => trace.count).reduce((acc, cur) => acc + cur, 0);
|
||||
let sum = this.listTraces.map(trace => trace.count).reduce((acc, cur) => acc + cur, 0);
|
||||
|
||||
return this.issueTraces.map(trace => {
|
||||
return this.listTraces.map(trace => {
|
||||
return {
|
||||
id: trace.id,
|
||||
value: Number((this.getPercentLabel(trace.count / sum))),
|
||||
@@ -120,8 +120,11 @@ export default {
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
listModal: function(newValue) { // 第一次打開 Modal 要繪圖
|
||||
if(newValue) this.createCy();
|
||||
},
|
||||
taskSeq: function(newValue){
|
||||
if(newValue !== null) this.createCy();
|
||||
if (newValue != null) this.createCy();
|
||||
},
|
||||
traceId: function(newValue) {
|
||||
// 當 traceId 屬性變化時更新 showTraceId
|
||||
@@ -167,7 +170,10 @@ export default {
|
||||
this.maxItems = false;
|
||||
this.showTraceId = id;
|
||||
this.startNum = 0;
|
||||
let result = await this.conformanceStore.getLogConformanceTraceDetail(this.issusNo, id, 0);
|
||||
|
||||
let result;
|
||||
if(this.category === 'issue') result = await this.conformanceStore.getLogConformanceTraceDetail(this.listNo, id, 0);
|
||||
else if(this.category === 'loop') result = await this.conformanceStore.getLogConformanceLoopsTraceDetail(this.listNo, id, 0);
|
||||
this.infiniteData = await result;
|
||||
},
|
||||
/**
|
||||
@@ -177,6 +183,7 @@ export default {
|
||||
// 避免每次渲染都重複累加
|
||||
this.processMap.nodes = [];
|
||||
// 將 api call 回來的資料帶進 node
|
||||
if(this.taskSeq != null) {
|
||||
this.taskSeq.forEach((node, index) => {
|
||||
this.processMap.nodes.push({
|
||||
data: {
|
||||
@@ -189,13 +196,15 @@ export default {
|
||||
width: 100
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 將 trace edge line 資料彙整
|
||||
*/
|
||||
setEdgesData(){
|
||||
this.processMap.edges = [];
|
||||
if(this.taskSeq != null) {
|
||||
this.taskSeq.forEach((edge, index) => {
|
||||
this.processMap.edges.push({
|
||||
data: {
|
||||
@@ -206,6 +215,7 @@ export default {
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
// 關係線數量筆節點少一個
|
||||
this.processMap.edges.pop();
|
||||
},
|
||||
@@ -218,7 +228,7 @@ export default {
|
||||
|
||||
this.setNodesData();
|
||||
this.setEdgesData();
|
||||
if(graphId !== null) cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
||||
if(graphId != null) cytoscapeMapTrace(this.processMap.nodes, this.processMap.edges, graphId);
|
||||
});
|
||||
},
|
||||
/**
|
||||
@@ -228,7 +238,7 @@ export default {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.startNum += 20
|
||||
const result = await this.conformanceStore.getLogConformanceTraceDetail(this.issusNo, this.showTraceId, this.startNum);
|
||||
const result = await this.conformanceStore.getLogConformanceTraceDetail(this.listNo, this.showTraceId, this.startNum);
|
||||
this.infiniteData = [...this.infiniteData, ...result];
|
||||
} catch(error) {
|
||||
// console.error('Failed to load data:', error);
|
||||
|
||||
@@ -24,6 +24,9 @@ export default defineStore('conformanceStore', {
|
||||
allIssueTraces: null,
|
||||
allTaskSeq: null,
|
||||
allCases: null,
|
||||
allLoopTraces: null,
|
||||
allLoopTaskSeq: null,
|
||||
allLoopCases: null,
|
||||
selectedRuleType: 'Have activity', // radio
|
||||
selectedActivitySequence: 'Start & End', // radio
|
||||
selectedMode: 'Directly follows', // radio
|
||||
@@ -78,6 +81,35 @@ export default defineStore('conformanceStore', {
|
||||
};
|
||||
return state.allCases;
|
||||
},
|
||||
loopTraces: state => {
|
||||
return state.allLoopTraces;
|
||||
},
|
||||
loopTaskSeq: state => {
|
||||
return state.allLoopTaskSeq;
|
||||
},
|
||||
loopCases: state => {
|
||||
if(state.allLoopCases !== null){
|
||||
state.allLoopCases.map(c => {
|
||||
c.started_at = moment(c.started_at).format('YYYY/MM/DD HH:MM');
|
||||
c.completed_at = moment(c.completed_at).format('YYYY/MM/DD HH:MM');
|
||||
c.attributes.map(att => {
|
||||
switch (att.type) {
|
||||
case 'date':
|
||||
att.value = att.value !== null ? moment(att.value).format('YYYY/MM/DD HH:MM:ss') : null;
|
||||
break;
|
||||
case 'float':
|
||||
att.value = att.value !== null ? new Decimal(att.value).toFixed(2) : null;
|
||||
break
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return att;
|
||||
})
|
||||
return c;
|
||||
});
|
||||
};
|
||||
return state.allLoopCases;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
@@ -157,8 +189,7 @@ export default defineStore('conformanceStore', {
|
||||
loading.isLoading = false;
|
||||
await delay(500);
|
||||
$toast.default('Failed to Get the detail of a temporary log conformance issue.',{position: 'bottom'});
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Get the Trace Details of a Temporary Log Conformance lssue.
|
||||
@@ -182,7 +213,50 @@ export default defineStore('conformanceStore', {
|
||||
await delay(500);
|
||||
$toast.default('Failed to Get the detail of a temporary log conformance issue.',{position: 'bottom'});
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Get the Details of a Temporary Log Conformance Loop.
|
||||
*/
|
||||
async getLogConformanceLoop(loopNo) {
|
||||
let checkerId = this.conformanceTempCheckerId;
|
||||
let api = `/api/temp-log-checkers/${checkerId}/loops/${loopNo}`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
this.allLoopTraces = response.data.traces;
|
||||
} catch(error) {
|
||||
await delay();
|
||||
loading.isLoading = true;
|
||||
await delay(1000);
|
||||
loading.isLoading = false;
|
||||
await delay(500);
|
||||
$toast.default('Failed to Get the detail of a temporary log conformance loop.',{position: 'bottom'});
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Get the Trace Details of a Temporary Log Conformance Loops.
|
||||
*/
|
||||
async getLogConformanceLoopsTraceDetail(loopNo, traceId, start) {
|
||||
let checkerId = this.conformanceTempCheckerId;
|
||||
const api = `/api/temp-log-checkers/${checkerId}/loops/${loopNo}/traces/${traceId}?start=${start}&page_size=20`;
|
||||
|
||||
try {
|
||||
const response = await this.$axios.get(api);
|
||||
this.allLoopTaskSeq = response.data.task_seq;
|
||||
this.allLoopCases = response.data.cases;
|
||||
return response.data.cases;
|
||||
} catch(error) {
|
||||
if(error.response.status === 404) this.infinite404 = 404;
|
||||
else {
|
||||
await delay();
|
||||
loading.isLoading = true;
|
||||
await delay(1000);
|
||||
loading.isLoading = false;
|
||||
await delay(500);
|
||||
$toast.default('Failed to Get the detail of a temporary log conformance loop.',{position: 'bottom'});
|
||||
};
|
||||
};
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user