diff --git a/_addons/clicker/clicker.js b/_addons/clicker/clicker.js index e7f2405..a07139c 100644 --- a/_addons/clicker/clicker.js +++ b/_addons/clicker/clicker.js @@ -3,258 +3,266 @@ function Clicker(provider) { this.user = null; var messages = { - loginError: "Please login to see this poll.", - unknownError: "Unknown error, please try again later.", - submitError: "Could not submit poll, please try again later.", - submit: "Send", - submitted: "Sent", - deadline: "You can modify your answer until ", + loginError: "Please login to see this poll.", + unknownError: "Unknown error, please try again later.", + submitError: "Could not submit poll, please try again later.", + submit: "Send", + submitted: "Sent", + deadline: "You can modify your answer until ", }; for (var m in provider.messages) - messages[m] = provider.messages[m]; + messages[m] = provider.messages[m]; var shuffle = function(n) { - var shuffle = Array(n).fill(0).map(function (x,i) { return i; }); - for (var i = n - 1; i > 0; i--) { - var j = Math.floor(Math.random() * (i + 1)) - var temp = shuffle[i]; - shuffle[i] = shuffle[j]; - shuffle[j] = temp; - } - return shuffle; + var shuffle = Array(n).fill(0).map(function (x,i) { return i; }); + for (var i = n - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)) + var temp = shuffle[i]; + shuffle[i] = shuffle[j]; + shuffle[j] = temp; + } + return shuffle; }; const clicker = this; this.loginMenu = $('#top-menu .elements-addon-clicker'); this.loginMenu.on('clicker.login-change', function(e) { - this.$('.submenu').innerHTML = ''; - if (clicker.user) { - this.$('.title').textContent = clicker.user.user.profile.name || clicker.user.user._id; - this.$('.submenu') - .append('li Éditer nom'); - this.$('.submenu') - .append('li') - .append('a Résultats') - .href = '../'.repeat(eLeMentS.page.url.split('/').length-2) - + 'addons/clicker/results'; - this.$('.submenu') - .append('li Logout'); - } else { - this.$('.title').textContent = 'Login'; - const sub = this.$('.submenu'); - provider.methods.forEach(function(m) { - var anchor = sub.append('li').append('a'); - anchor.href = provider.host + m.path; - if (m.icon) - anchor.append('i.fa.fa-' + m.icon); - if (m.title) - anchor.append('span.title ' + m.title); - }); - } + this.$('.submenu').innerHTML = ''; + if (clicker.user) { + this.$('.title').textContent = clicker.user.user.profile.name || clicker.user.user._id; + this.title = clicker.user.host; + this.$('.submenu') + .append('li Éditer nom'); + this.$('.submenu') + .append('li') + .append('a Résultats') + .href = '../'.repeat(eLeMentS.page.url.split('/').length-2) + + 'addons/clicker/results'; + this.$('.submenu') + .append('li Logout'); + } else { + this.$('.title').textContent = 'Login'; + const sub = this.$('.submenu'); + provider.auths.forEach(function(m) { + var anchor = sub.append('li').append('a'); + anchor.className = 'login-auth'; + anchor.href = m.host + m.path; + anchor.dataset.host = m.host; + if (m.icon) + anchor.append('i.fa.fa-' + m.icon); + if (m.title) + anchor.append('span.title ' + m.title); + }); + } }); this.loginMenu.on('click', function(e) { - clicker.logout(); - e.preventDefault(); - window.location.reload(); + window.localStorage['clicker.auth_host'] = this.dataset.host; + }, '.login-auth'); + this.loginMenu.on('click', function(e) { + clicker.logout(); + e.preventDefault(); + window.location.reload(); }, '.logout'); this.loginMenu.on('click', function(e) { - var nom = prompt('Éditer nom', clicker.user.user.profile.name); - clicker._authXHR('/profile', clicker.user.token, function(data, xhr) { - if (xhr.status == 200) { - clicker.user.user.profile = data; - window.sessionStorage['clicker.user'] = JSON.stringify(clicker.user); - clicker.loginMenu.dispatchEvent(new Event('clicker.login-change')); - } else { - console.log(xhr.status, data); - } - }, function(e) { - console.log(e); - }, { - name: nom - }); - e.preventDefault(); + var nom = prompt('Éditer nom', clicker.user.user.profile.name); + clicker._authXHR(null, '/profile', clicker.user.token, function(data, xhr) { + if (xhr.status == 200) { + clicker.user.user.profile = data; + window.sessionStorage['clicker.user'] = JSON.stringify(clicker.user); + clicker.loginMenu.dispatchEvent(new Event('clicker.login-change')); + } else { + console.log(xhr.status, data); + } + }, function(e) { + console.log(e); + }, { + name: nom + }); + e.preventDefault(); }, '.rename-profile'); - this._authXHR = function(path, token, next, onerr, data) { - var xhr = new XMLHttpRequest(); - xhr.open(data !== undefined ? 'POST' : 'GET', this.provider.host + path); - xhr.responseType = 'json'; - if (token) - xhr.setRequestHeader('Authorization', 'bearer ' + token); - xhr.onload = function(e) { - next(xhr.response, xhr); - }; - xhr.onerror = onerr ? onerr : function(err) { console.log(err); }; - if (data) - xhr.setRequestHeader('Content-type', 'application/json'); - xhr.send(JSON.stringify(data)); + this._authXHR = function(host, path, token, next, onerr, data) { + host = host || (this.user && this.user.host) || ''; + var xhr = new XMLHttpRequest(); + xhr.open(data !== undefined ? 'POST' : 'GET', host + path); + xhr.responseType = 'json'; + if (token) + xhr.setRequestHeader('Authorization', 'bearer ' + token); + xhr.onload = function(e) { + next(xhr.response, xhr); + }; + xhr.onerror = onerr ? onerr : function(err) { console.log(err); }; + if (data) + xhr.setRequestHeader('Content-type', 'application/json'); + xhr.send(JSON.stringify(data)); } this.login = function(next) { - var token, user = JSON.parse(window.sessionStorage.getItem('clicker.user')); - if (user !== null && user.expires > Date.now()) { - this.user = user; - next(null, this.user); - } else if (token = window.localStorage.getItem('clicker.token')) { - this._authXHR('/token', token, (function(data, xhr) { - if (xhr.status == 200) { - this.user = data; - window.sessionStorage['clicker.user'] = JSON.stringify(this.user); - window.localStorage['clicker.token'] = this.user.token; - next(null, this.user); - } else { - next(data); - } - }).bind(this), next); - } else { - next(); - } + var token, user = JSON.parse(window.sessionStorage.getItem('clicker.user')); + if (user !== null && user.expires > Date.now()) { + this.user = user; + next(null, this.user); + } else if ((token = window.localStorage.getItem('clicker.token')) + && (host = window.localStorage.getItem('clicker.auth_host'))) { + this._authXHR(host, '/token', token, (data, xhr) => { + if (xhr.status == 200) { + this.user = data; + this.user.host = host; + window.sessionStorage['clicker.user'] = JSON.stringify(this.user); + window.localStorage['clicker.token'] = this.user.token; + next(null, this.user); + } else { + next(data); + } + }, next); + } else { + next(); + } } this.logout = function() { - this.user = null; - window.sessionStorage.removeItem('clicker.user'); - window.localStorage.removeItem('clicker.token'); + this.user = null; + window.sessionStorage.removeItem('clicker.user'); + window.localStorage.removeItem('clicker.token'); } this.injectPoll = function(id, node) { - node.innerHTML = ''; - if (!this.user) { - node.append("p.clicker-error " + messages.loginError); - return console.error('Not logged in'); - } - var url = '/answer/' + id; - this._authXHR(url, this.user.token, (function(data, xhr) { - if (xhr.status != 200 && xhr.status != 403) { - node.append("p.clicker-error " + messages.unknownError); - return console.error(data); - } - console.log(data); - node.append('h3.clicker-title ' + data.poll.title); - node.append('div.clicker-question ' + data.poll.question); - var choices = node.append('ul.clicker-choices'); - var shuf = shuffle(data.poll.choices.length); - console.log(shuf); - shuf.forEach(function (x) { - makeChoice(choices, data, data.poll.choices[x]); - }); - - function makeChoice(parent, data, answ) { - var choice = parent - .append('li' + (answ.correct ? '.clicker-correct' : '')) - .append('label') - .append('div') - var input = choice - .append('input.clicker-choice#clicker-choice-' + answ._id); - input.type = data.poll.multiChoice ? 'checkbox' : 'radio'; - input.name = 'clicker-' + id; - if (data.answers.length - && data.answers[data.answers.length-1].answer.choices.indexOf(answ._id) >= 0) { - input.setAttribute('checked', true); - } - if (!data.poll.can.answer) { - input.disabled = true; - } - choice.innerHTML += answ.answer; - } - - var button = node - .append('button.clicker-submit') - .on('click', (function(e) { - button.disabled = true; - var answers = node - .$$('input.clicker-choice:checked') - .map(function(input) { - return input.id.slice('clicker-choice-'.length); - }); - this._authXHR(url, this.user.token, function(data, xhr) { - if (xhr.status == 200) { - console.log(data); - data.answers = data.result.answers.map(function(a) { - return { answer: a }; - }); - choices.innerHTML = ""; - shuf.forEach(function (x) { - makeChoice(choices, data, data.poll.choices[x]); - }); - grade(node, data.grade); - } else { - console.log(xhr.response); - alert(messages.submitError); - } - }, null, answers); - }).bind(this)); - var buttonText = button.append('span ' + messages.submit); - var buttonMark = button.append('span.clicker-grade.fa').append('span.fa-arrow-right'); + node.innerHTML = ''; + if (!this.user) { + node.append("p.clicker-error " + messages.loginError); + return console.error('Not logged in'); + } + var url = '/answer/' + id; + this._authXHR(null, url, this.user.token, (data, xhr) => { + if (xhr.status != 200 && xhr.status != 403) { + node.append("p.clicker-error " + messages.unknownError); + return console.error(data); + } + console.log(data); + node.append('h3.clicker-title ' + data.poll.title); + node.append('div.clicker-question ' + data.poll.question); + var choices = node.append('ul.clicker-choices'); + var shuf = shuffle(data.poll.choices.length); + console.log(shuf); + shuf.forEach(function (x) { + makeChoice(choices, data, data.poll.choices[x]); + }); + + function makeChoice(parent, data, answ) { + var choice = parent + .append('li' + (answ.correct ? '.clicker-correct' : '')) + .append('label') + .append('div') + var input = choice + .append('input.clicker-choice#clicker-choice-' + answ._id); + input.type = data.poll.multiChoice ? 'checkbox' : 'radio'; + input.name = 'clicker-' + id; + if (data.answers.length + && data.answers[data.answers.length-1].answer.choices.indexOf(answ._id) >= 0) { + input.setAttribute('checked', true); + } + if (!data.poll.can.answer) { + input.disabled = true; + } + choice.innerHTML += answ.answer; + } + + var button = node + .append('button.clicker-submit') + .on('click', (e) => { + button.disabled = true; + var answers = node + .$$('input.clicker-choice:checked') + .map(function(input) { + return input.id.slice('clicker-choice-'.length); + }); + this._authXHR(null, url, this.user.token, function(data, xhr) { + if (xhr.status == 200) { + console.log(data); + data.answers = data.result.answers.map(function(a) { + return { answer: a }; + }); + choices.innerHTML = ""; + shuf.forEach(function (x) { + makeChoice(choices, data, data.poll.choices[x]); + }); + grade(node, data.grade); + } else { + console.log(xhr.response); + alert(messages.submitError); + } + }, null, answers); + }); + var buttonText = button.append('span ' + messages.submit); + var buttonMark = button.append('span.clicker-grade.fa').append('span.fa-arrow-right'); - function grade(node, grade) { - buttonMark.className = ''; - if (grade) { - node.classList.add('graded'); - node.dataset['clickerGrade'] = JSON.stringify(grade); - if (grade.on ? grade.ok == grade.on : grade.ok) { - buttonMark.className = 'fa-check'; - } else { - buttonMark.className = 'fa-close'; - } - } else { - buttonText.textContent = messages.submitted; - } - } - - if (data.answers.length) { - grade(node, data.answers[data.answers.length-1].grade); - } + function grade(node, grade) { + buttonMark.className = ''; + if (grade) { + node.classList.add('graded'); + node.dataset['clickerGrade'] = JSON.stringify(grade); + if (grade.on ? grade.ok == grade.on : grade.ok) { + buttonMark.className = 'fa-check'; + } else { + buttonMark.className = 'fa-close'; + } + } else { + buttonText.textContent = messages.submitted; + } + } + + if (data.answers.length) { + grade(node, data.answers[data.answers.length-1].grade); + } - if (data.answers.length || !data.poll.multiChoice || !data.poll.can.answer) { - button.disabled = true; - } - - node.on('change', function(e) { - if(data.poll.can.answer) { - button.disabled = false; - buttonText.textContent = messages.submit; - buttonMark.className = 'fa-arrow-right'; - } - }); + if (data.answers.length || !data.poll.multiChoice || !data.poll.can.answer) { + button.disabled = true; + } + + node.on('change', function(e) { + if(data.poll.can.answer) { + button.disabled = false; + buttonText.textContent = messages.submit; + buttonMark.className = 'fa-arrow-right'; + } + }); - if (typeof(data.poll.can.answer) == 'string') - node - .append('div.clicker-deadline ' + messages.deadline + ' ') - .append('span ' + (new Date(data.poll.can.answer)).toLocaleString(false, { - day: 'numeric', - month: 'long', - year: 'numeric', - hour: 'numeric', - })); - }).bind(this), function(err) { - node.append("p.clicker-error " + messages.unknownError); - return console.error(err); - }); + if (typeof(data.poll.can.answer) == 'string') + node + .append('div.clicker-deadline ' + messages.deadline + ' ') + .append('span ' + (new Date(data.poll.can.answer)).toLocaleString(false, { + day: 'numeric', + month: 'long', + year: 'numeric', + hour: 'numeric', + })); + }, function(err) { + node.append("p.clicker-error " + messages.unknownError); + return console.error(err); + }); }; - this.loginMenu.on('clicker.login-change', (function (e) { - $$('.clicker-poll').forEach((function(poll) { - this.injectPoll(poll.id.slice('clicker-'.length), poll); - }).bind(this)); - }).bind(this)); + this.loginMenu.on('clicker.login-change', + (e) => $$('.clicker-poll').forEach( + (poll) => this.injectPoll(poll.id.slice('clicker-'.length), poll) + )); var qs = window.location.parsed_querystring(); if (qs.token !== undefined) { - window.localStorage['clicker.token'] = qs.token; - delete qs.token; - history.replaceState({}, '', - '?' + Object.keys(qs).map(function(k) { - return k + (qs[k] !== true ? '=' + qs[k] : ''); - }).join('&')); + window.localStorage['clicker.token'] = qs.token; + delete qs.token; + history.replaceState({}, '', + '?' + Object.keys(qs).map(function(k) { + return k + (qs[k] !== true ? '=' + qs[k] : ''); + }).join('&')); } - this.login((function(err, user) { - if (err) { - this.logout(); - console.log(err); - } - this.loginMenu.dispatchEvent(new Event('clicker.login-change')); - }).bind(this)); + this.login((err, user) => { + if (err) { + this.logout(); + console.log(err); + } + this.loginMenu.dispatchEvent(new Event('clicker.login-change')); + }); } var clicker = new Clicker(eLeMentS.page.addons.clicker); diff --git a/_addons/clicker/grading.js b/_addons/clicker/grading.js index 8b0013b..0c44df1 100644 --- a/_addons/clicker/grading.js +++ b/_addons/clicker/grading.js @@ -42,7 +42,7 @@ function grade(timeline, total) { function gradeAll(users, total) { return users.map((u) => new Promise((resolve, reject) => { - clicker._authXHR('/stats/user/' + u._id, clicker.user.token, (answers, xhr) => { + clicker._authXHR(null, '/stats/user/' + u._id, clicker.user.token, (answers, xhr) => { u.grade = grade(timeline(answers), total); resolve(u); }, (err) => { diff --git a/_addons/clicker/results.js b/_addons/clicker/results.js index 7f70587..716bce6 100644 --- a/_addons/clicker/results.js +++ b/_addons/clicker/results.js @@ -1,6 +1,6 @@ var url = '/stats/' + (location.search ? 'user/' + location.search.substr(1) : 'me'); -clicker._authXHR(url, clicker.user.token, function(answers, xhr) { +clicker._authXHR(null, url, clicker.user.token, function(answers, xhr) { if (xhr.status != 200) throw new Error(xhr.status + " " + answers.code + ": " + answers.message); @@ -19,7 +19,7 @@ clicker._authXHR(url, clicker.user.token, function(answers, xhr) { if (answer.grade) q.append('i.clicker-grade.fa' + (answer.correct ? '.fa-check' : '.fa-close')); } else { - clicker._authXHR('/polls/' + quiz, clicker.user.token, function(poll) { + clicker._authXHR(null, '/polls/' + quiz, clicker.user.token, function(poll) { var q = list.append('li ' + poll.title); if (poll.can.answer === false) { q.classList.add('past') diff --git a/_addons/clicker/stats.js b/_addons/clicker/stats.js index 3d16e01..c87a88a 100644 --- a/_addons/clicker/stats.js +++ b/_addons/clicker/stats.js @@ -1,4 +1,4 @@ -clicker._authXHR('/users', clicker.user.token, function(users, xhr) { +clicker._authXHR(null, '/users', clicker.user.token, function(users, xhr) { if (xhr.status != 200) throw new Error(xhr.status + " " + answers.code + ": " + answers.message); @@ -12,6 +12,7 @@ clicker._authXHR('/users', clicker.user.token, function(users, xhr) { var staleness = Math.max(now - u.lastSeen, 0); var a = udiv.append('li').append('a ' + u.profile.name); a.href = "results?" + u._id; + a.title = u.profile.data.login; a.css({ opacity: Math.max((month - staleness)/month, 0.1) }); } }); @@ -27,7 +28,7 @@ quizzes.forEach(function(l) { var quiz = quizzes.append('li'); var title = quiz.append('h4 '); var statdiv = quiz.append('p'); - clicker._authXHR('/stats/poll/' + q, clicker.user.token, function(answers, xhr) { + clicker._authXHR(null, '/stats/poll/' + q, clicker.user.token, function(answers, xhr) { var timeline = answers.map(function (a) { var answ = a.answers.reduce(function(min, a) { return new Date(a.date) < new Date(min.date) ? a : min; @@ -95,7 +96,7 @@ quizzes.forEach(function(l) { bezierCurve: false, }); }); - clicker._authXHR('/polls/' + q, clicker.user.token, function(poll, xhr) { + clicker._authXHR(null, '/polls/' + q, clicker.user.token, function(poll, xhr) { title.$('span:nth-child(1)').textContent = poll.title; }); }); diff --git a/_config.yml b/_config.yml index 9f45033..60b8f1a 100644 --- a/_config.yml +++ b/_config.yml @@ -37,10 +37,14 @@ defaults: favicon: yes muut: yes clicker: - host: 'https://keats.prism.uvsq.fr/aws' - methods: - - title: " GitHub" + auths: + - title: " Login ISTY" icon: github + host: 'https://keats.prism.uvsq.fr/aws' + path: /login/github + - title: " Login UVSQ" + icon: github + host: 'https://keats.prism.uvsq.fr/aws-alt' path: /login/github messages: loginError: Veulliez vous connecter pour visualiser ce questionnaire.