# HG changeset patch # User ymh # Date 1467369847 -7200 # Node ID f64fb2da5a5473e725178fe932ccbf65c4ee9470 # Parent 4a99d9a489872c14eeec47801c8696adebcfdfe3 add editin tracking diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/locale/fr/LC_MESSAGES/django.mo Binary file server/src/metaeducation/locale/fr/LC_MESSAGES/django.mo has changed diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/locale/fr/LC_MESSAGES/django.po --- 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 \n" "Language-Team: LANGUAGE \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" diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/settings/__init__.py --- 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 diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/settings/dev.py.tmpl --- 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}/" + diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/static/metaeducation/js/mtdc-save.js --- 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; } }; diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/static/metaeducation/js/mtdc-tracking-worker.js --- /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); diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/static/metaeducation/js/mtdc-tracking.js --- /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); + }); + + }); + +}; diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/static/metaeducation/lib/js.cookie.min.js --- /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={};a1){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 + @@ -16,8 +17,10 @@ + + @@ -72,10 +80,11 @@

{% trans "You don't have the permission to edit this Renkan graph." %}

{% trans "The Renkan graph you are trying to edit or view doesn't exist" %}

{% 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 : " %}

+

{% trans "There was no response from the server. If the problem persists after a page reload, please contact an administrator." %}

-{% endblock main_content %} \ No newline at end of file +{% endblock main_content %} diff -r 4a99d9a48987 -r f64fb2da5a54 server/src/metaeducation/templates/renkan_view.html --- 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 @@

{% trans "You don't have the permission to edit this Renkan graph." %}

{% trans "The Renkan graph you are trying to edit or view doesn't exist" %}

{% 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 : " %}

+

{% trans "There was no response from the server. If the problem persists after a page reload, please contact an administrator." %}