Skip to content

Commit d14768e

Browse files
committed
ui: add activity status summary
1 parent 53e258f commit d14768e

File tree

1 file changed

+81
-4
lines changed

1 file changed

+81
-4
lines changed

ui/src/views/CollectionWorkflow.vue

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,30 @@
1010
<dl>
1111
<dt>Status</dt>
1212
<dd><b-badge>{{ history.status }}</b-badge></dd>
13+
<dt>Activity summary</dt>
14+
<dd>
15+
<table class="table table-bordered table-hover table-sm">
16+
<thead class="thead">
17+
<tr>
18+
<th scope="col">Name</th>
19+
<th scope="col">Started</th>
20+
<th scope="col">Duration (seconds)</th>
21+
<th scope="col">Status</th>
22+
</tr>
23+
</thead>
24+
<tbody>
25+
<tr v-for="(item, index) in activities" v-bind:key="index">
26+
<td scope="row">{{ item.name }}</td>
27+
<td>{{ item.started | formatEpoch }}</td>
28+
<td>{{ item.duration }}</td>
29+
<td><CollectionStatusBadge :status="item.status"/></td>
30+
</tr>
31+
</tbody>
32+
</table>
33+
</dd>
1334
<dt>History</dt>
1435
<dd>
15-
<table class="table table-bordered table-hover">
36+
<table class="table table-bordered table-hover table-sm">
1637
<thead class="thead">
1738
<tr>
1839
<th scope="col">ID</th>
@@ -22,8 +43,8 @@
2243
</tr>
2344
</thead>
2445
<tbody>
25-
<tr v-for="item in history.history.slice().reverse()" v-bind:key="item.id" @click="view(item)">
26-
<th scope="row">{{ item.id }}</th>
46+
<tr v-for="item in history.history.slice().reverse()" v-bind:key="item.id">
47+
<td scope="row">{{ item.id }}</td>
2748
<td>{{ item.type }}</td>
2849
<td>{{ item.details.timestamp | formatEpoch }}</td>
2950
<td>{{ renderDetails(item) }}</td>
@@ -39,13 +60,19 @@
3960
<script lang="ts">
4061
import { Component, Prop, Provide, Vue } from 'vue-property-decorator';
4162
import { EnduroCollectionClient } from '../main';
63+
import CollectionStatusBadge from '@/components/CollectionStatusBadge.vue';
4264
import { CollectionShowResponseBody, CollectionWorkflowResponseBody, EnduroCollectionWorkflowHistoryResponseBody } from '../client/src';
4365
44-
@Component
66+
@Component({
67+
components: {
68+
CollectionStatusBadge,
69+
},
70+
})
4571
export default class CollectionWorkflow extends Vue {
4672
4773
private collection: any = {};
4874
private history: any = {history: []};
75+
private activities: any = {};
4976
private name: string = '';
5077
5178
private mounted() {
@@ -75,9 +102,57 @@ export default class CollectionWorkflow extends Vue {
75102
private loadHistory() {
76103
return EnduroCollectionClient.collectionWorkflow({id: +this.$route.params.id}).then((response: CollectionWorkflowResponseBody) => {
77104
this.history = response;
105+
this.processHistory();
78106
});
79107
}
80108
109+
private processHistory() {
110+
const ignoredActivities = [
111+
'internalSessionCreationActivity',
112+
'internalSessionCompletionActivity',
113+
];
114+
for (const event of this.history.history) {
115+
const details = event.details;
116+
if (event.type === 'ActivityTaskScheduled') {
117+
const attrs = details.activityTaskScheduledEventAttributes;
118+
const name = attrs.activityType.name;
119+
if (ignoredActivities.includes(name)) {
120+
continue;
121+
}
122+
this.activities[event.id] = {
123+
name,
124+
status: 'in progress',
125+
attempts: 0,
126+
started: details.timestamp,
127+
};
128+
} else if (event.type === 'ActivityTaskStarted') {
129+
const attrs = details.activityTaskStartedEventAttributes;
130+
if (attrs.scheduledEventId in this.activities) {
131+
const item = this.activities[attrs.scheduledEventId];
132+
item.attempts = attrs.attempt + 1;
133+
}
134+
} else if (event.type === 'ActivityTaskFailed') {
135+
const attrs = details.activityTaskFailedEventAttributes;
136+
if (attrs.scheduledEventId in this.activities) {
137+
const item = this.activities[attrs.scheduledEventId];
138+
item.status = 'error';
139+
item.completed = details.timestamp;
140+
item.duration = (item.completed - item.started) / 1000000000;
141+
item.duration = item.duration.toFixed(2);
142+
}
143+
} else if (event.type === 'ActivityTaskCompleted') {
144+
const attrs = details.activityTaskCompletedEventAttributes;
145+
if (attrs.scheduledEventId in this.activities) {
146+
const item = this.activities[attrs.scheduledEventId];
147+
item.status = 'done';
148+
item.completed = details.timestamp;
149+
item.duration = (item.completed - item.started) / 1000000000;
150+
item.duration = item.duration.toFixed(2);
151+
}
152+
}
153+
}
154+
}
155+
81156
private renderDetails(event: EnduroCollectionWorkflowHistoryResponseBody): string {
82157
let ret = '';
83158
@@ -88,6 +163,8 @@ export default class CollectionWorkflow extends Vue {
88163
const attrs: any = event.details;
89164
if (event.type === 'ActivityTaskScheduled') {
90165
ret = 'Activity: ' + attrs.activityTaskScheduledEventAttributes.activityType.name;
166+
} else if (event.type === 'ActivityTaskFailed') {
167+
ret = 'Error: ' + window.atob(attrs.activityTaskFailedEventAttributes.details);
91168
} else if (event.type === 'DecisionTaskScheduled') {
92169
const attempt: number = parseInt(attrs.decisionTaskScheduledEventAttributes.attempt, 10) + 1;
93170
ret = 'Attempts: ' + attempt;

0 commit comments

Comments
 (0)