Browse Source

Add D3, C3 and initial analytics view

tags/20180716
Sam Black 2 years ago
parent
commit
e4a72e077f
30 changed files with 19232 additions and 4 deletions
  1. +20
    -0
      LICENCES/c3js
  2. +26
    -0
      LICENCES/d3js
  3. +9236
    -0
      vowel/assets/js/charts/c3-0.4.18.js
  4. +9554
    -0
      vowel/assets/js/charts/d3-3.5.17.js
  5. +32
    -0
      vowel/assets/scss/charts/c3/arc.scss
  6. +4
    -0
      vowel/assets/scss/charts/c3/area.scss
  7. +14
    -0
      vowel/assets/scss/charts/c3/axis.scss
  8. +7
    -0
      vowel/assets/scss/charts/c3/bar.scss
  9. +3
    -0
      vowel/assets/scss/charts/c3/brush.scss
  10. +30
    -0
      vowel/assets/scss/charts/c3/chart.scss
  11. +9
    -0
      vowel/assets/scss/charts/c3/focus.scss
  12. +11
    -0
      vowel/assets/scss/charts/c3/grid.scss
  13. +13
    -0
      vowel/assets/scss/charts/c3/legend.scss
  14. +3
    -0
      vowel/assets/scss/charts/c3/line.scss
  15. +63
    -0
      vowel/assets/scss/charts/c3/main.scss
  16. +8
    -0
      vowel/assets/scss/charts/c3/point.scss
  17. +4
    -0
      vowel/assets/scss/charts/c3/region.scss
  18. +2
    -0
      vowel/assets/scss/charts/c3/select_drag.scss
  19. +7
    -0
      vowel/assets/scss/charts/c3/text.scss
  20. +3
    -0
      vowel/assets/scss/charts/c3/title.scss
  21. +38
    -0
      vowel/assets/scss/charts/c3/tooltip.scss
  22. +19
    -0
      vowel/models/analytics.py
  23. +20
    -0
      vowel/templates/analytics/index.html
  24. +23
    -0
      vowel/templates/analytics/organisation.html
  25. +4
    -2
      vowel/templates/layout/layout.html
  26. +7
    -1
      vowel/templates/layout/menu.html
  27. +1
    -1
      vowel/templates/layout/menu_anon.html
  28. +5
    -0
      vowel/utils/assets.py
  29. +64
    -0
      vowel/views/analytics.py
  30. +2
    -0
      vowel/web.py

+ 20
- 0
LICENCES/c3js View File

@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2013 Masayuki Tanaka

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 26
- 0
LICENCES/d3js View File

@@ -0,0 +1,26 @@
Copyright (c) 2010-2016, Michael Bostock
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* The name Michael Bostock may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 9236
- 0
vowel/assets/js/charts/c3-0.4.18.js
File diff suppressed because it is too large
View File


+ 9554
- 0
vowel/assets/js/charts/d3-3.5.17.js
File diff suppressed because it is too large
View File


+ 32
- 0
vowel/assets/scss/charts/c3/arc.scss View File

@@ -0,0 +1,32 @@
.c3-chart-arcs-title {
dominant-baseline: middle;
font-size: 1.3em;
}

.c3-chart-arcs .c3-chart-arcs-background {
fill: #e0e0e0;
stroke: none;
}
.c3-chart-arcs .c3-chart-arcs-gauge-unit {
fill: #000;
font-size: 16px;
}
.c3-chart-arcs .c3-chart-arcs-gauge-max {
fill: #777;
}
.c3-chart-arcs .c3-chart-arcs-gauge-min {
fill: #777;
}

.c3-chart-arc .c3-gauge-value {
fill: #000;
/* font-size: 28px !important;*/
}

.c3-chart-arc.c3-target g path {
opacity: 1;
}

.c3-chart-arc.c3-target.c3-focused g path {
opacity: 1;
}

+ 4
- 0
vowel/assets/scss/charts/c3/area.scss View File

@@ -0,0 +1,4 @@
.c3-area {
stroke-width: 0;
opacity: 0.2;
}

+ 14
- 0
vowel/assets/scss/charts/c3/axis.scss View File

@@ -0,0 +1,14 @@
.c3-axis-x .tick {
}
.c3-axis-x-label {
}

.c3-axis-y .tick {
}
.c3-axis-y-label {
}

.c3-axis-y2 .tick {
}
.c3-axis-y2-label {
}

+ 7
- 0
vowel/assets/scss/charts/c3/bar.scss View File

@@ -0,0 +1,7 @@
.c3-bar {
stroke-width: 0;
}
.c3-bar._expanded_ {
fill-opacity: 1;
fill-opacity: 0.75;
}

+ 3
- 0
vowel/assets/scss/charts/c3/brush.scss View File

@@ -0,0 +1,3 @@
.c3-brush .extent {
fill-opacity: .1;
}

+ 30
- 0
vowel/assets/scss/charts/c3/chart.scss View File

@@ -0,0 +1,30 @@
.c3 svg {
font: 10px sans-serif;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
.c3 path, .c3 line {
fill: none;
stroke: #000;
}
.c3 text {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}

.c3-legend-item-tile,
.c3-xgrid-focus,
.c3-ygrid,
.c3-event-rect,
.c3-bars path {
shape-rendering: crispEdges;
}

.c3-chart-arc path {
stroke: #fff;

}
.c3-chart-arc text {
fill: #fff;
font-size: 13px;
}

+ 9
- 0
vowel/assets/scss/charts/c3/focus.scss View File

@@ -0,0 +1,9 @@
.c3-target.c3-focused {
opacity: 1;
}
.c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step {
stroke-width: 2px;
}
.c3-target.c3-defocused {
opacity: 0.3 !important;
}

+ 11
- 0
vowel/assets/scss/charts/c3/grid.scss View File

@@ -0,0 +1,11 @@
.c3-grid line {
stroke: #aaa;
}
.c3-grid text {
fill: #aaa;
}
.c3-xgrid, .c3-ygrid {
stroke-dasharray: 3 3;
}
.c3-xgrid-focus {
}

+ 13
- 0
vowel/assets/scss/charts/c3/legend.scss View File

@@ -0,0 +1,13 @@
.c3-legend-item {
font-size: 12px;
}
.c3-legend-item-hidden {
opacity: 0.15;
}

.c3-legend-background {
opacity: 0.75;
fill: white;
stroke: lightgray;
stroke-width: 1
}

+ 3
- 0
vowel/assets/scss/charts/c3/line.scss View File

@@ -0,0 +1,3 @@
.c3-line {
stroke-width: 1px;
}

+ 63
- 0
vowel/assets/scss/charts/c3/main.scss View File

@@ -0,0 +1,63 @@
/*-- Chart --*/

@import 'chart';

/*-- Axis --*/

@import 'axis';

/*-- Grid --*/

@import 'grid';

/*-- Text on Chart --*/

@import 'text';

/*-- Line --*/

@import 'line';

/*-- Point --*/

@import 'point';

/*-- Bar --*/

@import 'bar';

/*-- Focus --*/

@import 'focus';

/*-- Region --*/

@import 'region';

/*-- Brush --*/

@import 'brush';

/*-- Select - Drag --*/

@import 'select_drag';

/*-- Legend --*/

@import 'legend';

/*-- Title --*/

@import 'title';

/*-- Tooltip --*/

@import 'tooltip';

/*-- Area --*/

@import 'area';

/*-- Arc --*/

@import 'arc';

+ 8
- 0
vowel/assets/scss/charts/c3/point.scss View File

@@ -0,0 +1,8 @@
.c3-circle._expanded_ {
stroke-width: 1px;
stroke: white;
}
.c3-selected-circle {
fill: white;
stroke-width: 2px;
}

+ 4
- 0
vowel/assets/scss/charts/c3/region.scss View File

@@ -0,0 +1,4 @@
.c3-region {
fill: steelblue;
fill-opacity: .1;
}

+ 2
- 0
vowel/assets/scss/charts/c3/select_drag.scss View File

@@ -0,0 +1,2 @@
.c3-dragarea {
}

+ 7
- 0
vowel/assets/scss/charts/c3/text.scss View File

@@ -0,0 +1,7 @@
.c3-text {
}

.c3-text.c3-empty {
fill: #808080;
font-size: 2em;
}

+ 3
- 0
vowel/assets/scss/charts/c3/title.scss View File

@@ -0,0 +1,3 @@
.c3-title {
font: 14px sans-serif;
}

+ 38
- 0
vowel/assets/scss/charts/c3/tooltip.scss View File

@@ -0,0 +1,38 @@
.c3-tooltip-container {
z-index: 10;
}
.c3-tooltip {
border-collapse:collapse;
border-spacing:0;
background-color:#fff;
empty-cells:show;
-webkit-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
-moz-box-shadow: 7px 7px 12px -9px rgb(119,119,119);
box-shadow: 7px 7px 12px -9px rgb(119,119,119);
opacity: 0.9;
}
.c3-tooltip tr {
border:1px solid #CCC;
}
.c3-tooltip th {
background-color: #aaa;
font-size:14px;
padding:2px 5px;
text-align:left;
color:#FFF;
}
.c3-tooltip td {
font-size:13px;
padding: 3px 6px;
background-color:#fff;
border-left:1px dotted #999;
}
.c3-tooltip td > span {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 6px;
}
.c3-tooltip td.value{
text-align: right;
}

+ 19
- 0
vowel/models/analytics.py View File

@@ -0,0 +1,19 @@
# coding=utf8
#
# analytics.py: vowel analytical models
# Copyright (C) 2018 Sam Black <samwwwblack@lapwing.org>
#
# 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 vowel.models import db

+ 20
- 0
vowel/templates/analytics/index.html View File

@@ -0,0 +1,20 @@
{% extends "layout/layout.html" %}

{% block head_title %}
Analytics
{% endblock %}

{% block header %}
<span class="uk-h3">Analytics</span>
{% endblock %}

{% block breadcrumbs %}
<li>
<span href="">
Analytics
</span>
</li>
{% endblock %}

{% block content %}
{% endblock %}

+ 23
- 0
vowel/templates/analytics/organisation.html View File

@@ -0,0 +1,23 @@
{% extends "layout/layout.html" %}

{% block head_title %}
Analytics for {{ organisation.name }}
{% endblock %}

{% block header %}
<span class="uk-h3">{{ organisation.name }}</span> Analytics
{% endblock %}

{% block breadcrumbs %}
<li>
<a href="{{ url_for('analytics.index') }}">Analytics</a>
</li>
<li>
<span href="">
{{ organisation.name }}
</span>
</li>
{% endblock %}

{% block content %}
{% endblock %}

+ 4
- 2
vowel/templates/layout/layout.html View File

@@ -7,7 +7,8 @@
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">

{% cache 86400, "head_css", branding_css or "default" %}
{% assets "uikit_css", "datetime_css", "datatables_css", "select2_css", "tinymce_skin_css", "annotator_css" %}
{% assets "uikit_css", "datetime_css", "datatables_css", "select2_css", "charts_css",
"tinymce_skin_css", "annotator_css" %}
<link href="{{ ASSET_URL }}" rel="stylesheet" type="text/css" />
{% endassets %}

@@ -76,7 +77,8 @@
</div>

{% cache 86400, "layout_js" %}
{% assets "page_js", "uikit_js", "datetime_js", "select2_js", "annotator_js", "dropzone_js", "vowel_js" %}
{% assets "page_js", "uikit_js", "datetime_js", "select2_js", "charts_js",
"annotator_js", "dropzone_js", "vowel_js" %}
<script src="{{ ASSET_URL }}" type="text/javascript"></script>
{% endassets %}
{% endcache %}


+ 7
- 1
vowel/templates/layout/menu.html View File

@@ -4,7 +4,7 @@
current_user.finished_courses or
not current_user.running_courses %}

<div class="uk-navbar-container" data-uk-sticky="media: 960" style="z-index: 1;">
<div class="uk-navbar-container" data-uk-sticky="media: 1280" style="z-index: 1;">
<div class="uk-container">
<nav data-uk-navbar="mode: click; boundary: .uk-container; offset: 1;">
<div class="uk-navbar-left uk-visible@m">
@@ -73,6 +73,12 @@
</ul>
</div>
</li>

{% if current_user.staff %}
<li>
<a href="{{ url_for('analytics.index') }}">Analytics</a>
</li>
{% endif %}
</ul>
</div>



+ 1
- 1
vowel/templates/layout/menu_anon.html View File

@@ -1,4 +1,4 @@
<div class="uk-navbar-container" data-uk-sticky="media: 960" style="z-index: 1;">
<div class="uk-navbar-container" data-uk-sticky="media: 1280" style="z-index: 1;">
<div class="uk-container">
<nav data-uk-navbar="mode: click; boundary: .uk-container">
<div class="uk-navbar-left uk-visible@m">


+ 5
- 0
vowel/utils/assets.py View File

@@ -110,6 +110,11 @@ datatables_css = Bundle("scss/datatables/jquery.dataTables.css",
filters="libsass,cssmin",
output="css/datatables.css")

charts_js = Bundle("js/charts/d3-3.5.17.js", "js/charts/c3-0.4.18.js",
filters="rjsmin", output="js/charts.js")
charts_css = Bundle("scss/charts/c3/main.scss", filters="libsass,cssmin",
output="css/charts.css")

select2_js = Bundle("js/select2/select2.full.js",
filters="rjsmin", output="js/select2.js")
select2_css = Bundle("scss/select2/core.scss",


+ 64
- 0
vowel/views/analytics.py View File

@@ -0,0 +1,64 @@
# coding=utf8
#
# analytics.py: Vowel analytics for course engagement
# and assessment performance.
# Copyright (C) 2018 Sam Black <samwwwblack@lapwing.org>
#
# 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 flask import Blueprint
from flask import redirect
from flask import render_template
from flask import url_for
from flask_security import current_user
from flask_security import login_required

from vowel.models.organisations import Organisation
from vowel.utils.auth import is_staff_member

analytics = Blueprint("analytics", __name__, url_prefix="/analytics")


@analytics.route("/")
@login_required
@is_staff_member(True)
def index():
"""
Analytics index page, listing all analytics
for the current user's organisations.

:return: overview of analytics for current user
:rtype: flask.Response
"""
if current_user.organisations.count() == 1:
return redirect(
url_for("analytics.organisation",
organisation_id=current_user.organisations[0].id))
return render_template("analytics/index.html")


@analytics.route("/organisation/<int:organisation_id>/")
@login_required
@is_staff_member()
def organisation(organisation_id):
"""
View analytics for organisation

:param organisation_id: organisation to view
:type organisation_id: int
:return: analytics for organisation
:rtype: flask.Response
"""
org = Organisation.query.get_or_404(organisation_id)
return render_template("analytics/organisation.html", organisation=org)

+ 2
- 0
vowel/web.py View File

@@ -51,6 +51,7 @@ from vowel.utils.organisation import organisation_from_request
from vowel.utils.queue import rq_manager
from vowel.utils.resources import delete_marked

from vowel.views.analytics import analytics
from vowel.views.annotations import annotations
from vowel.views.assessment import assessment
from vowel.views.course import courses
@@ -255,6 +256,7 @@ def register_blueprints(app):
app.register_blueprint(modules)
app.register_blueprint(lessons)
app.register_blueprint(assessment)
app.register_blueprint(analytics)
app.register_blueprint(resources)
app.register_blueprint(presentation)
app.register_blueprint(annotations)


Loading…
Cancel
Save