Commit 16f5f1ba authored by Louis's avatar Louis
Browse files

Use chartsjs.org to draw line charts (was morrisjs before)

parent d149f623
* pypimonitor 0.2.0 (unreleased)
* Name changed from "pypistats" to "pypimonitor".
* Use chartsjs.org to draw line charts (was morrisjs before).
-- Louis Paternault <spalax@gresille.org>
......
......@@ -3,7 +3,10 @@
- [ ] - Connection to http://localhost:PORT/foo: render DIR1/foo.yaml as an html page (or DIR2/foo.yaml if not found)
- [ ] - Connection to http://localhost:PORT: same action as now, using pkg=, usr=, and row= arguments. The array is limited to some pypi-only cells
- [ ] Change default port
- [ ] Use chart.js (see TODO/chart.html)
- [x] Use chart.js (see TODO/chart.html)
- [x] Use it
- [x] Remove outdated methods `iter_*`
- [x] Remove TODO/chart.html
- [ ] Utiliser l'API json qui n'est pas sensible à la casse
- json.loads(requests.get("http://pypi.python.org/pypi/pdfautonup/json").text)
- [ ] Display "Listening to http://localhost:PORT"
......
<!doctype html>
<html>
<head>
<title>Line Chart</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.1/Chart.bundle.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<div style="width:95%;">
<canvas id="canvas"></canvas>
</div>
<script>
var config = {
type: 'line',
data: {
datasets: [{
label: "argdispatch",
fill: false,
borderColor: "#F7464A",
pointBackgroundColor: "#F7464A",
backgroundColor: "rgba(0,0,0,0)",
data: [{
x: "2015-02-03 23:33:51",
y: 2,
version: "0.1.0",
}, {
x: "2015-02-04 23:33:51",
y: 3,
version: "0.2.0",
}, {
x: "2015-02-05 13:33:51",
y: 2,
version: "0.3.0",
}, {
x: "2015-02-06 13:33:51",
y: 4,
}],
}, {
label: "papersize",
fill: false,
borderColor: "#4AF746",
pointBackgroundColor: "#4AF746",
backgroundColor: "rgba(0,0,0,0)",
fill: true,
data: [{
x: "2015-02-03 13:33:51",
y: 3,
version: "0.1.0",
}, {
x: "2015-02-04 13:33:51",
y: 4,
version: "0.1.1",
}, {
x: "2015-02-06 13:33:51",
y: 3,
}],
}]
},
options: {
responsive: true,
defaultColor: "rgba(0, 0, 0, 0)",
title:{
display:true,
text:'Download counts'
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
var version = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]['version'];
if (typeof version == "undefined") {
return tooltipItem.xLabel + ": " + tooltipItem.yLabel;
} else {
return tooltipItem.xLabel + " (version " + version + "): " + tooltipItem.yLabel;
}
},
}
},
hover: {
mode: 'label'
},
scales: {
xAxes: [{
type: "time",
display: true,
}, ],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Downloads'
}
}]
}
}
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart.Scatter(ctx, config);
};
</script>
</body>
</html>
......@@ -55,30 +55,6 @@ class PackageList:
def __getitem__(self, key):
return self.packages[key]
def iter_dated_downloads(self, name=None):
if name is None:
packages = list(self.values())
else:
packages = [self[name]]
for date in set(itertools.chain(*(package.iter_dates() for package in packages))):
downloads = []
for package in packages:
try:
downloads.append((package.name, package.releases[date]['previous']))
except KeyError:
pass
yield (date, downloads)
yield (
datetime.datetime.now(),
[(package.name, package.total_downloads) for package in packages],
)
def iter_ykeys(self, name=None):
if name is None:
yield from self
else:
yield name
def DateTime2datetime(date):
timetuple = date.timetuple()
return datetime.datetime(
......
from urllib.parse import urlparse, parse_qs
import colorsys
import datetime
import functools
import http.server
import jinja2
......@@ -36,6 +37,7 @@ def _get_environment():
env = jinja2.Environment(loader=jinja2.FileSystemLoader(TEMPLATEDIR))
env.globals['counter'] = Counter().count
env.globals['now'] = datetime.datetime.now()
env.filters['PackageList'] = PackageList
env.filters['datetime'] = operator.methodcaller('strftime', "%Y-%m-%d %H:%M:%S")
env.filters['as_id'] = as_id
......
......@@ -5,13 +5,11 @@
<head>
<meta charset="utf-8">
<title>Pypi statistics</title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.1/Chart.bundle.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
{{ linecharts.plot(packages, none) }}
{{ linecharts.plot(packages.values()) }}
{% from "badge.html" import render as render_badge %}
<table>
......@@ -34,7 +32,7 @@
</table>
{% for package in packages|sort %}
{{ linecharts.plot(packages, package) }}
{{ linecharts.plot([packages[package]]) }}
{% endfor %}
</body>
</html>
{% macro plot(packagelist, name) -%}
{% macro plot(packagelist) -%}
{% set id = counter() %}
<div id="linechart{{ id }}" style="height: 250px;"></div>
<div style="width: 95%;">
<canvas id="linechart{{ id }}"></canvas>
</div>
<script>
new Morris.Line({
element: "linechart{{ id }}",
data: [
{% for date, downloads in packagelist.iter_dated_downloads(name) %}
{'date': '{{ date|datetime }}',
{%- for name, download in downloads -%}
{{ name|as_id }}: {{ download }}
{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
var config{{ id }} = {
type: 'line',
data: {
datasets: [
{% for package in packagelist %}
{
label: "{{ package.name }}",
fill: false,
borderColor: "{{ package.name | color(0.5, 0.8) }}",
pointBackgroundColor: "{{ package.name | color(0.5, 0.8) }}",
backgroundColor: "{{ package.name | color(0.5, 0.8) }}",
data: [
{%- for date in package.releases|sort -%}
{
x: "{{ date }}",
y: {{ package.releases[date].previous }},
version: "{{ package.releases[date].version }}"
},
{%- endfor -%}
{
x: "{{ now|datetime }}",
y: {{ package.total_downloads }},
}],
},
{% endfor %}
]
},
options: {
responsive: true,
defaultColor: "rgba(0, 0, 0, 0)",
title:{
display:true,
text:'Download counts'
},
tooltips: {
mode: 'label',
callbacks: {
label: function(tooltipItem, data) {
var version = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]['version'];
if (typeof version == "undefined") {
return tooltipItem.xLabel + ": " + tooltipItem.yLabel;
} else {
return tooltipItem.xLabel + " (version " + version + "): " + tooltipItem.yLabel;
}
{%- if not loop.last %},{% endif -%}
{% endfor %}
],
xkey: 'date',
ykeys: [{% for key in packagelist.iter_ykeys(name) -%}
"{{ key|as_id }}"
{%- if not loop.last %}, {% endif -%}
{%- endfor %}],
labels: [{% for key in packagelist.iter_ykeys(name) -%}
"{{ key }}"
{%- if not loop.last %}, {% endif -%}
{% endfor %}],
lineColors: [{% for key in packagelist.iter_ykeys(name) -%}
"{{ key |color(0.5, 0.8) }}"
{%- if not loop.last %}, {% endif -%}
{% endfor %}]
});
},
}
},
hover: {
mode: 'label'
},
scales: {
xAxes: [{
type: "time",
display: true,
}, ],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Downloads'
}
}]
}
}
};
window.addEventListener("load", function(event) {
window.myLine{{ id }} = new Chart.Scatter(
document.getElementById("linechart{{ id }}").getContext("2d"),
config{{ id }}
)
});
</script>
{%- endmacro %}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment