Improve event display, rather than just stringifying the json
This commit is contained in:
parent
ae62484d30
commit
7731b37c12
143
src/App.vue
143
src/App.vue
@ -1,22 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="(minions, jid) in jobs" :key="jid">
|
||||
<h3>{{ jid }}</h3>
|
||||
<div v-for="(minion_events, minion) in minions" :key="minion">
|
||||
<div v-for="(job, jid) in jobs" :key="jid">
|
||||
<h3>
|
||||
<span v-if="job.startEvent">
|
||||
{{ job.startEvent.data.fun }}
|
||||
{{ job.startEvent.data.arg }}
|
||||
</span>
|
||||
<span class="header-jid"> {{ jid }}</span>
|
||||
</h3>
|
||||
<div v-for="(events, minion) in job.minionEvents" :key="minion">
|
||||
<details class="minion">
|
||||
<summary>
|
||||
{{ minion }}
|
||||
<span v-for="(event, index) in minion_events" :key="index">
|
||||
<span v-for="(event, index) in events" :key="index">
|
||||
{{ event_symbol(event) }}
|
||||
</span>
|
||||
</summary>
|
||||
<details
|
||||
class="event"
|
||||
v-for="(event, index) in minion_events"
|
||||
:key="index"
|
||||
>
|
||||
<details class="event" v-for="(event, index) in events" :key="index">
|
||||
<summary>{{ event_name(event) }}</summary>
|
||||
<pre>{{ JSON.stringify(event, null, 2) }}</pre>
|
||||
<pre v-if="rawEvents">{{ JSON.stringify(event, null, 2) }}</pre>
|
||||
<div v-if="isJobEventType(event, 'prog')">
|
||||
{{ JSON.stringify(event.data.data, null, 2) }}
|
||||
</div>
|
||||
<div v-else-if="isJobEventType(event, 'ret')">
|
||||
{{ event.data.jid }}: {{ event.data.fun }}
|
||||
{{ event.data.fun_args }} => {{ event.data.retcode }}
|
||||
<pre>{{
|
||||
typeof event.data.return === 'string'
|
||||
? event.data.return
|
||||
: JSON.stringify(event.data.return, null, 2)
|
||||
}}</pre>
|
||||
</div>
|
||||
</details>
|
||||
</details>
|
||||
</div>
|
||||
@ -31,29 +45,33 @@ import credentials from './credentials.json';
|
||||
|
||||
import * as salt from './salt';
|
||||
|
||||
function isEventType<T extends salt.SaltEvent['splitTag'][1]>(
|
||||
event: salt.SaltEvent,
|
||||
type: T
|
||||
): event is Extract<salt.SaltEvent, { splitTag: ['salt', T, ...any[]] }> {
|
||||
return event.splitTag[1] === type;
|
||||
}
|
||||
|
||||
function isJobEventType<T extends salt.SaltEvent['splitTag'][3]>(
|
||||
event: salt.SaltEvent,
|
||||
type: T
|
||||
): event is Extract<
|
||||
salt.SaltEvent,
|
||||
{ splitTag: ['salt', 'job', any, T, ...any[]] }
|
||||
> {
|
||||
return event.splitTag[3] === type;
|
||||
}
|
||||
|
||||
const BASE_URL = 'https://salt.sawtooth.claremontmakerspace.org:8000/';
|
||||
|
||||
type MinionJobEvent = salt.JobProgEvent | salt.JobRetEvent;
|
||||
|
||||
class Job {
|
||||
startEvent?: salt.JobNewEvent;
|
||||
minionEvents: { [key: string]: MinionJobEvent[] } = {};
|
||||
jid: salt.JobID;
|
||||
|
||||
constructor(jid: salt.JobID, startEvent?: salt.JobNewEvent) {
|
||||
this.jid = jid;
|
||||
this.startEvent = startEvent;
|
||||
}
|
||||
|
||||
addEvent(event: MinionJobEvent) {
|
||||
if (!(event.data.id in this.minionEvents))
|
||||
Vue.set(this.minionEvents, event.data.id, []);
|
||||
this.minionEvents[event.data.id].push(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
export default class App extends Vue {
|
||||
evtSource: EventSource | null = null;
|
||||
events: salt.SaltEvent[] = [];
|
||||
jobs: { [key: string]: Job } = {};
|
||||
rawEvents: boolean = false;
|
||||
|
||||
mounted(): void {
|
||||
fetch(BASE_URL + 'login', {
|
||||
@ -66,56 +84,66 @@ export default class App extends Vue {
|
||||
const token: string = r.return[0].token;
|
||||
this.evtSource = new EventSource(BASE_URL + 'events?token=' + token);
|
||||
this.evtSource.onmessage = e => {
|
||||
const evt = JSON.parse(e.data);
|
||||
evt.splitTag = evt.tag.split('/');
|
||||
this.events.push(evt);
|
||||
const event = JSON.parse(e.data);
|
||||
event.splitTag = event.tag.split('/');
|
||||
this.events.push(event);
|
||||
|
||||
if (this.isEventType(event, 'job')) {
|
||||
if (this.isJobEventType(event, 'new')) {
|
||||
this.$set(
|
||||
this.jobs,
|
||||
event.data.jid,
|
||||
new Job(event.data.jid, event)
|
||||
);
|
||||
} else {
|
||||
if (!(event.data.jid in this.jobs))
|
||||
this.$set(this.jobs, event.data.jid, new Job(event.data.jid));
|
||||
this.jobs[event.data.jid].addEvent(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
isEventType<T extends salt.SaltEvent['splitTag'][1]>(
|
||||
event: salt.SaltEvent,
|
||||
type: T
|
||||
): event is Extract<salt.SaltEvent, { splitTag: ['salt', T, ...any[]] }> {
|
||||
return event.splitTag[1] === type;
|
||||
}
|
||||
|
||||
isJobEventType<T extends salt.SaltEvent['splitTag'][3]>(
|
||||
event: salt.SaltEvent,
|
||||
type: T
|
||||
): event is Extract<
|
||||
salt.SaltEvent,
|
||||
{ splitTag: ['salt', 'job', any, T, ...any[]] }
|
||||
> {
|
||||
return event.splitTag[3] === type;
|
||||
}
|
||||
|
||||
event_name(event: salt.JobEvent) {
|
||||
if (isJobEventType(event, 'prog')) {
|
||||
if (this.isJobEventType(event, 'prog')) {
|
||||
return `${this.event_symbol(event)} Progress: ${
|
||||
event.data.data.ret.name
|
||||
}|${event.data.data.ret.duration} `;
|
||||
} else if (isJobEventType(event, 'ret')) {
|
||||
} else if (this.isJobEventType(event, 'ret')) {
|
||||
return `${this.event_symbol(event)} Return: ${event.data.fun} `;
|
||||
}
|
||||
}
|
||||
|
||||
event_symbol(event: salt.JobEvent) {
|
||||
if (isJobEventType(event, 'prog')) {
|
||||
if (this.isJobEventType(event, 'prog')) {
|
||||
const ret = event.data.data.ret;
|
||||
if (!ret.result) return '✗';
|
||||
else if (Object.keys(ret.changes).length !== 0) return 'Δ';
|
||||
else return '✓';
|
||||
} else if (isJobEventType(event, 'ret')) {
|
||||
} else if (this.isJobEventType(event, 'ret')) {
|
||||
return event.data.success ? '✓' : '✗';
|
||||
}
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
// {jid: {mid: event[]}}
|
||||
get jobs(): { [key: string]: { [key: string]: salt.JobEvent[] } } {
|
||||
return this.events.reduce(
|
||||
(
|
||||
acc: { [key: string]: { [key: string]: salt.JobEvent[] } },
|
||||
e: salt.SaltEvent
|
||||
) => {
|
||||
if (
|
||||
isEventType(e, 'job') &&
|
||||
(isJobEventType(e, 'prog') || isJobEventType(e, 'ret'))
|
||||
) {
|
||||
if (!(e.data.jid in acc)) acc[e.data.jid] = {};
|
||||
if (!(e.data.id in acc[e.data.jid])) acc[e.data.jid][e.data.id] = [];
|
||||
acc[e.data.jid][e.data.id].push(e);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -124,6 +152,11 @@ export default class App extends Vue {
|
||||
margin-left: 2ex;
|
||||
}
|
||||
|
||||
.header-jid {
|
||||
font-size: x-small;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user