mirror of
https://github.com/lucaspalomodevelop/indico-plugins.git
synced 2026-03-12 23:27:22 +00:00
Piwik: Remove unreliable/broken download tracking
This commit is contained in:
parent
a240e284fd
commit
65361fa851
@ -5,14 +5,12 @@
|
||||
// them and/or modify them under the terms of the MIT License;
|
||||
// see the LICENSE file for more details.
|
||||
|
||||
import 'jqtree';
|
||||
import 'jquery';
|
||||
import './main.css';
|
||||
import 'indico/jquery/compat/jqplot';
|
||||
|
||||
$(function() {
|
||||
const $t = $T.domain('piwik');
|
||||
const treeDOMTarget = '#materialTree';
|
||||
|
||||
/**
|
||||
* Clears the DOM element for the graph and then initiates a jqPlot render
|
||||
@ -75,26 +73,6 @@ $(function() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw a customized jqTree
|
||||
*/
|
||||
const draw_jqTree = function(treeData) {
|
||||
$(treeDOMTarget).tree({
|
||||
data: treeData,
|
||||
autoOpen: 0,
|
||||
saveState: true,
|
||||
onCanSelectNode(node) {
|
||||
// Leaf node (material) can be selected
|
||||
return node.children.length === 0;
|
||||
},
|
||||
onCreateLi(node, $li) {
|
||||
if (node.id !== undefined) {
|
||||
$li.find('.title').addClass('selectableNode');
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get base values for API requests
|
||||
*/
|
||||
@ -146,56 +124,6 @@ $(function() {
|
||||
return output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load material downloads data via AJAX and draw its graph
|
||||
*/
|
||||
const load_material_graph = function(uri, replot) {
|
||||
replot = typeof replot !== 'undefined' ? replot : false;
|
||||
const DOMTarget = 'materialDownloadChart';
|
||||
const graph_params = get_api_params();
|
||||
graph_params.download_url = uri;
|
||||
|
||||
$.ajax({
|
||||
url: build_url(PiwikPlugin.urls.data_downloads, graph_params),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success(data) {
|
||||
if (handleAjaxError(data)) {
|
||||
return;
|
||||
}
|
||||
const materialHits = [
|
||||
get_jqplot_array_values(data.metrics.downloads.individual, 'total'),
|
||||
get_jqplot_array_values(data.metrics.downloads.individual, 'unique'),
|
||||
];
|
||||
draw_jqplot_graph(materialHits, DOMTarget, replot);
|
||||
$('#materialTotalDownloads').html(data.metrics.downloads.cumulative.total);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the material files data and draw its jqTree
|
||||
*/
|
||||
const load_material_tree = function() {
|
||||
$(treeDOMTarget).html(progressIndicator(true, true).dom);
|
||||
|
||||
$.ajax({
|
||||
url: build_url(PiwikPlugin.urls.material, get_api_params()),
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success(data) {
|
||||
if (handleAjaxError(data)) {
|
||||
return;
|
||||
}
|
||||
if (data.material.tree !== null) {
|
||||
draw_jqTree(data.material.tree);
|
||||
} else {
|
||||
$(treeDOMTarget).html($t.gettext('No material found'));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads visits data and draw its graph
|
||||
*/
|
||||
@ -273,13 +201,6 @@ $(function() {
|
||||
window.location.href = url;
|
||||
});
|
||||
|
||||
// Event handler for clicking 'selectable' elements from the jqTree.
|
||||
$(treeDOMTarget).bind('tree.click', function(event) {
|
||||
$('#materialTitle').html(event.node.name);
|
||||
$('#materialDownloadChart').html(progressIndicator(true, true).dom);
|
||||
load_material_graph(event.node.id, true);
|
||||
});
|
||||
|
||||
// jQuery UI Dialog if no data is received via AJAX (timeout)
|
||||
$('#dialogNoGraphData').dialog({
|
||||
modal: true,
|
||||
@ -294,7 +215,6 @@ $(function() {
|
||||
|
||||
load_graphs();
|
||||
load_visits_graph();
|
||||
load_material_tree();
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
@ -116,54 +116,6 @@ div#statsGenerated {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
div#materialTree {
|
||||
display: block;
|
||||
width: 190px;
|
||||
height: 80%;
|
||||
overflow: auto;
|
||||
float: left;
|
||||
padding: 15px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div#materialContainer {
|
||||
display: block;
|
||||
width: 510px;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
/* jqTree Formatting */
|
||||
|
||||
div#materialTree ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
div#marginTree ul ul {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
span.selectableNode {
|
||||
color: #0b63a5 !important;
|
||||
font-size: 0.9em;
|
||||
display: block;
|
||||
width: auto;
|
||||
border-bottom: 1px solid #efefef;
|
||||
}
|
||||
|
||||
ul.tree .title {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
/* jqPlot Formatting */
|
||||
|
||||
div#materialDownloadChart {
|
||||
width: auto;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
div#visitorChart {
|
||||
margin-left: 15px;
|
||||
width: 95%;
|
||||
|
||||
@ -11,8 +11,7 @@ from werkzeug.exceptions import NotFound
|
||||
|
||||
from indico.modules.events.management.controllers import RHManageEventBase
|
||||
|
||||
from indico_piwik.reports import (ReportCountries, ReportDevices, ReportDownloads, ReportGeneral, ReportMaterial,
|
||||
ReportVisitsPerDay)
|
||||
from indico_piwik.reports import ReportCountries, ReportDevices, ReportGeneral, ReportVisitsPerDay
|
||||
from indico_piwik.views import WPStatistics
|
||||
|
||||
|
||||
@ -58,15 +57,6 @@ class RHApiEventBase(RHApiBase):
|
||||
self._report_params['contrib_id'] = request.args.get('contrib_id')
|
||||
|
||||
|
||||
class RHApiDownloads(RHApiEventBase):
|
||||
def _process_args(self):
|
||||
RHApiEventBase._process_args(self)
|
||||
self._report_params['download_url'] = request.args['download_url']
|
||||
|
||||
def _process(self):
|
||||
return jsonify(ReportDownloads.get(**self._report_params))
|
||||
|
||||
|
||||
class RHApiEventVisitsPerDay(RHApiEventBase):
|
||||
def _process(self):
|
||||
return jsonify(ReportVisitsPerDay.get(**self._report_params))
|
||||
@ -80,8 +70,3 @@ class RHApiEventGraphCountries(RHApiEventBase):
|
||||
class RHApiEventGraphDevices(RHApiEventBase):
|
||||
def _process(self):
|
||||
return jsonify(ReportDevices.get(**self._report_params))
|
||||
|
||||
|
||||
class RHApiMaterial(RHApiEventBase):
|
||||
def _process(self):
|
||||
return jsonify(ReportMaterial.get(**self._report_params))
|
||||
|
||||
@ -17,7 +17,6 @@ from indico_piwik import _
|
||||
class SettingsForm(IndicoForm):
|
||||
enabled = BooleanField(_("Track global visits"), widget=SwitchWidget())
|
||||
enabled_for_events = BooleanField(_("Track events"), widget=SwitchWidget())
|
||||
enabled_for_downloads = BooleanField(_("Track downloads"), widget=SwitchWidget())
|
||||
cache_enabled = BooleanField(_("Cache results"), widget=SwitchWidget())
|
||||
server_url = StringField(_("Piwik server URL"))
|
||||
server_api_url = StringField(_("Piwik API server URL"),
|
||||
|
||||
@ -12,15 +12,13 @@ from flask_pluginengine import render_plugin_template
|
||||
|
||||
from indico.core import signals
|
||||
from indico.core.plugins import IndicoPlugin, IndicoPluginBlueprint, plugin_url_rule_to_js, url_for_plugin
|
||||
from indico.modules.attachments.models.attachments import AttachmentType
|
||||
from indico.modules.events.contributions import Contribution
|
||||
from indico.web.menu import SideMenuItem
|
||||
|
||||
from indico_piwik import _
|
||||
from indico_piwik.controllers import (RHApiDownloads, RHApiEventGraphCountries, RHApiEventGraphDevices,
|
||||
RHApiEventVisitsPerDay, RHApiMaterial, RHStatistics)
|
||||
from indico_piwik.controllers import (RHApiEventGraphCountries, RHApiEventGraphDevices, RHApiEventVisitsPerDay,
|
||||
RHStatistics)
|
||||
from indico_piwik.forms import SettingsForm
|
||||
from indico_piwik.queries.tracking import track_download_request
|
||||
|
||||
|
||||
class PiwikPlugin(IndicoPlugin):
|
||||
@ -36,7 +34,6 @@ class PiwikPlugin(IndicoPlugin):
|
||||
default_settings = {
|
||||
'enabled': False,
|
||||
'enabled_for_events': True,
|
||||
'enabled_for_downloads': True,
|
||||
'cache_enabled': True,
|
||||
'server_url': '//127.0.0.1/piwik/',
|
||||
'server_api_url': '//127.0.0.1/piwik/',
|
||||
@ -50,7 +47,6 @@ class PiwikPlugin(IndicoPlugin):
|
||||
def init(self):
|
||||
super().init()
|
||||
self.connect(signals.menu.items, self.add_sidemenu_item, sender='event-management-sidemenu')
|
||||
self.connect(signals.attachments.attachment_accessed, self.track_download)
|
||||
self.template_hook('html-head', self.inject_tracking)
|
||||
|
||||
def inject_tracking(self, **kwargs):
|
||||
@ -73,23 +69,10 @@ class PiwikPlugin(IndicoPlugin):
|
||||
return blueprint
|
||||
|
||||
def get_vars_js(self):
|
||||
return {'urls': {'material': plugin_url_rule_to_js('piwik.material'),
|
||||
'data_downloads': plugin_url_rule_to_js('piwik.data_downloads'),
|
||||
'data_visits': plugin_url_rule_to_js('piwik.data_visits'),
|
||||
return {'urls': {'data_visits': plugin_url_rule_to_js('piwik.data_visits'),
|
||||
'graph_countries': plugin_url_rule_to_js('piwik.graph_countries'),
|
||||
'graph_devices': plugin_url_rule_to_js('piwik.graph_devices')}}
|
||||
|
||||
def track_download(self, attachment, from_preview, **kwargs):
|
||||
if from_preview or not self.settings.get('enabled_for_downloads'):
|
||||
return
|
||||
if attachment.type == AttachmentType.link:
|
||||
resource_url = attachment.link_url
|
||||
resource_title = f'Link - {attachment.title}'
|
||||
else:
|
||||
resource_url = request.base_url
|
||||
resource_title = f'Download - {attachment.title}'
|
||||
track_download_request.delay(resource_url, resource_title)
|
||||
|
||||
def _get_event_tracking_params(self):
|
||||
site_id_events = PiwikPlugin.settings.get('site_id_events')
|
||||
if not self.settings.get('enabled_for_events') or not site_id_events:
|
||||
@ -115,8 +98,6 @@ class PiwikPlugin(IndicoPlugin):
|
||||
|
||||
blueprint = IndicoPluginBlueprint('piwik', __name__, url_prefix='/event/<int:event_id>/manage/statistics')
|
||||
blueprint.add_url_rule('/', 'view', RHStatistics)
|
||||
blueprint.add_url_rule('/material', 'material', RHApiMaterial, methods=('GET', 'POST'))
|
||||
blueprint.add_url_rule('/data/downloads', 'data_downloads', RHApiDownloads, methods=('GET', 'POST'))
|
||||
blueprint.add_url_rule('/data/visits', 'data_visits', RHApiEventVisitsPerDay, methods=('GET', 'POST'))
|
||||
blueprint.add_url_rule('/graph/countries', 'graph_countries', RHApiEventGraphCountries, methods=('GET', 'POST'))
|
||||
blueprint.add_url_rule('/graph/devices', 'graph_devices', RHApiEventGraphDevices, methods=('GET', 'POST'))
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from operator import itemgetter
|
||||
from urllib.parse import quote
|
||||
|
||||
from indico_piwik.queries.base import PiwikQueryReportEventBase
|
||||
from indico_piwik.queries.utils import get_json_from_remote_server, reduce_json, stringify_seconds
|
||||
@ -30,43 +29,6 @@ class PiwikQueryReportEventMetricVisitsBase(PiwikQueryReportEventMetricBase):
|
||||
return result if result else {}
|
||||
|
||||
|
||||
class PiwikQueryReportEventMetricDownloads(PiwikQueryReportEventMetricBase):
|
||||
def call(self, download_url, **query_params):
|
||||
return super().call(method='Actions.getDownload', downloadUrl=quote(download_url), **query_params)
|
||||
|
||||
def get_result(self, download_url):
|
||||
result = get_json_from_remote_server(self.call, download_url=download_url, segmentation_enabled=False)
|
||||
return {'cumulative': self._get_cumulative_results(result),
|
||||
'individual': self._get_per_day_results(result)}
|
||||
|
||||
def _get_per_day_results(self, results):
|
||||
hits_calendar = {}
|
||||
|
||||
for date, hits in results.items():
|
||||
day_hits = {'total': 0, 'unique': 0}
|
||||
if hits:
|
||||
for metrics in hits:
|
||||
day_hits['total'] += metrics['nb_hits']
|
||||
day_hits['unique'] += metrics['nb_uniq_visitors']
|
||||
hits_calendar[date] = day_hits
|
||||
|
||||
return hits_calendar
|
||||
|
||||
def _get_cumulative_results(self, results):
|
||||
"""
|
||||
Returns a dictionary of {'total': x, 'unique': y} for the
|
||||
date range.
|
||||
"""
|
||||
hits = {'total': 0, 'unique': 0}
|
||||
|
||||
day_hits = list(hits[0] for hits in results.values() if hits)
|
||||
for metrics in day_hits:
|
||||
hits['total'] += metrics['nb_hits']
|
||||
hits['unique'] += metrics['nb_uniq_visitors']
|
||||
|
||||
return hits
|
||||
|
||||
|
||||
class PiwikQueryReportEventMetricReferrers(PiwikQueryReportEventMetricBase):
|
||||
def call(self, **query_params):
|
||||
return super().call(method='Referrers.getReferrerType', period='range', **query_params)
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
# This file is part of the Indico plugins.
|
||||
# Copyright (C) 2002 - 2021 CERN
|
||||
#
|
||||
# The Indico plugins are free software; you can redistribute
|
||||
# them and/or modify them under the terms of the MIT License;
|
||||
# see the LICENSE file for more details.
|
||||
|
||||
from datetime import datetime
|
||||
from urllib.parse import quote
|
||||
|
||||
from indico.core.celery import celery
|
||||
|
||||
from indico_piwik.piwik import PiwikRequest
|
||||
|
||||
|
||||
@celery.task
|
||||
def track_download_request(download_url, download_title):
|
||||
"""Track a download in Piwik"""
|
||||
from indico_piwik.plugin import PiwikPlugin
|
||||
|
||||
if not download_url:
|
||||
raise ValueError("download_url can't be empty")
|
||||
if not download_title:
|
||||
raise ValueError("download_title can't be empty")
|
||||
|
||||
request = PiwikRequest(server_url=PiwikPlugin.settings.get('server_api_url'),
|
||||
site_id=PiwikPlugin.settings.get('site_id_events'),
|
||||
api_token=PiwikPlugin.settings.get('server_token'),
|
||||
query_script=PiwikPlugin.track_script)
|
||||
|
||||
action_url = quote(download_url)
|
||||
dt = datetime.now()
|
||||
request.call(idsite=request.site_id,
|
||||
rec=1,
|
||||
action_name=quote(download_title),
|
||||
url=action_url,
|
||||
download=action_url,
|
||||
h=dt.hour, m=dt.minute, s=dt.second)
|
||||
@ -11,15 +11,13 @@ from datetime import timedelta
|
||||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from indico.core.cache import make_scoped_cache
|
||||
from indico.modules.attachments.util import get_nested_attached_items
|
||||
from indico.modules.events import Event
|
||||
from indico.modules.events.contributions import Contribution
|
||||
from indico.util.date_time import format_time, now_utc, utc_to_server
|
||||
from indico.util.serializer import Serializer
|
||||
|
||||
from indico_piwik.queries.graphs import PiwikQueryReportEventGraphCountries, PiwikQueryReportEventGraphDevices
|
||||
from indico_piwik.queries.metrics import (PiwikQueryReportEventMetricDownloads,
|
||||
PiwikQueryReportEventMetricPeakDateAndVisitors,
|
||||
from indico_piwik.queries.metrics import (PiwikQueryReportEventMetricPeakDateAndVisitors,
|
||||
PiwikQueryReportEventMetricReferrers, PiwikQueryReportEventMetricUniqueVisits,
|
||||
PiwikQueryReportEventMetricVisitDuration, PiwikQueryReportEventMetricVisits)
|
||||
|
||||
@ -92,13 +90,6 @@ class ReportDevices(ReportBase):
|
||||
self.graphs = {'devices': PiwikQueryReportEventGraphDevices(**self.params).get_result()}
|
||||
|
||||
|
||||
class ReportDownloads(ReportBase):
|
||||
__public__ = ['metrics']
|
||||
|
||||
def _build_report(self, download_url):
|
||||
self.metrics = {'downloads': PiwikQueryReportEventMetricDownloads(**self.params).get_result(download_url)}
|
||||
|
||||
|
||||
class ReportGeneral(ReportBase):
|
||||
__public__ = ['event_id', 'contrib_id', 'start_date', 'end_date', 'metrics', 'contributions', 'timestamp']
|
||||
|
||||
@ -132,34 +123,6 @@ class ReportGeneral(ReportBase):
|
||||
self.contributions[key] = '{} ({})'.format(contribution.title, format_time(contribution.start_dt))
|
||||
|
||||
|
||||
class ReportMaterial(ReportBase):
|
||||
__public__ = ['material']
|
||||
|
||||
def _build_report(self):
|
||||
event = Event.get_or_404(self.params['event_id'], is_deleted=False)
|
||||
new_material = get_nested_attached_items(event)
|
||||
self.material = {'tree': [self._format_data(new_material)]}
|
||||
|
||||
def _format_data(self, raw_node):
|
||||
if 'object' not in raw_node:
|
||||
return None
|
||||
node = {'label': raw_node['object'].title,
|
||||
'children': []}
|
||||
if 'files' in raw_node:
|
||||
node['children'] += self._format_data_files(raw_node['files'])
|
||||
if 'folders' in raw_node:
|
||||
for folder in raw_node['folders']:
|
||||
node['children'] += [{'label': folder.title, 'children': self._format_data_files(folder.attachments)}]
|
||||
if 'children' in raw_node:
|
||||
node['children'] += [self._format_data(child) for child in raw_node['children']]
|
||||
if not node['children']:
|
||||
return None
|
||||
return node
|
||||
|
||||
def _format_data_files(self, files):
|
||||
return [{'id': f.absolute_download_url, 'label': f.title} for f in files]
|
||||
|
||||
|
||||
class ReportVisitsPerDay(ReportBase):
|
||||
__public__ = ['metrics']
|
||||
|
||||
|
||||
@ -179,34 +179,6 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="statsRow">
|
||||
|
||||
<!-- File Downloads -->
|
||||
<div class="statsWidget full edge">
|
||||
<div class="statsWidgetTitle">
|
||||
{% trans %}Material Downloads{% endtrans %}
|
||||
</div>
|
||||
<div class="statsWidgetContent">
|
||||
<div id="materialTree"></div>
|
||||
<div id="materialContainer">
|
||||
<div id="materialHeader" class="statsTableDivider">
|
||||
{% trans %}Downloads for{% endtrans %}:
|
||||
<span id="materialTitle">
|
||||
—
|
||||
</span>
|
||||
({% trans %}Total{% endtrans %}: <span id="materialTotalDownloads">0</span>)
|
||||
</div>
|
||||
<div id="materialInfo">
|
||||
<div id="materialDownloadChart">
|
||||
{% trans %}No material selected{% endtrans %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="statsGenerated">
|
||||
{% trans dt=report.timestamp | format_datetime('long') -%}
|
||||
This report was generated at: {{ dt }}
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "indico-plugin-piwik",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "indico_piwik/client/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/indico/indico-plugins.git"
|
||||
},
|
||||
"author": "Indico Team <indico.team@cern.ch>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/indico/indico-plugins/issues"
|
||||
},
|
||||
"homepage": "https://github.com/indico/indico-plugins#readme",
|
||||
"dependencies": {
|
||||
"jqtree": "^1.4.4"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user