mirror of
https://github.com/YunoHost/tartiflette.git
synced 2024-09-03 20:06:08 +02:00
First working version of the app maintainer dashboard
This commit is contained in:
parent
5f456bbcd7
commit
905ee51e6d
4 changed files with 222 additions and 7 deletions
22
app/app.py
22
app/app.py
|
@ -1,6 +1,7 @@
|
|||
from flask import render_template, make_response, Blueprint
|
||||
from .models.pr import PullRequest
|
||||
from .models.appci import App, AppCI, AppCIBranch
|
||||
from .models.applists import App
|
||||
from .models.appci import AppCI, AppCIBranch
|
||||
from .models.unlistedapps import UnlistedApp
|
||||
from .settings import SITE_ROOT
|
||||
import json
|
||||
|
@ -118,6 +119,9 @@ def badge(app):
|
|||
|
||||
badge = "level%s.svg" % level if not level is None else "unknown.svg"
|
||||
|
||||
if not app.ci_enabled:
|
||||
badge = "unknown.svg"
|
||||
|
||||
svg = open("./app/static/badges/%s" % badge).read()
|
||||
response = make_response(svg)
|
||||
response.content_type = 'image/svg+xml'
|
||||
|
@ -151,3 +155,19 @@ def appsobservatory_unlisted():
|
|||
|
||||
return render_template("unlistedapps.html", apps=apps)
|
||||
|
||||
@main.route('/app_maintainer_dash')
|
||||
def app_maintainer_dash():
|
||||
|
||||
maintainers = set()
|
||||
apps = App.query.all()
|
||||
for app in apps:
|
||||
maintainers.update(app.maintainers)
|
||||
for test in app.most_recent_tests_per_branch():
|
||||
if test.branch.name == "stable":
|
||||
app.ci_level = test.level
|
||||
|
||||
maintainers = sorted(maintainers, key=lambda m: m.lower())
|
||||
apps = sorted(apps, key=lambda app: app.name.lower())
|
||||
|
||||
return render_template("maintainer.html", maintainers=maintainers, apps=apps)
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class AppList(db.Model):
|
|||
known_app.maintainers = [ maintainer["name"] for maintainer in maintainers_info ]
|
||||
|
||||
known_app.maintained = app.get("maintained", True)
|
||||
known_app.state = app["state"]
|
||||
known_app.ci_enabled = app["state"] == self.state_for_ci
|
||||
known_app.public_level = app.get("level", None)
|
||||
|
||||
|
@ -78,20 +79,18 @@ class AppList(db.Model):
|
|||
|
||||
known_app.public_commit = app["git"]["revision"]
|
||||
known_app.master_commit = g.commit(known_app, "master")
|
||||
known_app.public_commit_date = g.commit_date(known_app, known_app.public_commit)
|
||||
known_app.master_commit_date = g.commit_date(known_app, known_app.master_commit)
|
||||
known_app.testing_diff = g.diff(known_app, "master", "testing")["ahead_by"]
|
||||
known_app.opened_issues = issues_and_prs["nb_issues"]
|
||||
known_app.opened_prs = issues_and_prs["nb_prs"]
|
||||
|
||||
known_app.public_vs_master_time_diff = \
|
||||
(g.commit_date(known_app, known_app.master_commit) -
|
||||
g.commit_date(known_app, known_app.public_commit)).days
|
||||
else:
|
||||
known_app.public_commit = "???"
|
||||
known_app.master_commit = "???"
|
||||
known_app.testing_diff = -1
|
||||
known_app.opened_issues = 0
|
||||
known_app.opened_prs = 0
|
||||
known_app.public_vs_master_time_diff = 0
|
||||
|
||||
try:
|
||||
db.session.commit()
|
||||
|
@ -106,6 +105,7 @@ class App(db.Model):
|
|||
repo = db.Column(db.String(128), unique=True, nullable=False)
|
||||
maintainers = db.Column(db.PickleType)
|
||||
maintained = db.Column(db.Boolean, nullable=False)
|
||||
state = db.Column(db.String(64), nullable=False)
|
||||
ci_enabled = db.Column(db.Boolean, nullable=False)
|
||||
public_level = db.Column(db.Integer, default=-1, nullable=True)
|
||||
|
||||
|
@ -115,10 +115,11 @@ class App(db.Model):
|
|||
# 'Status info' stuff
|
||||
public_commit = db.Column(db.String(64), nullable=False)
|
||||
master_commit = db.Column(db.String(64), nullable=False)
|
||||
public_commit_date = db.Column(db.DateTime, nullable=True)
|
||||
master_commit_date = db.Column(db.DateTime, nullable=True)
|
||||
testing_diff = db.Column(db.Integer, default=-1)
|
||||
opened_issues = db.Column(db.Integer, default=-1)
|
||||
opened_prs = db.Column(db.Integer, default=-1)
|
||||
public_vs_master_time_diff = db.Column(db.Integer, default=9999)
|
||||
|
||||
def __repr__(self):
|
||||
return '<App %r>' % self.name
|
||||
|
@ -126,9 +127,13 @@ class App(db.Model):
|
|||
def init():
|
||||
pass
|
||||
|
||||
@property
|
||||
def public_vs_master_time_diff(self):
|
||||
return (self.public_commit_date - self.master_commit_date).days
|
||||
|
||||
def most_recent_tests_per_branch(self):
|
||||
|
||||
from appci import AppCIBranch, AppCIResult, AppCI
|
||||
from app.models.appci import AppCIBranch, AppCIResult, AppCI
|
||||
branches = AppCIBranch.query.all()
|
||||
for branch in branches:
|
||||
most_recent_test = AppCIResult.query \
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
<a class="dropdown-item" href="{{ url_for('main.appsobservatory_unlisted')}}">Unlisted apps</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('main.app_maintainer_dash') }}">App maintainer dashboard</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
187
app/templates/maintainer.html
Normal file
187
app/templates/maintainer.html
Normal file
|
@ -0,0 +1,187 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="mx-auto">
|
||||
<select id="maintainer-select">
|
||||
<option value="all">All</option>
|
||||
<option value="nobody">Nobody / Unmaintained</option>
|
||||
{% for maintainer in maintainers %}
|
||||
<option value="{{ maintainer.lower()|replace(" ", "") }}">{{ maintainer }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="mx-auto">
|
||||
<div>
|
||||
<table class="table table-responsive ci-app-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="ci-app-row-title">App</th>
|
||||
<th class="ci-app-test-title"><div>Declared state</div></th>
|
||||
<th class="ci-app-test-title"><div>Maintained</div></th>
|
||||
<th class="ci-app-test-title"><div>Public level</div></th>
|
||||
<th class="ci-app-test-title"><div>CI level</div></th>
|
||||
<th class="ci-app-test-title"><div># opened issues</div></th>
|
||||
<th class="ci-app-test-title"><div># opened PR</div></th>
|
||||
<th class="ci-app-test-title"><div>Last commit</div></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for app in apps %}
|
||||
<tr class="appline" app="{{ app.name }}" maintainers="{% for m in app.maintainers %}{{ m.lower()|replace(" ", "") }}|{% endfor %}" maintained="{{ app.maintained }}">
|
||||
|
||||
|
||||
<td class="ci-app-row-title">
|
||||
<a href="{{ url_for('main.appci_app', app=app.name) }}">
|
||||
<span class="font-weight-bold" title="More tests / info for this app">
|
||||
{{ app.name }}</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
{% if app.list.name == "official" %}
|
||||
<span class="official-star oi oi-star" title="Official" aria-hidden="true"></span>
|
||||
{% elif app.state == "working" %}
|
||||
<span class="text-success oi oi-circle-check" title="Working" aria-hidden="true"></span>
|
||||
{% elif app.state == "inprogress" %}
|
||||
<span class="text-warning oi oi-wrench" title="In progress" aria-hidden="true"></span>
|
||||
{% else %}
|
||||
<span class="text-danger oi oi-fire" title="Not working" aria-hidden="true"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
|
||||
{% if app.maintained %}
|
||||
<td class="text-success">
|
||||
<span class="oi oi-circle-check" aria-hidden="true"></span>
|
||||
{% else %}
|
||||
<td class="text-warning">
|
||||
<span class="oi oi-warning" aria-hidden="true"></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
|
||||
{% if app.state == "inprogress" or app.state == "notworking" %}
|
||||
<td class="ci-app-level"><div title="Public Level"></div></td>
|
||||
<td class="ci-app-level"><div title="CI Level"></div></td>
|
||||
{% else %}
|
||||
|
||||
|
||||
<td class="ci-app-level
|
||||
{% if app.public_level == None or app.public_level == -1 or app.public_level == "?" %}
|
||||
table-active
|
||||
{% elif app.public_level <= 0 %}
|
||||
table-danger
|
||||
{% elif app.public_level <= 2 %}
|
||||
table-warning
|
||||
{% else %}
|
||||
table-success
|
||||
{% endif %}
|
||||
" value="{{ app.public_level }}">
|
||||
<div title="Public Level"><strong>{{ app.public_level if app.public_level >= 0 else "?" }}</strong></div>
|
||||
</td>
|
||||
|
||||
|
||||
<td class="ci-app-level
|
||||
{% if app.ci_level == None or app.ci_level == -1 or app.ci_level == "?" %}
|
||||
table-active
|
||||
{% elif app.ci_level <= 0 %}
|
||||
table-danger
|
||||
{% elif app.ci_level <= 2 %}
|
||||
table-warning
|
||||
{% else %}
|
||||
table-success
|
||||
{% endif %}
|
||||
" value="{{ app.ci_level }}">
|
||||
<div title="CI Level"><strong>{{ app.ci_level if app.ci_level and app.ci_level >= 0 else "?" }}</strong></div>
|
||||
</td>
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
<td class="font-weight-bold
|
||||
{% if app.opened_issues >= 10 %}
|
||||
text-danger
|
||||
{% elif app.opened_issues >= 5 %}
|
||||
text-warning
|
||||
{% elif app.opened_issues > 0 %}
|
||||
text-active
|
||||
{% else %}
|
||||
text-success
|
||||
{% endif %}
|
||||
">{{ app.opened_issues }}</a></td>
|
||||
|
||||
|
||||
<td class="font-weight-bold
|
||||
{% if app.opened_prs > 0 %}
|
||||
text-info
|
||||
{% endif %}
|
||||
">{{ app.opened_prs }}</td>
|
||||
|
||||
|
||||
<td class="ci-app-test-info">
|
||||
{% if app.public_commit_date %}
|
||||
<span class="daysAgo" timestamp={{ app.public_commit_date.timestamp() }}></span></td>
|
||||
{% else %}
|
||||
<span class="daysAgo">???</span></td>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td class="px-0">
|
||||
<a href="{{ app.repo }}">
|
||||
<span class="oi oi-external-link text-info"
|
||||
aria-hidden="true"
|
||||
title="To the Git repo!"></span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
$('#maintainer-select').on('change', function() {
|
||||
var maintainer = this.value;
|
||||
if (maintainer == "all")
|
||||
{
|
||||
$(".appline").show();
|
||||
return;
|
||||
}
|
||||
else if (maintainer == "nobody")
|
||||
{
|
||||
$(".appline").each(function (i) {
|
||||
if ((this.attributes["maintainers"].value == "") || (this.attributes["maintained"].value == "False"))
|
||||
{
|
||||
$(this).show();
|
||||
}
|
||||
else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$(".appline").each(function (i) {
|
||||
var maintainers = this.attributes["maintainers"].value.split("|");
|
||||
if (maintainers.includes(maintainer)) {
|
||||
$(this).show();
|
||||
}
|
||||
else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue