mirror of
https://github.com/YunoHost/yunorunner.git
synced 2024-09-03 20:05:52 +02:00
[enh] make one new page per app
This commit is contained in:
parent
719cb13c08
commit
84cc6f86a3
2 changed files with 113 additions and 7 deletions
43
run.py
43
run.py
|
@ -322,7 +322,7 @@ async def run_job(worker, job):
|
||||||
await broadcast({
|
await broadcast({
|
||||||
"action": "update_job",
|
"action": "update_job",
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, ["jobs", f"job-{job.id}"])
|
}, ["jobs", f"job-{job.id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
# fake stupid command, whould run CI instead
|
# fake stupid command, whould run CI instead
|
||||||
task_logger.info(f"Starting job '{job.name}' #{job.id}...")
|
task_logger.info(f"Starting job '{job.name}' #{job.id}...")
|
||||||
|
@ -351,7 +351,7 @@ async def run_job(worker, job):
|
||||||
"action": "update_job",
|
"action": "update_job",
|
||||||
"id": job.id,
|
"id": job.id,
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, ["jobs", f"job-{job.id}"])
|
}, ["jobs", f"job-{job.id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
@ -385,7 +385,7 @@ async def run_job(worker, job):
|
||||||
"action": "update_job",
|
"action": "update_job",
|
||||||
"id": job.id,
|
"id": job.id,
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, ["jobs", f"job-{job.id}"])
|
}, ["jobs", f"job-{job.id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
|
|
||||||
async def broadcast(message, channels):
|
async def broadcast(message, channels):
|
||||||
|
@ -539,6 +539,24 @@ async def ws_apps(request, websocket):
|
||||||
await websocket.recv()
|
await websocket.recv()
|
||||||
|
|
||||||
|
|
||||||
|
@app.websocket('/app-<app_name>-ws')
|
||||||
|
async def ws_app(request, websocket, app_name):
|
||||||
|
# XXX I don't check if the app exists because this websocket is supposed to
|
||||||
|
# be only loaded from the app page which does this job already
|
||||||
|
app = Repo.select().where(Repo.name == app_name)[0]
|
||||||
|
|
||||||
|
subscribe(websocket, f"app-jobs-{app.url}")
|
||||||
|
|
||||||
|
await websocket.send(ujson.dumps({
|
||||||
|
"action": "init_jobs",
|
||||||
|
"data": Job.select().where(Job.url_or_path == app.url).order_by(-Job.id),
|
||||||
|
}))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# do nothing with input but wait
|
||||||
|
await websocket.recv()
|
||||||
|
|
||||||
|
|
||||||
def require_token():
|
def require_token():
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
|
@ -584,7 +602,7 @@ async def api_new_job(request):
|
||||||
await broadcast({
|
await broadcast({
|
||||||
"action": "new_job",
|
"action": "new_job",
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, "jobs")
|
}, ["jobs", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
return response.text("ok")
|
return response.text("ok")
|
||||||
|
|
||||||
|
@ -618,7 +636,7 @@ async def api_delete_job(request, job_id):
|
||||||
await broadcast({
|
await broadcast({
|
||||||
"action": "delete_job",
|
"action": "delete_job",
|
||||||
"data": data,
|
"data": data,
|
||||||
}, ["jobs", f"job-{job_id}"])
|
}, ["jobs", f"job-{job_id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
return response.text("ok")
|
return response.text("ok")
|
||||||
|
|
||||||
|
@ -643,7 +661,7 @@ async def api_stop_job(request, job_id):
|
||||||
await broadcast({
|
await broadcast({
|
||||||
"action": "update_job",
|
"action": "update_job",
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, ["jobs", f"job-{job.id}"])
|
}, ["jobs", f"job-{job.id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
return response.text("ok")
|
return response.text("ok")
|
||||||
|
|
||||||
|
@ -662,7 +680,7 @@ async def api_stop_job(request, job_id):
|
||||||
await broadcast({
|
await broadcast({
|
||||||
"action": "update_job",
|
"action": "update_job",
|
||||||
"data": model_to_dict(job),
|
"data": model_to_dict(job),
|
||||||
}, ["jobs", f"job-{job.id}"])
|
}, ["jobs", f"job-{job.id}", f"app-jobs-{job.url_or_path}"])
|
||||||
|
|
||||||
return response.text("ok")
|
return response.text("ok")
|
||||||
|
|
||||||
|
@ -710,6 +728,17 @@ async def html_apps(request):
|
||||||
return {'relative_path_to_root': '../', 'path': request.path}
|
return {'relative_path_to_root': '../', 'path': request.path}
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/apps/<app_name>/')
|
||||||
|
@jinja.template('app.html')
|
||||||
|
async def html_app(request, app_name):
|
||||||
|
app = Repo.select().where(Repo.name == app_name)
|
||||||
|
|
||||||
|
if app.count == 0:
|
||||||
|
raise NotFound()
|
||||||
|
|
||||||
|
return {"app": app[0], 'relative_path_to_root': '../../', 'path': request.path}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@jinja.template('index.html')
|
@jinja.template('index.html')
|
||||||
async def html_index(request):
|
async def html_index(request):
|
||||||
|
|
77
templates/app.html
Normal file
77
templates/app.html
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<% extends "base.html" %>
|
||||||
|
|
||||||
|
<% block content %>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title">Jobs for app <{ app.name }> <a target="_blank" href="<{ app.url }>">↪</a></h1>
|
||||||
|
<div id="jobs">
|
||||||
|
<table class="table is-bordered is-hoverable is-striped is-fullwidth">
|
||||||
|
<thead>
|
||||||
|
<th>App</th>
|
||||||
|
<th>State</th>
|
||||||
|
<th>Created time</th>
|
||||||
|
<th>Started time</th>
|
||||||
|
<th>End time</th>
|
||||||
|
</thead>
|
||||||
|
<tr v-for="(job, index) in jobs" :id="job.id" v-bind:class="[{deleted: job.deleted}, job.state + 'Job']">
|
||||||
|
<td><a v-if="!job.deleted" v-bind:href="'<{ relative_path_to_root }>job/' + job.id">{{job.name}}</a><span v-if="job.deleted">{{job.name}} (deleted)</span> <small title="job's id">#{{job.id}} </small></td>
|
||||||
|
<td>{{job.state}}</td>
|
||||||
|
<td>{{timestampToDate(job.created_time)}}</td>
|
||||||
|
<td>{{timestampToDate(job.started_time)}}</td>
|
||||||
|
<td>{{timestampToDate(job.end_time)}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<% endblock %>
|
||||||
|
|
||||||
|
<% block javascript %>
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var app = new Vue({
|
||||||
|
el: '#jobs',
|
||||||
|
data: {
|
||||||
|
jobs: []
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
timestampToDate: function (timestamp) {
|
||||||
|
console.log(timestamp)
|
||||||
|
if (timestamp === null) return "";
|
||||||
|
|
||||||
|
return new Date(timestamp * 1000).toLocaleString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
ws = new ReconnectingWebSocket(websocketPrefix() + '://' + document.domain + ':' + location.port + websocketRelativePath('<{ path }>') + '/app-<{ app.name }>-ws');
|
||||||
|
|
||||||
|
ws.onmessage = function (event) {
|
||||||
|
var message = JSON.parse(event.data);
|
||||||
|
var data = message.data;
|
||||||
|
var action = message.action;
|
||||||
|
|
||||||
|
if (action == "init_jobs") {
|
||||||
|
app.jobs = data;
|
||||||
|
} else if (action == "update_job") {
|
||||||
|
for (var i = 0; i < app.jobs.length; ++i) {
|
||||||
|
if (app.jobs[i].id == data.id) {
|
||||||
|
Vue.set(app.jobs, i, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (action == "new_job") {
|
||||||
|
app.jobs.splice(0, 0, data);
|
||||||
|
} else if (action == "delete_job") {
|
||||||
|
for (var i = 0; i < app.jobs.length; ++i) {
|
||||||
|
if (app.jobs[i].id == data.id) {
|
||||||
|
Vue.set(app.jobs[i], 'deleted', true);
|
||||||
|
Vue.set(app.jobs[i], 'state', 'deleted');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})()
|
||||||
|
</script>
|
||||||
|
<% endblock %>
|
Loading…
Add table
Reference in a new issue