diff --git a/app/views/branded/layouts/application.html.erb b/app/views/branded/layouts/application.html.erb index 6145d56..103b42b 100644 --- a/app/views/branded/layouts/application.html.erb +++ b/app/views/branded/layouts/application.html.erb @@ -35,6 +35,14 @@ <%= stylesheet_link_tag fingerprinted_asset('application') %> <%= javascript_include_tag fingerprinted_asset('vendor') %> <%= javascript_include_tag fingerprinted_asset('application') %> + <%= javascript_tag do %> + var options = { + message: '<%= d_("dmpopidor", "By continuing to browse, you accept the use of cookies to measure the traffic of the website with the software Matomo. Those data are not personal, as they are anonymized. We followed directions from the CNIL and configured this tool so that its use does not require your consent.")%>', + moreinfo: '<%= terms_path( :anchor => 'cookies') %>', + linkmsg: '<%= d_("dmpopidor", "Learn more") %>' + }; + var cb = new Cookiebanner(options); cb.run(); + <% end %> <%= csrf_meta_tags %> diff --git a/config/locale/dmpopidor.pot b/config/locale/dmpopidor.pot index a6c15b1..280ffba 100644 --- a/config/locale/dmpopidor.pot +++ b/config/locale/dmpopidor.pot @@ -147,7 +147,7 @@ msgid "Default template" msgstr "" -msgid "Check \"No organisation\" and check "No funder"" +msgid "Check \"No organisation\" and check \"No funder\"" msgstr "" msgid "Find the list of the available templates" @@ -156,3 +156,9 @@ msgid "Plan for testing, practice, or educational purposes" msgstr "" +msgid "By continuing to browse, you accept the use of cookies to measure the traffic of the website with the software Matomo. Those data are not personal, as they are anonymized. We followed directions from the CNIL and configured this tool so that its use does not require your consent." +msgstr "" + +msgid "Learn more" +msgstr "" + diff --git a/config/locale/en_GB/dmpopidor.po b/config/locale/en_GB/dmpopidor.po index b868f12..1a507fc 100644 --- a/config/locale/en_GB/dmpopidor.po +++ b/config/locale/en_GB/dmpopidor.po @@ -145,11 +145,17 @@ msgid "Default template" msgstr "Default template" -msgid "Check \"No organisation\" and check "No funder"" -msgstr "Check \"No organisation\" and check "No funder"" +msgid "Check \"No organisation\" and check \"No funder\"" +msgstr "Check \"No organisation\" and check \"No funder\"" msgid "Find the list of the available templates" msgstr "Find the list of the available templates" msgid "Plan for testing, practice, or educational purposes" -msgstr "Plan for testing, practice, or educational purposes" \ No newline at end of file +msgstr "Plan for testing, practice, or educational purposes" + +msgid "By continuing to browse, you accept the use of cookies to measure the traffic of the website with the software Matomo. Those data are not personal, as they are anonymized. We followed directions from the CNIL and configured this tool so that its use does not require your consent." +msgstr "By continuing to browse, you accept the use of cookies to measure the traffic of the website with the software Matomo. Those data are not personal, as they are anonymized. We followed directions from the CNIL and configured this tool so that its use does not require your consent." + +msgid "Learn more" +msgstr "Learn more" \ No newline at end of file diff --git a/config/locale/fr_FR/dmpopidor.po b/config/locale/fr_FR/dmpopidor.po index 5d945bb..f54cf3e 100644 --- a/config/locale/fr_FR/dmpopidor.po +++ b/config/locale/fr_FR/dmpopidor.po @@ -144,7 +144,7 @@ msgid "Default template" msgstr "Modèle par défaut" -msgid "Check \"No organisation\" and check "No funder"" +msgid "Check \"No organisation\" and check \"No funder\"" msgstr "Cocher \"Pas d’organisme\" et cocher \"Pas de financeur\"" msgid "Find the list of the available templates" @@ -153,4 +153,10 @@ msgid "Plan for testing, practice, or educational purposes" msgstr "Plan de test, d'entrainement ou créé en vue d'une formation" +msgid "By continuing to browse, you accept the use of cookies to measure the traffic of the website with the software Matomo. Those data are not personal, as they are anonymized. We followed directions from the CNIL and configured this tool so that its use does not require your consent." +msgstr "En poursuivant votre navigation, vous acceptez le dépôt de cookies destinés à mesurer la fréquentation du site grâce au logiciel Matomo. Ces données ne sont pas personnelles, car anonymisées. Nous avons suivi les indications de la CNIL et paramétré cet outil afin que son utilisation ne requière pas votre consentement." + +msgid "Learn more" +msgstr "En savoir plus" + diff --git a/config/locales/static_pages/en_GB.yml b/config/locales/static_pages/en_GB.yml index 8283d63..9666de8 100644 --- a/config/locales/static_pages/en_GB.yml +++ b/config/locales/static_pages/en_GB.yml @@ -15,7 +15,7 @@ body_text_html: "
A Data Management Plan (DMP) is a document that specifies which data will be collected or generated, how they will be managed, shared and preserved during and after the project. Preparing a plan is a good practice of any research project generating data. Moreover, funding bodies and institutions increasingly require their researchers to produce DMPs.
DMP OPIDoR is a tool to help you write a DMP.
DMP OPIDoR is based on the open source DMPRoadmap codebase, which is jointly developped by the Digital Curation Centre (DCC) and the University of California Curation Center (UC3). DMP OPIDoR source code is available on GitHub. DMP OPIDoR has been customised for French researchers.
DMP OPIDoR includes a number of templates that represent the requirements of different funders and institutions.Users are asked three questions at the outset so we can determine the appropriate template to display. Guidance is provided to help you interpret and answer the questions. This guidance is provided by researcher funders, universities and disciplines.
-The thematic DCC guidance is listed in 'Data Management Planning themes' by DCC.
+The thematic DCC guidance is listed in 'Data Management Planning themes' by DCC.
If you do not have a DMP OPIDoR account, click on 'Create an account' on the homepage.
If you have an account, please log in :
@@ -42,15 +42,15 @@ Reymonet N., Moysan M., Cartier A., Délémontez R. Université Paris Diderot et Université Paris Descartes. 2018.The creation of hyperlinks by third parties to pages or documents in the CNRS website is permitted provided that the links are not contrary to the interests of the CNRS, and that they ensure the possibility for the user to identify the origin and author.
Your password is stored in an encrypted form and cannot be retrieved. If forgotten, it has to be reset
-To adapt our site to the users' needs, we measure the number of visits, page views, visitors' activity and return frequency.
-Piwik, the statistics tool used by CNRS generates a cookie with a unique ID, whose storage is limited to 13 months.
+Matomo, the statistics tool used by CNRS generates a cookie with a unique ID, whose storage is limited to 13 months.
We also collect your IP address to identify your geographical location, which is then immediately anonymized and cannot be used by CNRS to trace a physical person.
The information collected is not disclosed to third parties nor used for other purposes.
Your browser can be configured to notify you the cookies stored on your computer and to ask you to accept them or not. You can accept or reject cookies on a case-by-case basis or choose to systematically reject them. Remember that changing settings may modify your access conditions to our services which require the use of cookies.
diff --git a/config/locales/static_pages/fr_FR.yml b/config/locales/static_pages/fr_FR.yml index b15c6c7..4f67c87 100644 --- a/config/locales/static_pages/fr_FR.yml +++ b/config/locales/static_pages/fr_FR.yml @@ -15,7 +15,7 @@ body_text_html: "Un plan de gestion de données (DMP) est un document qui spécifie quelles données sont collectées ou générées, comment celles-ci sont gérées, partagées et préservées pendant et après le projet. L'élaboration d'un plan de gestion est une bonne pratique pour tout projet de recherche générant des données. Par ailleurs, les organismes de financement et les institutions exigent de plus en plus de leurs chercheurs la production de DMPs.
DMP OPIDoR est un outil d'aide à la rédaction de DMP.
DMP OPIDoR est basé sur le code open source DMPRoadmap qui a été developpé par le Digital Curation Centre (DCC) et l'University of California Curation Center (UC3). Le code source de DMP OPIDoR est disponible sur GitHub. DMP OPIDoR a été personnalisé pour les chercheurs français.
DMP OPIDoR propose un certain nombre de modèles répondant aux exigences d'organismes de financement et d'institutions. Au départ, les utilisateurs doivent répondre à trois questions pour que nous puissions déterminer le modèle qu'il convient d'afficher. Des recommandations vous sont fournies pour vous permettre d'interpréter et de répondre aux questions. Ces recommandations sont proposées par les agences de financement, les institutions et les disciplines.
-Les recommandations du Digital Curation Centre (DCC) sont issues du document suivant : 'Data Management Planning themes' du DCC.
+Les recommandations du Digital Curation Centre (DCC) sont issues du document suivant : 'Data Management Planning themes' du DCC.
En l'absence de compte DMP OPIDoR, cliquez sur 'Créer un compte' en page d'accueil.
Si vous avez un compte, connectez vous :
@@ -43,15 +43,15 @@ Reymonet N., Moysan M., Cartier A., Délémontez R. Université Paris Diderot et Université Paris Descartes. 2018. Ce document a pour vocation d’accompagner les chercheurs et chargés de projets dans la rédact.. 2018.La mise en place de liens hypertextes par des tiers vers des pages ou des documents diffusés sur le site du CNRS, est autorisée sous réserve que les liens ne contreviennent pas aux intérêts du CNRS, et, qu'ils garantissent la possibilité pour l'utilisateur d'identifier l'origine et l'auteur du document.
Votre mot de passe est mémorisé sous forme cryptée et ne peut pas être récupéré. Si vous avez oublié votre mot de passe, vous devez le réinitialiser.
-En vue d’adapter le site aux demandes de ses visiteurs, nous mesurons le nombre de visites, le nombre de pages vues ainsi que l’activité des visiteurs sur le site et leur fréquence de retour.
-Piwik, l’outil de statistiques utilisé par le CNRS, génère un cookie avec un identifiant unique, dont la durée de conservation est limitée à 13 mois.
+Matomo, l’outil de statistiques utilisé par le CNRS, génère un cookie avec un identifiant unique, dont la durée de conservation est limitée à 13 mois.
Nous collectons également votre adresse IP, afin de déterminer la ville depuis laquelle vous vous connectez. Celle-ci est immédiatement anonymisée. Le CNRS ne peut donc en aucun cas remonter par ce biais à une personne physique.
Les données ne sont pas cédées à des tiers ni utilisées à d’autres fins.
Vous pouvez paramétrer votre navigateur afin qu’il vous signale la présence de cookies et vous propose de les accepter ou non. Vous pouvez accepter ou refuser les cookies au cas par cas ou bien les refuser une fois pour toutes. Il est rappelé que ce paramétrage est susceptible de modifier vos conditions d’accès aux services du site nécessitant l’utilisation de cookies.
diff --git a/lib/assets/javascripts/application.js b/lib/assets/javascripts/application.js index 196a5ee..bae67df 100644 --- a/lib/assets/javascripts/application.js +++ b/lib/assets/javascripts/application.js @@ -6,6 +6,7 @@ import './utils/tabHelper'; import './utils/tooltipHelper'; import './utils/popoverHelper'; +import './utils/cookiebanner'; // Page specific JS import './views/answers/edit'; diff --git a/lib/assets/javascripts/utils/cookiebanner.js b/lib/assets/javascripts/utils/cookiebanner.js new file mode 100644 index 0000000..80fb1a7 --- /dev/null +++ b/lib/assets/javascripts/utils/cookiebanner.js @@ -0,0 +1,587 @@ +/*global window:false, setTimeout:true, console:true */ +/* +Copyright (C) 2013-2015 Good Code and Cookie Banner contributors + +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. +*/ + +(function(context) { + 'use strict'; + + var win = context, doc = win.document; + + var global_instance_name = 'cbinstance'; + + /*eslint-disable */ + /*! + * contentloaded.js + * + * Author: Diego Perini (diego.perini at gmail.com) + * Summary: cross-browser wrapper for DOMContentLoaded + * Updated: 20101020 + * License: MIT + * Version: 1.2 + * + * URL: + * http://javascript.nwbox.com/ContentLoaded/ + * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE + * + */ + // @win window reference + // @fn function reference + function contentLoaded(win, fn) { + var done = false, top = true, + doc = win.document, root = doc.documentElement, + + add = doc.addEventListener ? 'addEventListener' : 'attachEvent', + rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent', + pre = doc.addEventListener ? '' : 'on', + + init = function(e) { + if (e.type == 'readystatechange' && doc.readyState != 'complete') return; + (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false); + if (!done && (done = true)) fn.call(win, e.type || e); + }, + + poll = function() { + try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; } + init('poll'); + }; + + if (doc.readyState == 'complete') fn.call(win, 'lazy'); + else { + if (doc.createEventObject && root.doScroll) { + try { top = !win.frameElement; } catch(e) { } + if (top) poll(); + } + doc[add](pre + 'DOMContentLoaded', init, false); + doc[add](pre + 'readystatechange', init, false); + win[add](pre + 'load', init, false); + } + } + /*eslint-enable */ + + var Cookies = { + get: function (key) { + return decodeURIComponent(doc.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(key).replace(/[-.+*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; + }, + set: function (key, val, end, path, domain, secure) { + if (!key || /^(?:expires|max-age|path|domain|secure)$/i.test(key)) { + return false; + } + var expires = ''; + if (end) { + switch (end.constructor) { + case Number: + expires = end === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + end; + break; + case String: + expires = '; expires=' + end; + break; + case Date: + expires = '; expires=' + end.toUTCString(); + break; + } + } + doc.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(val) + expires + (domain ? '; domain=' + domain : '') + (path ? '; path=' + path : '') + (secure ? '; secure' : ''); + return true; + }, + has: function (key) { + return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(key).replace(/[-.+*]/g, '\\$&') + '\\s*\\=')).test(doc.cookie); + }, + remove: function (key, path, domain) { + if (!key || !this.has(key)) { return false; } + doc.cookie = encodeURIComponent(key) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + ( domain ? '; domain=' + domain : '') + ( path ? '; path=' + path : ''); + return true; + } + }; + + var Utils = { + + // merge objects and whatnot + merge: function() { + var obj = {}, + i = 0, + al = arguments.length, + key; + if (0 === al) { + return obj; + } + for (; i < al; i++) { + for (key in arguments[i]) { + if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { + obj[key] = arguments[i][key]; + } + } + } + return obj; + }, + + str2bool: function(str) { + str = String(str); + switch (str.toLowerCase()) { + case 'false': + case 'no': + case '0': + case '': + return false; + default: + return true; + } + }, + + fade_in: function(el) { + if (el.style.opacity < 1) { + el.style.opacity = (parseFloat(el.style.opacity) + 0.05).toFixed(2); + win.setTimeout(function(){ + Utils.fade_in(el); + }, 50); + } + }, + + fade_out: function(el, duration_ms) { + if (typeof(el) !== "undefined") { + el.style.opacity = 1; + var seconds = duration_ms / 1000; + el.style.transition = "opacity " + seconds + "s ease"; + el.style.opacity = 0; + setTimeout(function() { el.parentNode.removeChild(el); }, duration_ms); + } + }, + + get_data_attribs: function(script) { + var data = {}; + if (Object.prototype.hasOwnProperty.call(script, 'dataset')) { + data = script.dataset; + } else { + var attribs = script.attributes; + var key; + for (key in attribs) { + if (Object.prototype.hasOwnProperty.call(attribs, key)) { + var attr = attribs[key]; + if (/^data-/.test(attr.name)) { + var camelized = Utils.camelize(attr.name.substr(5)); + // True when option name starts with "on" + var isFunction = (camelized.lastIndexOf('on', 0) === 0); + + data[camelized] = isFunction ? eval(attr.value) : attr.value; // jshint ignore:line + } + } + } + } + return data; + }, + + /** + * "Standardizes" the options keys by converting and removing + * any potential "dashed-property-name" into "dashedPropertyName". + * In case both are present, the dashedPropertyName wins. + */ + normalize_keys: function(options_object) { + var camelized = {}; + for (var key in options_object) { + if (Object.prototype.hasOwnProperty.call(options_object, key)) { + var camelized_key = Utils.camelize(key); + // TODO: could this break for "falsy" values within options_object? + // avoiding "dashed-property-name" overriding a potentially existing "dashedPropertyName" + camelized[camelized_key] = options_object[camelized_key] ? options_object[camelized_key] : options_object[key]; + } + } + return camelized; + }, + + camelize: function(str) { + var separator = '-', + match = str.indexOf(separator); + while (match !== -1) { + var last = (match === (str.length - 1)), + next = last ? '' : str[match + 1], + upnext = next.toUpperCase(), + sep_substr = last ? separator : separator + next; + str = str.replace(sep_substr, upnext); + match = str.indexOf(separator); + } + return str; + }, + + find_script_by_id: function(id) { + var scripts = doc.getElementsByTagName('script'); + for (var i = 0, l = scripts.length; i < l; i++) { + if (id === scripts[i].id) { + return scripts[i]; + } + } + return null; + }, + + is_numeric: function(val) { + // eslint-disable-next-line eqeqeq + return (parseFloat(val) == val); // want type coercion here! + }, + + }; + + var script_el_invoker = Utils.find_script_by_id('cookiebanner'); + + var Cookiebanner = context.Cookiebanner = function(opts) { + this.init(opts); + }; + + Cookiebanner.prototype = { + + // for testing stuff from the outside mostly + cookiejar: Cookies, + + init: function(opts) { + + this.inserted = false; + this.closed = false; + + var default_text = 'We use cookies to enhance your experience. ' + + 'By continuing to visit this site you agree to our use of cookies.'; + var default_link = 'Learn more'; + + this.default_options = { + // autorun: true, + cookie: 'cookiebanner-accepted', + closeText: '✖', + closeStyle: 'float:right;padding-left:5px;', + closePrecedes: true, + cookiePath: '/', + cookieDomain: null, + cookieSecure: false, + debug: false, + expires: Infinity, + zindex: 255, + mask: false, + maskOpacity: 0.5, + maskBackground: '#000', + height: 'auto', + minHeight: '21px', + bg: '#000', + fg: '#ddd', + link: '#aaa', + position: 'bottom', + padding: '5px 16px', + message: default_text, + linkmsg: default_link, + moreinfo: 'http://aboutcookies.org', + moreinfoTarget: '_blank', + moreinfoRel: 'noopener noreferrer', + moreinfoDecoration: 'none', + moreinfoFontWeight: 'normal', + moreinfoFontSize: null, + effect: null, + fontSize: '14px', + fontFamily: 'arial, sans-serif', + instance: global_instance_name, + textAlign: 'center', + acceptOnScroll: false, + acceptOnClick: false, + acceptOnTimeout: null, + acceptOnFirstVisit: false, + onInserted: null, + onClosed: null, + delayBeforeClose: null, + fadeOutDurationMs: 2000 + }; + + this.options = this.default_options; + this.script_el = script_el_invoker; + + if (this.script_el) { + var data_options = Utils.get_data_attribs(this.script_el); + this.options = Utils.merge(this.options, data_options); + } + + // allowing opts passed to the ctor to override everything + if (opts) { + // mimics the "data-option-name" HTML attribute becoming + // this.options.optionName + opts = Utils.normalize_keys(opts); + this.options = Utils.merge(this.options, opts); + } + + // allows customizing the global instance name via options too + global_instance_name = this.options.instance; + + // TODO: parse/validate other options that can benefit + this.options.zindex = parseInt(this.options.zindex, 10); + this.options.mask = Utils.str2bool(this.options.mask); + this.options.closePrecedes = Utils.str2bool(this.options.closePrecedes); + + // check for a possible global callback specified as a string + if ('string' === typeof this.options.expires) { + if ('function' === typeof context[this.options.expires]) { + this.options.expires = context[this.options.expires]; + } else { + // No global callback under that name, check if it's a + // number/numeric and use as duration in seconds. + if (Utils.is_numeric(this.options.expires)) { + this.options.expires = Number(parseFloat(this.options.expires)); + } + } + } + + // check if expires is a callback + if ('function' === typeof this.options.expires) { + // TODO: this might not always be as simple as this + this.options.expires = this.options.expires(); + } + + // Proceed with our plans only if we're invoked via a