Binary file server/src/metaeducation/locale/fr/LC_MESSAGES/django.mo has changed
--- a/server/src/metaeducation/locale/fr/LC_MESSAGES/django.po Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/locale/fr/LC_MESSAGES/django.po Fri Jul 01 12:44:07 2016 +0200
@@ -8,7 +8,7 @@
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-05-19 11:35+0200\n"
+"POT-Creation-Date: 2016-05-24 16:17+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -38,41 +38,68 @@
msgid "last name"
msgstr "Nom"
-#: metaeducation/templates/renkan_edit.html:67
+#: metaeducation/templates/renkan_edit.html:70
+#: metaeducation/templates/renkan_view.html:66
msgid "The Renkan server has reported an error"
msgstr "Le serveur Renkan a rencontré une erreur."
-#: metaeducation/templates/renkan_edit.html:71
+#: metaeducation/templates/renkan_edit.html:73
+#: metaeducation/templates/renkan_view.html:69
msgid ""
"The Renkan graph you are trying to edit is currently being edited by another "
"user. We advise you to reload the page."
-msgstr "Le graphe Renkan que vous tentez d'éditer est actuellement en cours d'édition par un autre "
-"utilisateur. Nous vous conseillons de recharger la page."
+msgstr ""
+"Le graphe Renkan que vous tentez d'éditer est actuellement en cours "
+"d'édition par un autre utilisateur. Nous vous conseillons de recharger la "
+"page."
-#: metaeducation/templates/renkan_edit.html:73
+#: metaeducation/templates/renkan_edit.html:74
+#: metaeducation/templates/renkan_view.html:70
msgid ""
"There was an error with the graph data sent to the Renkan server. If the "
"problem persists after a page reload, please contact an administrator. Error "
"message was : "
-msgstr "Une erreur s'est produite lors de l'envoi des données d'éditions du graphe Renkan. Si le "
-"problème persiste après rechargement de la page, merci de contacter un administrateur. Message "
-"d'erreur: "
+msgstr ""
+"Une erreur s'est produite lors de l'envoi des données d'éditions du graphe "
+"Renkan. Si le problème persiste après rechargement de la page, merci de "
+"contacter un administrateur. Message d'erreur: "
#: metaeducation/templates/renkan_edit.html:75
+#: metaeducation/templates/renkan_view.html:71
msgid "You don't have the permission to edit this Renkan graph."
msgstr "Vous n'avez pas le droit d'éditer ce graphe Renkan."
-#: metaeducation/templates/renkan_edit.html:77
+#: metaeducation/templates/renkan_edit.html:76
+#: metaeducation/templates/renkan_view.html:72
msgid "The Renkan graph you are trying to edit or view doesn't exist"
-msgstr "Le graphe Renkan que vous cherchez à visualiser ou éditer n'existe pas."
+msgstr ""
+"Le graphe Renkan que vous cherchez à visualiser ou éditer n'existe pas."
-#: metaeducation/templates/renkan_edit.html:79
+#: metaeducation/templates/renkan_edit.html:77
+#: metaeducation/templates/renkan_view.html:73
msgid ""
"There was an error with the Renkan server. If the problem persists after a "
"page reload, please contact an administrator. The error message was : "
-msgstr "Une erreur s'est produite au niveau du serveur Renkan. Si le problème persiste après "
-"rechargement de la page, merci de contacter un administrateur. Message d'erreur: "
+msgstr ""
+"Une erreur s'est produite au niveau du serveur Renkan. Si le problème "
+"persiste après rechargement de la page, merci de contacter un "
+"administrateur. Message d'erreur: "
-#: metaeducation/templates/renkan_edit.html:83
+#: metaeducation/templates/renkan_edit.html:78
+#: metaeducation/templates/renkan_view.html:74
+#, fuzzy
+#| msgid ""
+#| "There was an error with the Renkan server. If the problem persists after "
+#| "a page reload, please contact an administrator. The error message was : "
+msgid ""
+"There was no response from the server. If the problem persists after a page "
+"reload, please contact an administrator."
+msgstr ""
+"Le serveur Renkan ne répond pas. Si le problème "
+"persiste après rechargement de la page, merci de contacter un "
+"administrateur."
+
+#: metaeducation/templates/renkan_edit.html:81
+#: metaeducation/templates/renkan_view.html:77
msgid "Reload the page"
msgstr "Recharger la page"
--- a/server/src/metaeducation/settings/__init__.py Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/settings/__init__.py Fri Jul 01 12:44:07 2016 +0200
@@ -163,3 +163,7 @@
MTDC_CLIENT_CREDENTIALS_TOKEN_URL = "" # "https://dev.enteduc.fr/oauth/oauth2/token"
MTDC_REFERENCE_RESOURCE_BASE_URL = MTDC_GED_BASE_URL + "" # "http://192.168.1.62:20411/ws/resource/" # MTDC_GED_BASE_URL + "/ws/resource/"
OAUTH_REDIRECT_URI = "" # Redirect URI for the GED server, when validating tokens
+
+LRS_TRACKING_SERVICE_URL = "" # URL of the LRS to which we send tracking data
+LRS_MTDC_RENKAN_USERNAME = "" # Username of Renkan app for LRS auth
+LRS_MTDC_RENKAN_PASSWORD = "" # Password of Renkan app for LRS auth
--- a/server/src/metaeducation/settings/dev.py.tmpl Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/settings/dev.py.tmpl Fri Jul 01 12:44:07 2016 +0200
@@ -125,3 +125,10 @@
MTDC_CLIENT_CREDENTIALS_TOKEN_URL = "" # This URL is the ABSOLUTE url for getting a token via Client Credentials from server to server.
MTDC_REFERENCE_RESOURCE_BASE_URL = "" # This URL is the ABSOLUTE url for the GED resource referencement service from server to server.
OAUTH_REDIRECT_URI = "" # Redirect URI for the GED server, used when validating GED tokens during client credentials flow.
+
+LRS_TRACKING_SERVICE_URL = "" # URL of the LRS to which we send tracking data
+LRS_MTDC_RENKAN_USERNAME = "" # Username of Renkan app for LRS auth
+LRS_MTDC_RENKAN_PASSWORD = "" # Password of Renkan app for LRS auth
+TRACKING_RNKNS_NAMESPACE = "" # Namespace for renkan nodes and edges URI, must be of the format "http://{something}/"
+TRACKING_VOCABULARY_NAMESPACE = "" # Namespace for tracking custom vocabulary, must be of the format "http://{something}/"
+
--- a/server/src/metaeducation/static/metaeducation/js/mtdc-save.js Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/static/metaeducation/js/mtdc-save.js Fri Jul 01 12:44:07 2016 +0200
@@ -12,6 +12,7 @@
});
Rkns.$.getJSON(_opts.url, function(_data) {
_renkan.dataloader.load(_data);
+ _renkan.setCurrentUser(_opts.user_id, _opts.user_name);
_proj.set({
loadingStatus : false
});
@@ -105,6 +106,9 @@
Rkns.$('#500Error').append(jqXHR.responseText);
document.getElementById('500Error').style.display = 'block';
break;
+ case 503:
+ document.getElementById('503Error').style.display = 'block';
+ break;
}
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/static/metaeducation/js/mtdc-tracking-worker.js Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,194 @@
+/* globals operative _ Cookies $ */
+/* eslint no-console: 0 */
+
+
+(function(root) {
+ 'use strict';
+
+ if (typeof root.Mtdc !== 'object') {
+ root.Mtdc = {};
+ }
+
+ var Mtdc = root.Mtdc;
+
+
+ Mtdc.TrackingWorker = function(currentUser, trackingUrl, registration, debounceDelay = 1000) {
+
+ function _sendTrackingInfo() {
+ var trackingMessages = this.trackingMessages;
+ this.trackingMessages = [];
+ if(trackingMessages.length === 0) {
+ return;
+ }
+ $.ajax({
+ method: 'POST',
+ url: this.trackingUrl,
+ headers: {
+ 'X-CSRFToken': this.csrftoken
+ },
+ data: JSON.stringify(trackingMessages),
+ contentType: 'application/json'
+ }).done(function(data) {
+ console.log('Send tracking info success', data);
+ }).fail(function(){
+ console.log('send tracking data failed', trackingMessages);
+ });
+ }
+
+ var trackingWorker = {
+ trackingMessages: [],
+ currentUser: currentUser,
+ trackingUrl: trackingUrl,
+ getUUID4 : function() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ var r = Math.random() * 16 | 0,
+ v = c === 'x' ? r : (r & 0x3 | 0x8);
+ return v.toString(16);
+ });
+ },
+ _init: function() {
+ this.sendTrackingInfo = _.debounce(_.bind(_sendTrackingInfo, this), debounceDelay);
+ this.csrftoken = Cookies.get('csrftoken');
+ this.registration = registration ? registration : this.getUUID4();
+ return this;
+ },
+ _pushTrackingMessage: function(msg) {
+ this.trackingMessages.push(msg);
+ this.sendTrackingInfo();
+ },
+ flushTrackingInfo() {
+ this.sendTrackingInfo.flush();
+ },
+ _getBaseMsg: function(verb) {
+ var timestamp = new Date(),
+ verbNode = {
+ add: {
+ id: 'http://activitystrea.ms/schema/1.0/create',
+ display: { 'fr-FR': 'a créé' }
+ },
+ update: {
+ id: 'http://activitystrea.ms/schema/1.0/update',
+ display: { 'fr-FR': 'a modifié' }
+ },
+ delete: {
+ id: 'http://activitystrea.ms/schema/1.0/delete',
+ display: { 'fr-FR': 'a supprimé' }
+ },
+ move: {
+ id: 'http://activitystrea.ms/schema/1.0/move',
+ display: { 'fr-FR': 'a déplacé'}
+ },
+ close: {
+ id: 'http://activitystrea.ms/schema/1.0/close',
+ display: { 'fr-FR': 'a fermé'}
+ }
+ }[verb];
+ return {
+ actor: {
+ objectType: 'Agent',
+ name: this.currentUser,
+ account: {
+ homePage: 'https://www.metaeducation.fr/Utilisateurs/',
+ name: this.currentUser
+ }
+ },
+ verb: verbNode,
+ object: {
+ objectType: 'Activity'
+ },
+ context: {
+ registration: this.registration,
+ extensions: {
+ 'http://liris.renkantracking.org/application': 'Outil carte mentale'
+ }
+ },
+ timestamp: timestamp.toISOString()
+ };
+ },
+ _getObjectUrn: function(objectType, objectId) {
+ return 'urn:mtdc:renkan:'+ objectType + ':' + objectId;
+ },
+ _sendNodeMsg: function(verb, nodeData, changedData, previousData) {
+ this._sendObjectMsg('node', 'http://www.w3.org/ns/activitystreams#Node', verb, nodeData, changedData, previousData);
+ },
+ _sendEdgeMsg: function(verb, nodeData, changedData, previousData) {
+ this._sendObjectMsg('edge', 'http://www.w3.org/ns/activitystreams#Edge', verb, nodeData, changedData, previousData);
+ },
+ _sendViewMsg: function(verb, viewData, changedData, previousData) {
+ this._sendObjectMsg('view', 'http://www.w3.org/ns/activitystreams#View', verb, viewData, changedData, previousData);
+ },
+ _sendObjectMsg: function(objectType, objectTypeUrl, verb, objData, changedData, previousData) {
+
+ var msg = this._getBaseMsg(verb);
+
+ msg.object = _.merge(msg.object, {
+ id: this._getObjectUrn(objectType, objData._id), //TODO full url ???
+ definition: {
+ name: {
+ 'fr-FR': objData.title
+ },
+ description: {
+ 'fr-FR': objData.description
+ },
+ type: objectTypeUrl,
+ extensions: {
+ 'http://www.w3.org/ns/activitystreams#Data': objData,
+ 'http://www.w3.org/ns/activitystreams#DataChanged': changedData, //this part are not sent if undefined
+ 'http://www.w3.org/ns/activitystreams#DataPrevious': previousData //this part are not sent if undefined
+ }
+ }
+ });
+ msg.context = _.merge(msg.context, {
+ extensions: {
+ 'http://liris.renkantracking.org/fromCreate': objData.origin
+ }
+ });
+
+ this._pushTrackingMessage(msg);
+
+ },
+ addNode: function(nodeData) {
+ this._sendNodeMsg('add', nodeData);
+ },
+ deleteNode: function(nodeData) {
+ this._sendNodeMsg('delete', nodeData);
+ },
+ updateNode: function(nodeData, changedData, previousData) {
+ if('position' in changedData) {
+ this._sendNodeMsg('move', nodeData, { position: changedData['position']}, { position: previousData['position']});
+ delete changedData['position'];
+ delete previousData['position'];
+ }
+ if(_.isEmpty(changedData)) {
+ return;
+ }
+ this._sendNodeMsg('update', nodeData, changedData, previousData);
+ },
+ addEdge: function(edgeData) {
+ this._sendEdgeMsg('add', edgeData);
+ },
+ deleteEdge: function(edgeData) {
+ this._sendEdgeMsg('delete', edgeData);
+ },
+ updateEdge: function(edgeData, changedData, previousData) {
+ this._sendEdgeMsg('update', edgeData, changedData, previousData);
+ },
+ addView: function(edgeData) {
+ this._sendViewMsg('add', edgeData);
+ },
+ deleteView: function(edgeData) {
+ this._sendViewMsg('delete', edgeData);
+ },
+ updateView: function(viewData, changedData, previousData) {
+ this._sendViewMsg('update', viewData, changedData, previousData);
+ },
+ closeProject: function(projData) {
+ }
+
+ };
+
+ return trackingWorker._init();
+ };
+
+
+})(window);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/static/metaeducation/js/mtdc-tracking.js Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,95 @@
+/* Tracking module that listens to Renkan events */
+/* globals Rkns */
+/* eslint no-console: 0 */
+
+Rkns.mtdcTracking = function(_renkan, _trackingWorker) {
+
+ var _proj = _renkan.project;
+
+ function prepareObjData(node) {
+ var objData = node.toJSON(),
+ p = node.get('project');
+ objData.project = { id: p.get('id'), title: p.get('title')};
+ objData.origin = node.get('origin', -1);
+ return objData;
+ }
+
+ function registerNode(_node) {
+ _node.on('remove', function(_n) {
+ var nodeData = prepareObjData(_n);
+ _trackingWorker.deleteNode(nodeData);
+ });
+ _node.on('change', function(_n) {
+ var nodeData = prepareObjData(_n);
+ var dataChanged = _n.changed;
+ var previousData = Rkns._.mapValues(_n.changed, function(v,k) { return _n.previous(k); });
+ _trackingWorker.updateNode(nodeData, dataChanged, previousData);
+ });
+ }
+
+ function registerEdge(_edge) {
+ _edge.on('remove', function(_e) {
+ var edgeData = prepareObjData(_e);
+ _trackingWorker.deleteEdge(edgeData);
+ });
+ _edge.on('change', function(_e) {
+ var edgeData = prepareObjData(_e);
+ var dataChanged = _e.changed;
+ var previousData = Rkns._.mapValues(_e.changed, function(v,k) { return _e.previous(k); });
+ _trackingWorker.updateEdge(edgeData, dataChanged, previousData);
+ });
+ }
+
+ function registerView(_view) {
+ _view.on('remove', function(_v) {
+ var viewData = prepareObjData(_v);
+ _trackingWorker.deleteView(viewData);
+ });
+ _view.on('change', function(_v) {
+ var viewData = prepareObjData(_v);
+ var dataChanged = _v.changed;
+ var previousData = Rkns._.mapValues(_v.changed, function(v,k) { return _v.previous(k); });
+ _trackingWorker.updateView(viewData, dataChanged, previousData);
+ });
+ }
+
+
+ _proj.on('change:loadingStatus', function(_p) {
+ if(_p.get('loadingStatus')) {
+ return;
+ }
+ // -> track open for editing
+
+ _p.on('add:nodes', function(_node) {
+ var nodeData = prepareObjData(_node);
+ registerNode(_node);
+ _trackingWorker.addNode(nodeData);
+ });
+
+ _p.on('add:edges', function(_edge) {
+ var edgeData = prepareObjData(_edge);
+ registerEdge(_edge);
+ _trackingWorker.addEdge(edgeData);
+ });
+
+ _p.on('add:views', function(_view) {
+ var viewData = prepareObjData(_view);
+ registerView(_view);
+ _trackingWorker.addView(viewData);
+ });
+
+ _proj.get('nodes').each(function(_node) {
+ registerNode(_node);
+ });
+
+ _proj.get('edges').each(function(_edge) {
+ registerEdge(_edge);
+ });
+
+ _proj.get('views').each(function(_view) {
+ registerView(_view);
+ });
+
+ });
+
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/static/metaeducation/lib/js.cookie.min.js Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,2 @@
+/*! js-cookie v2.1.2 | MIT */
+!function(a){if("function"==typeof define&&define.amd)define(a);else if("object"==typeof exports)module.exports=a();else{var b=window.Cookies,c=window.Cookies=a();c.noConflict=function(){return window.Cookies=b,c}}}(function(){function a(){for(var a=0,b={};a<arguments.length;a++){var c=arguments[a];for(var d in c)b[d]=c[d]}return b}function b(c){function d(b,e,f){var g;if("undefined"!=typeof document){if(arguments.length>1){if(f=a({path:"/"},d.defaults,f),"number"==typeof f.expires){var h=new Date;h.setMilliseconds(h.getMilliseconds()+864e5*f.expires),f.expires=h}try{g=JSON.stringify(e),/^[\{\[]/.test(g)&&(e=g)}catch(i){}return e=c.write?c.write(e,b):encodeURIComponent(String(e)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),b=encodeURIComponent(String(b)),b=b.replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent),b=b.replace(/[\(\)]/g,escape),document.cookie=[b,"=",e,f.expires&&"; expires="+f.expires.toUTCString(),f.path&&"; path="+f.path,f.domain&&"; domain="+f.domain,f.secure?"; secure":""].join("")}b||(g={});for(var j=document.cookie?document.cookie.split("; "):[],k=/(%[0-9A-Z]{2})+/g,l=0;l<j.length;l++){var m=j[l].split("="),n=m.slice(1).join("=");'"'===n.charAt(0)&&(n=n.slice(1,-1));try{var o=m[0].replace(k,decodeURIComponent);if(n=c.read?c.read(n,o):c(n,o)||n.replace(k,decodeURIComponent),this.json)try{n=JSON.parse(n)}catch(i){}if(b===o){g=n;break}b||(g[o]=n)}catch(i){}}return g}}return d.set=d,d.get=function(a){return d(a)},d.getJSON=function(){return d.apply({json:!0},[].slice.call(arguments))},d.defaults={},d.remove=function(b,c){d(b,"",a(c,{expires:-1}))},d.withConverter=b,d}return b(function(){})});
\ No newline at end of file
--- a/server/src/metaeducation/templates/renkan_edit.html Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/templates/renkan_edit.html Fri Jul 01 12:44:07 2016 +0200
@@ -4,6 +4,7 @@
{% block js_import %}
{{block.super}}
<script src="{% static 'renkanmanager/lib/jquery-mousewheel/jquery.mousewheel.js' %}"></script>
+ <script src="{% static 'metaeducation/lib/js.cookie.min.js' %}"></script>
<script src="{% static 'renkanmanager/lib/lodash/lodash.js' %}"></script>
<script src="{% static 'renkanmanager/lib/backbone/backbone.js' %}"></script>
<script src="{% static 'renkanmanager/lib/backbone-relational/backbone-relational.js' %}"></script>
@@ -16,8 +17,10 @@
<script src="{% static 'renkanmanager/lib/requirejs/require.js' %}"></script>
<script src="{% static 'renkanmanager/lib/renkan/js/renkan.js' %}"></script>
<script src="{% static 'metaeducation/js/mtdc-save.js' %}"></script>
+ <script src="{% static 'metaeducation/js/mtdc-tracking.js' %}"></script>
+ <script src="{% static 'metaeducation/js/mtdc-tracking-worker.js' %}"></script>
<script type="text/javascript">
-
+
function startRenkan(){
var _renkan = new Rkns.Renkan({
static_url : "{% static 'renkanmanager/lib/renkan/' %}",
@@ -26,8 +29,6 @@
url_parameters: false,
update_url: false,
user_authenticated: true,
- user_id: "{{ user.id }}",
- user_name: "{{ user.username }}",
url_parameters: false,
update_url: false,
user_color_editable: false,
@@ -47,8 +48,15 @@
home_button_url: false,
popup_editor: true,
});
+ _renkan.setCurrentUser('{{ user.external_id }}', '{{ user.username }}');
+
+ var trackingWorker = Mtdc.TrackingWorker(_renkan.current_user, "{% url 'tracking_view' %}");
+
+ Rkns.mtdcTracking(_renkan, trackingWorker);
Rkns.mtdcJsonIO(_renkan, {
- url: "{% url 'v1.0:renkan_detail' renkan_guid=renkan_guid %}?content_only=true"
+ url: "{% url 'v1.0:renkan_detail' renkan_guid=renkan_guid %}?content_only=true",
+ user_id: '{{ user.external_id }}',
+ user_name: '{{ user.username }}'
});
};
</script>
@@ -72,10 +80,11 @@
<p id="403Error" class="errorMsg">{% trans "You don't have the permission to edit this Renkan graph." %}</p>
<p id="404Error" class="errorMsg">{% trans "The Renkan graph you are trying to edit or view doesn't exist" %}</p>
<p id="500Error" class="errorMsg">{% trans "There was an error with the Renkan server. If the problem persists after a page reload, please contact an administrator. The error message was : " %}</p>
+ <p id="503Error" class="errorMsg">{% trans "There was no response from the server. If the problem persists after a page reload, please contact an administrator." %}</p>
</div>
<div class="errorModal-footer">
<h4 id="renkanErrorReload">{% trans "Reload the page" %}</h4>
</div>
</div>
</div>
-{% endblock main_content %}
\ No newline at end of file
+{% endblock main_content %}
--- a/server/src/metaeducation/templates/renkan_view.html Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/templates/renkan_view.html Fri Jul 01 12:44:07 2016 +0200
@@ -71,6 +71,7 @@
<p id="403Error" class="errorMsg">{% trans "You don't have the permission to edit this Renkan graph." %}</p>
<p id="404Error" class="errorMsg">{% trans "The Renkan graph you are trying to edit or view doesn't exist" %}</p>
<p id="500Error" class="errorMsg">{% trans "There was an error with the Renkan server. If the problem persists after a page reload, please contact an administrator. The error message was : " %}</p>
+ <p id="503Error" class="errorMsg">{% trans "There was no response from the server. If the problem persists after a page reload, please contact an administrator." %}</p>
</div>
<div class="errorModal-footer">
<h4 id="renkanErrorReload">{% trans "Reload the page" %}</h4>
--- a/server/src/metaeducation/urls.py Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/urls.py Fri Jul 01 12:44:07 2016 +0200
@@ -20,7 +20,7 @@
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
-from .views import ListRenkansView, NewRenkanView, EditRenkanView, ViewRenkanView, DeleteRenkanView
+from .views import ListRenkansView, NewRenkanView, EditRenkanView, ViewRenkanView, DeleteRenkanView, UITrackingView
urlpatterns = [
@@ -32,6 +32,7 @@
url(r'^front/new/$', NewRenkanView.as_view(), name='front_new_renkan'),
url(r'^front/edit/(?P<renkan_guid>[\w-]+)/$', EditRenkanView.as_view(), name='front_edit_renkan'),
url(r'^front/view/(?P<renkan_guid>[\w-]+)/$', ViewRenkanView.as_view(), name='front_view_renkan'),
+ url(r'^tracking/$', UITrackingView.as_view(), name='tracking_view'),
url(r'^front/delete/(?P<renkan_guid>[\w-]+)/$', staff_member_required(DeleteRenkanView.as_view()), name='front_delete_renkan')
]
--- a/server/src/metaeducation/views.py Mon Jun 27 16:12:38 2016 +0200
+++ b/server/src/metaeducation/views.py Fri Jul 01 12:44:07 2016 +0200
@@ -1,3 +1,4 @@
+import logging, json
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect
@@ -7,8 +8,10 @@
from renkanmanager.api.views import RenkanDetail
from renkanmanager.models import Renkan
from renkanmanager.serializers import RenkanSerializer
-from rest_framework.renderers import TemplateHTMLRenderer
from metaeducation import __version__
+from metaeducation.utils import send_tracking_data
+
+logger = logging.getLogger(__name__)
class ListRenkansView(View):
template_name = "renkan_list.html"
@@ -47,8 +50,20 @@
template_name = "renkan_edit.html"
class DeleteRenkanView(View):
+
def get(self, request, renkan_guid):
request.method = "DELETE"
delete_response = RenkanDetail.as_view()(request, renkan_guid)
- return HttpResponseRedirect(request.META.get('HTTP_REFERER', settings.BASE_URL))
-
\ No newline at end of file
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER', settings.BASE_URL))
+
+class UITrackingView(View):
+ def post(self, request):
+ try:
+ logger.debug("POSTING DATA %r", str(request.body, 'utf-8'))
+ # Testing if JSON is properly formatted
+ json.loads(str(request.body, 'utf-8'))
+ send_tracking_data(str(request.body, 'utf-8'))
+ return HttpResponse("Tracking data was sent")
+ except ValueError:
+ logger.debug("ERROR POSTING DATA")
+ return HttpResponse("Error sending data")
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/views/__init__.py Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,5 @@
+
+from .renkan import ListRenkansView, NewRenkanView, EditRenkanView, ViewRenkanView, DeleteRenkanView
+from .tracking import UITrackingView
+
+__all__ = [ "ListRenkansView", "NewRenkanView", "EditRenkanView", "ViewRenkanView", "DeleteRenkanView", "UITrackingView" ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/views/renkan.py Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,55 @@
+import logging, json
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render
+from django.views.generic import TemplateView, View
+from renkanmanager.api.views import RenkanDetail
+from renkanmanager.models import Renkan
+from renkanmanager.serializers import RenkanSerializer
+from metaeducation import __version__
+
+logger = logging.getLogger(__name__)
+
+class ListRenkansView(View):
+ template_name = "renkan_list.html"
+
+ def get(self, request):
+ renkans = Renkan.objects.filter(creator=request.user)
+ return render(request, self.template_name, {'renkans': renkans, 'version': __version__})
+
+ def post(self, request):
+ create_data = {
+ "title" : request.POST.get("title", "Untitled Renkan")
+ }
+
+ serializer = RenkanSerializer(data=create_data)
+ if serializer.is_valid():
+ serializer.save(creator=request.user)
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER', settings.BASE_URL))
+
+class NewRenkanView(View):
+
+ def get(self, request):
+ create_data = {
+ "title" : "Untitled Renkan"
+ }
+ serializer = RenkanSerializer(data=create_data)
+ if serializer.is_valid():
+ new_renkan = serializer.save(creator=request.user)
+ return HttpResponseRedirect(reverse("front_edit_renkan", kwargs={"renkan_guid": new_renkan.renkan_guid}))
+
+
+class ViewRenkanView(TemplateView):
+ template_name = "renkan_view.html"
+
+
+class EditRenkanView(TemplateView):
+ template_name = "renkan_edit.html"
+
+class DeleteRenkanView(View):
+
+ def get(self, request, renkan_guid):
+ request.method = "DELETE"
+ delete_response = RenkanDetail.as_view()(request, renkan_guid)
+ return HttpResponseRedirect(request.META.get('HTTP_REFERER', settings.BASE_URL))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/metaeducation/views/tracking.py Fri Jul 01 12:44:07 2016 +0200
@@ -0,0 +1,42 @@
+import logging, json
+import requests
+from django.conf import settings
+from django.http import HttpResponse, HttpResponseServerError
+from django.views.generic import View
+
+logger = logging.getLogger(__name__)
+
+class UITrackingView(View):
+
+ def send_tracking_data(self, json_data):
+ tracking_data = json.loads(json_data)
+ logger.debug("SENDING %r", tracking_data)
+ resp = requests.post(
+ settings.LRS_TRACKING_SERVICE_URL + "statements",
+ json=tracking_data,
+ auth=requests.auth.HTTPBasicAuth(
+ settings.LRS_MTDC_RENKAN_USERNAME,
+ settings.LRS_MTDC_RENKAN_PASSWORD
+ ),
+ headers = {"X-Experience-API-Version": "1.0.1"}
+ )
+ logger.debug("%r: %r", resp.status_code, resp.text)
+ return resp
+
+ def post(self, request):
+ logger.debug("POSTING DATA %r", str(request.body, 'utf-8'))
+
+ try:
+ resp = self.send_tracking_data(str(request.body, 'utf-8'))
+ resp.raise_for_status()
+ except requests.exceptions.ConnectionError as e:
+ logger.debug("ERROR Connecting %r", e)
+ return HttpResponseServerError(str(e))
+ except requests.exceptions.HTTPError as e:
+ logger.debug("ERROR POSTING DATA %r", e)
+ return HttpResponse(resp.text, status=resp.status_code, content_type='text/plain')
+ else:
+ httpresp = HttpResponse(resp.text, status=resp.status_code, content_type=resp.headers.get('content-type'))
+ for h in {'X-Experience-API-Consistent-Through', 'X-Experience-API-Version', 'Date'}.intersection(resp.headers.keys()):
+ httpresp[h] = resp.headers[h]
+ return httpresp