mirror of
https://github.com/YunoHost/yunorunner.git
synced 2024-09-03 20:05:52 +02:00
154 lines
6.7 KiB
HTML
154 lines
6.7 KiB
HTML
<% extends "base.html" %>
|
|
|
|
<% block content %>
|
|
<section class="section">
|
|
<div class="container">
|
|
<h1 class="title">Apps</h1>
|
|
<div id="apps">
|
|
<template v-if="inited">
|
|
<table class="table is-bordered is-hoverable is-striped is-fullwidth">
|
|
<thead>
|
|
<th>App</th>
|
|
<th>Last job</th>
|
|
<th>Created time</th>
|
|
<th>Started time</th>
|
|
<th>End time</th>
|
|
<th>Repo</th>
|
|
<th>Commit</th>
|
|
<th title="random day of the month on which a job is scheduled for this app">Day</th>
|
|
</thead>
|
|
<template v-if="apps.length > 0">
|
|
<tr v-for="(app, index) in apps" :id="app.id" v-bind:class="[app.job_state + 'Job']">
|
|
<td><a v-bind:href="app.name + '/'">{{app.name}}</a></td>
|
|
<td><a v-bind:href="'<{ relative_path_to_root }>job/' + app.job_id">#{{app.job_id}}</a> <span v-bind:class="['tag', jobStateTagClass(app.job_state)]">{{app.job_state}}</span></td>
|
|
<td>{{timestampToDate(app.created_time)}}</td>
|
|
<td>{{timestampToDate(app.started_time)}}</td>
|
|
<td>{{timestampToDate(app.end_time)}}</td>
|
|
<td><a target="_blank" v-bind:href="app.url">repo</a></td>
|
|
<td><a target="_blank" v-bind:href="app.url + '/commit/' + app.revision">{{app.revision.slice(0, 7)}}</a></td>
|
|
<td class="randomJobDay" title="random day of the month on which a job is scheduled for this app">{{app.random_job_day}}</td>
|
|
</tr>
|
|
</template>
|
|
<template v-else>
|
|
<tr><td colspan="7">Not apps available yet.</td></tr>
|
|
</template>
|
|
</table>
|
|
</template>
|
|
<div v-else>Loading...</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<% endblock %>
|
|
|
|
<% block javascript %>
|
|
<script>
|
|
(function() {
|
|
var app = new Vue({
|
|
el: '#apps',
|
|
data: {
|
|
apps: [],
|
|
inited: false,
|
|
},
|
|
methods: {
|
|
timestampToDate: function (timestamp) {
|
|
if (timestamp === null) return "";
|
|
|
|
return new Date(timestamp * 1000).toLocaleString()
|
|
},
|
|
appStateTagClass: function (appState) {
|
|
// this is one the only used one
|
|
if (appState == "working")
|
|
return {"is-success": true}
|
|
// other states notworking inprogress validated
|
|
if (appState == "")
|
|
return {"is-danger": true}
|
|
return {"is-danger": true}
|
|
},
|
|
jobStateTagClass: function (jobState) {
|
|
if (jobState == "done")
|
|
return {"is-success": true}
|
|
if (jobState == "failure")
|
|
return {"is-danger": true}
|
|
if (jobState == "canceled")
|
|
return {"is-warning": true}
|
|
if (jobState == "running")
|
|
return {"is-info": true}
|
|
}
|
|
}
|
|
})
|
|
|
|
ws = new ReconnectingWebSocket(websocketPrefix() + '://' + document.domain + ':' + location.port + websocketRelativePath('<{ path }>') + '/apps-ws');
|
|
|
|
ws.onmessage = function (event) {
|
|
var message = JSON.parse(event.data);
|
|
var data = message.data;
|
|
var action = message.action;
|
|
|
|
if (action == "init_apps") {
|
|
app.apps = data;
|
|
Vue.set(app, 'inited', true);
|
|
} else if (action == "new_app") {
|
|
for (var i = 0; i < app.apps.length; ++i) {
|
|
if (data.name < app.apps[i].name) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// I need to set everything as null then a first job should be
|
|
// created right after the app
|
|
app.apps.splice(i, 0, Object.assign(data, {
|
|
"job_id": null,
|
|
"job_name": null,
|
|
"url_or_path": null,
|
|
"job_state": null,
|
|
"log": null,
|
|
"created_time": null,
|
|
"started_time": null,
|
|
"end_time": null,
|
|
}));
|
|
} else if (action == "update_app") {
|
|
for (var i = 0; i < app.apps.length; ++i) {
|
|
if (app.apps[i].id == data.id) {
|
|
Vue.set(app.apps[i], 'name', data.name);
|
|
Vue.set(app.apps[i], 'state', data.state);
|
|
Vue.set(app.apps[i], 'url', data.url);
|
|
Vue.set(app.apps[i], 'revision', data.revision);
|
|
Vue.set(app.apps[i], 'random_job_day', data.random_job_day);
|
|
break;
|
|
}
|
|
}
|
|
} else if (action == "delete_app") {
|
|
for (var i = 0; i < app.apps.length; ++i) {
|
|
if (app.apps[i].id == data.id) {
|
|
app.apps.splice(i, i);
|
|
break;
|
|
}
|
|
}
|
|
} else if (action == "update_job") {
|
|
for (var i = 0; i < app.apps.length; ++i) {
|
|
if (app.apps[i].job_id == data.id) {
|
|
Vue.set(app.apps[i], 'job_state', data.state);
|
|
Vue.set(app.apps[i], 'created_time', data.created_time);
|
|
Vue.set(app.apps[i], 'started_time', data.started_time);
|
|
Vue.set(app.apps[i], 'end_time', data.end_time);
|
|
break;
|
|
}
|
|
}
|
|
} else if (action == "new_job") {
|
|
for (var i = 0; i < app.apps.length; ++i) {
|
|
if (app.apps[i].url == data.url_or_path) {
|
|
Vue.set(app.apps[i], 'job_id', data.id);
|
|
Vue.set(app.apps[i], 'job_name', data.name);
|
|
Vue.set(app.apps[i], 'job_state', data.state);
|
|
Vue.set(app.apps[i], 'created_time', data.created_time);
|
|
Vue.set(app.apps[i], 'started_time', data.started_time);
|
|
Vue.set(app.apps[i], 'end_time', data.end_time);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
})()
|
|
</script>
|
|
<% endblock %>
|