30 changed files with 19232 additions and 4 deletions
@ -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. |
@ -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. |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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; |
||||
} |
@ -0,0 +1,4 @@
|
||||
.c3-area { |
||||
stroke-width: 0; |
||||
opacity: 0.2; |
||||
} |
@ -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 { |
||||
} |
@ -0,0 +1,7 @@
|
||||
.c3-bar { |
||||
stroke-width: 0; |
||||
} |
||||
.c3-bar._expanded_ { |
||||
fill-opacity: 1; |
||||
fill-opacity: 0.75; |
||||
} |
@ -0,0 +1,3 @@
|
||||
.c3-brush .extent { |
||||
fill-opacity: .1; |
||||
} |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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 { |
||||
} |
@ -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 |
||||
} |
@ -0,0 +1,3 @@
|
||||
.c3-line { |
||||
stroke-width: 1px; |
||||
} |
@ -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'; |
@ -0,0 +1,8 @@
|
||||
.c3-circle._expanded_ { |
||||
stroke-width: 1px; |
||||
stroke: white; |
||||
} |
||||
.c3-selected-circle { |
||||
fill: white; |
||||
stroke-width: 2px; |
||||
} |
@ -0,0 +1,4 @@
|
||||
.c3-region { |
||||
fill: steelblue; |
||||
fill-opacity: .1; |
||||
} |
@ -0,0 +1,7 @@
|
||||
.c3-text { |
||||
} |
||||
|
||||
.c3-text.c3-empty { |
||||
fill: #808080; |
||||
font-size: 2em; |
||||
} |
@ -0,0 +1,3 @@
|
||||
.c3-title { |
||||
font: 14px sans-serif; |
||||
} |
@ -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; |
||||
} |
@ -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 |
@ -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 %} |
@ -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 %} |
@ -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) |
Loading…
Reference in new issue