dataviz: add a gauge cell (#8477)
This commit is contained in:
parent
a2a1b66783
commit
5bde8c06ca
10
README
10
README
|
@ -126,3 +126,13 @@ details.
|
|||
|
||||
You should have received a copy of the GNU Affero General Public License along
|
||||
with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
Combo embeds some other pieces of code, with their own authors and copyright
|
||||
notices:
|
||||
|
||||
Gauge.js
|
||||
Files: combo/apps/dataviz/static/js/gauge.min.js
|
||||
License: MIT
|
||||
Comment:
|
||||
From http://bernii.github.io/gauge.js/
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2015 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import django.apps
|
||||
|
||||
class AppConfig(django.apps.AppConfig):
|
||||
name = 'combo.apps.dataviz'
|
||||
|
||||
def get_before_urls(self):
|
||||
from . import urls
|
||||
return urls.urlpatterns
|
||||
|
||||
default_app_config = 'combo.apps.dataviz.AppConfig'
|
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0001_initial'),
|
||||
('data', '0012_auto_20151029_1535'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Gauge',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('placeholder', models.CharField(max_length=20)),
|
||||
('order', models.PositiveIntegerField()),
|
||||
('slug', models.SlugField(verbose_name='Slug', blank=True)),
|
||||
('public', models.BooleanField(default=True, verbose_name='Public')),
|
||||
('restricted_to_unlogged', models.BooleanField(default=False, verbose_name='Restrict to unlogged users')),
|
||||
('title', models.CharField(max_length=150, null=True, verbose_name='Title', blank=True)),
|
||||
('url', models.URLField(max_length=150, null=True, verbose_name='URL', blank=True)),
|
||||
('data_source', models.CharField(max_length=150, null=True, verbose_name='Data Source', blank=True)),
|
||||
('max_value', models.PositiveIntegerField(null=True, verbose_name='Max Value', blank=True)),
|
||||
('groups', models.ManyToManyField(to='auth.Group', verbose_name='Groups', blank=True)),
|
||||
('page', models.ForeignKey(to='data.Page')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Gauge',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dataviz', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='gauge',
|
||||
name='jsonp_data_source',
|
||||
field=models.BooleanField(default=True, verbose_name='Use JSONP to get data'),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,57 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2014-2015 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from combo.data.models import CellBase
|
||||
from combo.data.library import register_cell_class
|
||||
|
||||
|
||||
@register_cell_class
|
||||
class Gauge(CellBase):
|
||||
title = models.CharField(_('Title'), max_length=150, blank=True, null=True)
|
||||
url = models.URLField(_('URL'), max_length=150, blank=True, null=True)
|
||||
data_source = models.CharField(_('Data Source'), max_length=150,
|
||||
blank=True, null=True)
|
||||
jsonp_data_source = models.BooleanField(_('Use JSONP to get data'),
|
||||
default=True)
|
||||
max_value = models.PositiveIntegerField(_('Max Value'), blank=True, null=True)
|
||||
|
||||
template_name = 'combo/gauge-cell.html'
|
||||
|
||||
class Media:
|
||||
js = ('js/gauge.min.js', 'js/combo.gauge.js')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Gauge')
|
||||
|
||||
def get_additional_label(self):
|
||||
return self.title
|
||||
|
||||
def get_cell_extra_context(self):
|
||||
if self.jsonp_data_source:
|
||||
data_source_url = self.data_source
|
||||
else:
|
||||
data_source_url = reverse('combo-ajax-gauge-count', kwargs={'cell': self.id})
|
||||
return {'cell': self,
|
||||
'title': self.title,
|
||||
'url': self.url,
|
||||
'max_value': self.max_value,
|
||||
'data_source_url': data_source_url,
|
||||
'jsonp': self.jsonp_data_source,
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
$(function() {
|
||||
var opts = {
|
||||
lines: 12, // The number of lines to draw
|
||||
angle: 0.15, // The length of each line
|
||||
lineWidth: 0.44, // The line thickness
|
||||
pointer: {
|
||||
length: 0.9, // The radius of the inner circle
|
||||
strokeWidth: 0.035, // The rotation offset
|
||||
color: '#000000' // Fill color
|
||||
},
|
||||
limitMax: 'false', // If true, the pointer will not go past the end of the gauge
|
||||
colorStart: '#6FADCF', // Colors
|
||||
colorStop: '#8FC0DA', // just experiment with them
|
||||
strokeColor: '#E0E0E0', // to see which ones work best for you
|
||||
percentColors: [[0.0, "#a9d70b" ], [0.8, "#f9c802"], [1.0, "#ff0000"]],
|
||||
generateGradient: true
|
||||
};
|
||||
$('[data-combo-gauge').each(function(idx, elem) {
|
||||
var target = $(elem).find('canvas')[0];
|
||||
var gauge = new Gauge(target).setOptions(opts);
|
||||
gauge.maxValue = parseInt($(elem).data('gauge-max-value'))
|
||||
gauge.set(0); // set actual value
|
||||
var ajax_params = {dataType: 'json'}
|
||||
if ($(elem).data('gauge-count-url')) {
|
||||
ajax_params.url = $(elem).data('gauge-count-url');
|
||||
} else {
|
||||
ajax_params.url = $(elem).data('gauge-count-jsonp-url');
|
||||
ajax_params.xhrFields = { withCredentials: true };
|
||||
ajax_params.crossDomain = true;
|
||||
}
|
||||
ajax_params.success = function(data) {
|
||||
if (data.count > gauge.maxValue) {
|
||||
gauge.animationSpeed = 16;
|
||||
gauge.set(gauge.maxValue);
|
||||
} else {
|
||||
gauge.set(data.count);
|
||||
}
|
||||
var counter_value = $('<span class="counter">' + data.count + '</span>').appendTo(elem);
|
||||
}
|
||||
$.ajax(ajax_params);
|
||||
});
|
||||
});
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
|||
<div
|
||||
data-combo-gauge="true"
|
||||
{% if jsonp %}
|
||||
data-gauge-count-jsonp-url="{{data_source_url}}"
|
||||
{% else %}
|
||||
data-gauge-count-url="{% url 'combo-ajax-gauge-count' cell=cell.id %}"
|
||||
{% endif %}
|
||||
data-gauge-max-value="{{max_value}}" class="bo-block">
|
||||
<canvas style="width: 100%;">
|
||||
</canvas>
|
||||
{% if title %}
|
||||
{% if url %}<a href="{{url}}">{% endif %}{{title}}{% if url %}</a>{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
|
@ -0,0 +1,24 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2014-2015 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import ajax_gauge_count
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^ajax/gauge-count/(?P<cell>[\w_-]+)/$',
|
||||
ajax_gauge_count, name='combo-ajax-gauge-count'),
|
||||
)
|
|
@ -0,0 +1,29 @@
|
|||
# combo - content management system
|
||||
# Copyright (C) 2015 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
import requests
|
||||
|
||||
from django.conf import settings
|
||||
from django.http import Http404, HttpResponse
|
||||
|
||||
from .models import Gauge
|
||||
|
||||
|
||||
def ajax_gauge_count(request, *args, **kwargs):
|
||||
gauge = Gauge.objects.get(id=kwargs['cell'])
|
||||
response = requests.get(gauge.data_source)
|
||||
return HttpResponse(response.content, content_type='text/json')
|
|
@ -18,3 +18,20 @@ div.welcome {
|
|||
div.textcell {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#content div.cell.gauge {
|
||||
width: 270px;
|
||||
max-width: 32%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.cell.gauge div.bo-block {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.cell.gauge div.bo-block span.counter {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 1ex;
|
||||
font-size: 300%;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue