agola-web/src/components/log.vue

142 lines
3.0 KiB
Vue
Raw Normal View History

2018-12-09 13:21:20 +00:00
<template>
<div class="dark">
<div class="log">
<div class="stream-line" v-for="(item, index) in items" :key="index">
<div v-html="item"/>
</div>
</div>
</div>
</template>
<script>
import { apiurl, apiurlwithtoken, fetch } from "@/util/auth";
import AnsiUp from "ansi_up";
export default {
name: "Log",
props: {
show: Boolean,
runid: String,
taskid: String,
2019-03-13 14:42:58 +00:00
setup: Boolean,
2018-12-09 13:21:20 +00:00
step: Number,
stepphase: String
},
computed: {},
data() {
let formatter = new AnsiUp();
formatter.use_classes = true;
return {
items: [],
lines: [],
formatter: formatter,
es: null,
fetching: false
};
},
methods: {
2019-03-29 17:19:07 +00:00
fetch() {
2018-12-09 13:21:20 +00:00
if (this.fetching) {
return;
}
this.fetching = true;
if (this.stepphase == "running") {
this.streamLogs();
}
if (this.stepphase == "success" || this.stepphase == "failed") {
this.getLogs();
}
},
2019-03-29 17:19:07 +00:00
streamLogs() {
2019-03-13 14:42:58 +00:00
let path = "/logs?runID=" + this.runid + "&taskID=" + this.taskid;
if (this.setup) {
path += "&setup";
} else {
path += "&step=" + this.step;
}
path += "&follow&stream";
this.es = new EventSource(apiurlwithtoken(path));
2018-12-09 13:21:20 +00:00
this.es.onmessage = event => {
var data = event.data;
// TODO(sgotti) ansi_up doesn't handle carriage return (\r), find a way to also handle it
this.items.push(this.formatter.ansi_to_html(data));
};
// don't reconnect on error
this.es.onerror = () => {
this.es.close();
};
},
2019-03-29 17:19:07 +00:00
async getLogs() {
2019-03-13 14:42:58 +00:00
let path = "/logs?runID=" + this.runid + "&taskID=" + this.taskid;
if (this.setup) {
path += "&setup";
} else {
path += "&step=" + this.step;
}
2019-03-29 17:19:07 +00:00
let res = await fetch(apiurl(path))
2018-12-09 13:21:20 +00:00
.then(r => {
if (r.status == 200) {
return r.text();
}
return "";
})
.then(data => {
this.items.push(this.formatter.ansi_to_html(data));
});
}
},
watch: {
show: function(post, pre) {
if (pre == false && post == true) {
this.fetch();
}
},
stepphase: function(post, pre) {
if (pre == "notstarted" && post == "running") {
this.streamLogs();
}
if (pre == "notstarted" && (post == "success" || post == "failed")) {
this.getLogs();
}
if (pre == "running" && (post == "success" || post == "failed")) {
// TODO(sgotti)
}
}
},
created: function() {
if (this.show) {
this.fetch();
}
},
beforeDestroy() {
if (this.es !== null) {
this.es.close();
}
}
};
</script>
<style scoped lang="scss">
.log {
background-color: #222;
color: #f1f1f1;
font-family: Cousine, monospace;
font-size: 12px;
line-height: 19px;
white-space: pre-wrap;
word-wrap: break-word;
text-align: left;
font-size: 12px;
padding: 5px;
.stream-line {
pre {
line-height: 1.2;
}
}
}
</style>