Adding roadmapProgressBar as a dirty subfolder

This commit is contained in:
Alexandre Aubin 2017-03-17 19:27:52 +01:00
parent f7d624d068
commit 8a70a4216e
5 changed files with 302 additions and 0 deletions

90
roadmapProgressBar/analyze.py Executable file
View file

@ -0,0 +1,90 @@
#!/usr/bin/python3
import json
from bs4 import BeautifulSoup
status_filters = {
"all": None,
"new": ["New", "Confirmed"],
"ongoing": ["In Progress"],
"done": ["Closed", "Resolved", "Rejected"]
}
type_filters = {
"all": None,
"Bug": "Bug",
"Feature": "Feature",
"Improve": "Improvement",
"Doc": "Documentation"
}
def parse_issues():
soup = BeautifulSoup(open("data/raw_roadmapissues.xml").read(), "lxml")
issues = []
for issue in soup.issues:
cleaned_issue = {}
cleaned_issue["id"] = issue.id.text
cleaned_issue["priority"] = issue.priority["name"]
cleaned_issue["status"] = issue.status["name"]
cleaned_issue["type"] = issue.tracker["name"]
issues.append(cleaned_issue)
return issues
def filtered_issues(issues, status_filter=None, type_filter=None):
issues_filtered = issues
if status_filter != None:
issues_filtered = [ issue for issue in issues_filtered if issue["status"] in status_filter]
if type_filter != None:
issues_filtered = [ issue for issue in issues_filtered if issue["type"] == type_filter ]
return len(issues_filtered)
def main():
issues = parse_issues()
summary = {}
for type_name, type_filter in type_filters.items():
summary[type_name] = {}
for status_name, status_filter in status_filters.items():
summary[type_name][status_name] = filtered_issues(issues, status_filter,
type_filter)
for type_name, type_filter in type_filters.items():
for status_name, status_filter in status_filters.items():
if (status_name != "all"):
n = summary[type_name][status_name]
p = float("{0:.1f}".format(100 * n / summary[type_name]["all"]))
summary[type_name][status_name] = (n,p)
if (type_name != "all"):
n = summary[type_name]["all"]
p = float("{0:.1f}".format(100 * n / summary["all"]["all"]))
summary[type_name]["all"] = (n,p)
with open("summary.json", "w") as f:
f.write(json.dumps(summary))
main()

View file

14
roadmapProgressBar/fetch.py Executable file
View file

@ -0,0 +1,14 @@
#!/usr/bin/python3
import requests
import json
def get_roadmapissues():
roadmapissues = requests.get("https://dev.yunohost.org/issues.xml?fixed_version_id=11&status_id=*&limit=100")
with open("data/raw_roadmapissues.xml", "w") as f:
f.write(roadmapissues.text)
get_roadmapissues()

44
roadmapProgressBar/publish.py Executable file
View file

@ -0,0 +1,44 @@
#!/usr/bin/python3
import os
import json
from jinja2 import Template
from ansi2html import Ansi2HTMLConverter
from ansi2html.style import get_styles
###############################################################################
output_dir = "./www/"
template_path = os.path.join(output_dir,"template.html")
output_path = os.path.join(output_dir,"index.html")
summary_path = os.path.join("./", "summary.json")
###############################################################################
conv = Ansi2HTMLConverter()
shell_css = "\n".join(map(str, get_styles(conv.dark_bg, conv.scheme)))
def shell_to_html(shell):
return conv.convert(shell, False)
###############################################################################
if __name__ == '__main__':
# Fetch the list of all reports, sorted in reverse-chronological order
summary = json.load(open(summary_path))
# Generate the output using the template
template = open(template_path, "r").read()
t = Template(template)
result = t.render(data=summary, convert=shell_to_html, shell_css=shell_css)
open(output_path, "w").write(result)
print("Done.")

View file

@ -0,0 +1,154 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<title>Yunohost Pull Requests Dashboard</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="css/bootstrap.css" media="screen">
<link rel="stylesheet" href="skins/eden.css" media="screen">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link href="css/animate.css" rel="stylesheet">
<style>
.navbar-holder-dark{
padding: 20px 20px 200px 20px;
background: #333333;
}
.progress .progress-bar {
padding-top:5px;
font-size:16px;
font-weight: 600;
}
.progress-bar-none {
background-color:transparent;
color: #2c3e50;
}
.issue-legend {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
text-align: center;
font-weight: bold;
margin-bottom:20px;
}
</style>
</head>
<body>
<div class="container">
<div class="page-header" id="banner">
<div class="row">
<h1>Yunohost Roadmap Dashboard</h1>
</div>
</div>
<h3>2.6.x</h3>
<div class="row">
<div class="col-md-offset-1 col-md-10">
<div class="issue-legend">All ({{data.all.all}} issues) </div>
<div class="bs-component">
<div class="progress">
<div class="progress-bar progress-bar-success" style="width:
{{data.all.done[1]}}%">{{data.all.done[0]}} done</div>
<div class="progress-bar progress-bar-warning" style="width:
{{data.all.ongoing[1]}}%">{{data.all.ongoing[0]}}
ongoing</div>
<div class="progress-bar progress-bar-none" style="width:
{{data.all.new[1]}}%">{{data.all.new[0]}} new</div>
</div>
</div>
{% for type, statuses in data.items() %}
{% if type != "all" %}
<div class="bs-component" style="display:inline-block; width: {{
statuses.all[1]-0.5 }}%" >
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: {{statuses.done[1]}}%">
{{ statuses.done[0] }}
</div>
<div class="progress-bar progress-bar-warning" style="width: {{statuses.ongoing[1]}}%">
{{ statuses.ongoing[0] }}
</div>
<div class="progress-bar progress-bar-none" style="width:
{{statuses.new[1]}}%">
{{ statuses.new[0] }}
</div>
</div>
<div class="issue-legend">{{ type }}<br> ({{ statuses.all[0]
}})</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="col-md-offset-1 col-md-10">
</div>
</div>
<footer>
<div class="row">
<div class="col-lg-12">
<hr/>
<p>CSS Skin/boilerplate/whatever you call it : <a href="http://scripteden.com/" rel="nofollow">Script Eden</a>.</p>
</div>
</div>
</footer>
</div>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script>
function filter(team) {
// Declare variables
var input, filter, table, tr, td, i;
table = document.getElementById("thePRlist");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++)
{
if (team == '') { tr[i].style.display = ""; }
else if (tr[i].classList == "") { tr[i].style.display = ""; }
else if (tr[i].classList.contains(team)) { tr[i].style.display = ""; }
else { tr[i].style.display = "none"; }
}
selector = document.getElementById("select-team");
li = selector.getElementsByTagName("li");
if (team == "") { team = "team-all"; }
for (i = 0; i < li.length; i++)
{
if (li[i].getAttribute("id") == "select-".concat(team))
{
li[i].classList.add("active");
}
else
{
li[i].classList.remove("active");
}
}
}
</script>
</body>
</html>