Added results view page

This commit is contained in:
pmk 2018-09-24 11:05:10 +02:00
parent fa285134cb
commit 773d1acdbe
14 changed files with 417 additions and 288 deletions

View File

@ -6,8 +6,7 @@
define([], function () { define([], function () {
return (function (name) { return (function (handle) {
let handle = name;
let output_enabled = false; let output_enabled = false;
return { return {

View File

@ -5,15 +5,15 @@
// You can call it anything you like // You can call it anything you like
define([], function () { define([], function () {
let debug_enabled = false;
let self = { let self = {
fail_report_exception: function fail_report_exception(ex) { fail_report_exception: function fail_report_exception(ex) {
if (ex.error != undefined) { if (ex.error != undefined) {
console.error("Error from webservice: ", ex.error, "\n", ex.debuginfo, "\n---Stack trace---\n", ex.stacktrace, "\n", ex); console.error("Error from webservice: ", ex.error, "\n",
ex.debuginfo, "\n---Stack trace---\n", ex.stacktrace, "\n", ex);
} }
else { else {
console.error("Exception from webservice: ", ex.message, "\n", ex.debuginfo, "\n---Stack trace---\n", ex.backtrace, "\n", ex); console.error("Exception from webservice: ", ex.message, "\n",
ex.debuginfo, "\n---Stack trace---\n", ex.backtrace, "\n", ex);
} }
}, },

View File

@ -1,3 +1,4 @@
/*eslint max-len: ["error", { "code": 150 }]*/
/**! /**!
* @preserve Shadow animation 1.11 * @preserve Shadow animation 1.11
* http://www.bitstorm.org/jquery/shadow-animation/ * http://www.bitstorm.org/jquery/shadow-animation/
@ -8,228 +9,230 @@
define(['jquery'], function (jQuery) { define(['jquery'], function (jQuery) {
return jQuery(function($, undefined) { return jQuery(function($) {
/** /**
* Check whether the browser supports RGBA color mode. * Check whether the browser supports RGBA color mode.
* *
* Author Mehdi Kabab <http://pioupioum.fr> * Author Mehdi Kabab <http://pioupioum.fr>
* @return {boolean} True if the browser support RGBA. False otherwise. * @return {boolean} True if the browser support RGBA. False otherwise.
*/ */
function isRGBACapable() { function isRGBACapable() {
var $script = $('script:first'), var $script = $('script:first'),
color = $script.css('color'), color = $script.css('color'),
result = false; result = false;
if (/^rgba/.test(color)) { if (/^rgba/.test(color)) {
result = true; result = true;
} else { } else {
try { try {
result = (color !== $script.css('color', 'rgba(0, 0, 0, 0.5)').css('color')); result = (color !== $script.css('color', 'rgba(0, 0, 0, 0.5)').css('color'));
$script.css('color', color); $script.css('color', color);
} catch (e) { } catch (e) {
} }
} }
$script.removeAttr('style'); $script.removeAttr('style');
return result; return result;
} }
$.extend(true, $, { $.extend(true, $, {
support: { support: {
'rgba': isRGBACapable() 'rgba': isRGBACapable()
} }
}); });
/*************************************/ /*************************************/
// First define which property to use // First define which property to use
var styles = $('html').prop('style'); var styles = $('html').prop('style');
var boxShadowProperty; var boxShadowProperty;
$.each(['boxShadow', 'MozBoxShadow', 'WebkitBoxShadow'], function(i, property) { $.each(['boxShadow', 'MozBoxShadow', 'WebkitBoxShadow'], function(i, property) {
var val = styles[property]; var val = styles[property];
if (typeof val !== 'undefined') { if (typeof val !== 'undefined') {
boxShadowProperty = property; boxShadowProperty = property;
return false; return false;
} }
}); });
// Extend the animate-function // Extend the animate-function
if (boxShadowProperty) { if (boxShadowProperty) {
$['Tween']['propHooks']['boxShadow'] = { $['Tween']['propHooks']['boxShadow'] = {
get: function(tween) { get: function(tween) {
return $(tween.elem).css(boxShadowProperty); return $(tween.elem).css(boxShadowProperty);
}, },
set: function(tween) { set: function(tween) {
var style = tween.elem.style; var style = tween.elem.style;
var p_begin = parseShadows($(tween.elem)[0].style[boxShadowProperty] || $(tween.elem).css(boxShadowProperty)); var p_begin = parseShadows($(tween.elem)[0].style[boxShadowProperty] || $(tween.elem).css(boxShadowProperty));
var p_end = parseShadows(tween.end); var p_end = parseShadows(tween.end);
var maxShadowCount = Math.max(p_begin.length, p_end.length); var maxShadowCount = Math.max(p_begin.length, p_end.length);
var i; var i;
for(i = 0; i < maxShadowCount; i++) { for(i = 0; i < maxShadowCount; i++) {
p_end[i] = $.extend({}, p_begin[i], p_end[i]); p_end[i] = $.extend({}, p_begin[i], p_end[i]);
if (p_begin[i]) { if (p_begin[i]) {
if (!('color' in p_begin[i]) || $.isArray(p_begin[i].color) === false) { if (!('color' in p_begin[i]) || $.isArray(p_begin[i].color) === false) {
p_begin[i].color = p_end[i].color || [0, 0, 0, 0]; p_begin[i].color = p_end[i].color || [0, 0, 0, 0];
} }
} else { } else {
p_begin[i] = parseShadows('0 0 0 0 rgba(0,0,0,0)')[0]; p_begin[i] = parseShadows('0 0 0 0 rgba(0,0,0,0)')[0];
} }
} }
tween['run'] = function(progress) { tween['run'] = function(progress) {
var rs = calculateShadows(p_begin, p_end, progress); var rs = calculateShadows(p_begin, p_end, progress);
style[boxShadowProperty] = rs; style[boxShadowProperty] = rs;
}; };
} }
}; };
} }
// Calculate an in-between shadow. // Calculate an in-between shadow.
function calculateShadows(beginList, endList, pos) { function calculateShadows(beginList, endList, pos) {
var shadows = []; var shadows = [];
$.each(beginList, function(i) { $.each(beginList, function(i) {
var parts = [], begin = beginList[i], end = endList[i]; var parts = [], begin = beginList[i], end = endList[i];
if (begin.inset) { if (begin.inset) {
parts.push('inset'); parts.push('inset');
} }
if (typeof end.left !== 'undefined') { if (typeof end.left !== 'undefined') {
parts.push(parseFloat(begin.left + pos * (end.left - begin.left)) + 'px ' parts.push(parseFloat(begin.left + pos * (end.left - begin.left)) + 'px '
+ parseFloat(begin.top + pos * (end.top - begin.top)) + 'px'); + parseFloat(begin.top + pos * (end.top - begin.top)) + 'px');
} }
if (typeof end.blur !== 'undefined') { if (typeof end.blur !== 'undefined') {
parts.push(parseFloat(begin.blur + pos * (end.blur - begin.blur)) + 'px'); parts.push(parseFloat(begin.blur + pos * (end.blur - begin.blur)) + 'px');
} }
if (typeof end.spread !== 'undefined') { if (typeof end.spread !== 'undefined') {
parts.push(parseFloat(begin.spread + pos * (end.spread - begin.spread)) + 'px'); parts.push(parseFloat(begin.spread + pos * (end.spread - begin.spread)) + 'px');
} }
if (typeof end.color !== 'undefined') { if (typeof end.color !== 'undefined') {
var color = 'rgb' + ($.support['rgba'] ? 'a' : '') + '(' var color = 'rgb' + ($.support['rgba'] ? 'a' : '') + '('
+ parseInt((begin.color[0] + pos * (end.color[0] - begin.color[0])), 10) + ',' + parseInt((begin.color[0] + pos * (end.color[0] - begin.color[0])), 10) + ','
+ parseInt((begin.color[1] + pos * (end.color[1] - begin.color[1])), 10) + ',' + parseInt((begin.color[1] + pos * (end.color[1] - begin.color[1])), 10) + ','
+ parseInt((begin.color[2] + pos * (end.color[2] - begin.color[2])), 10); + parseInt((begin.color[2] + pos * (end.color[2] - begin.color[2])), 10);
if ($.support['rgba']) { if ($.support['rgba']) {
color += ',' + parseFloat(begin.color[3] + pos * (end.color[3] - begin.color[3])); color += ',' + parseFloat(begin.color[3] + pos * (end.color[3] - begin.color[3]));
} }
color += ')'; color += ')';
parts.push(color); parts.push(color);
} }
shadows.push(parts.join(' ')); shadows.push(parts.join(' '));
}); });
return shadows.join(', '); return shadows.join(', ');
} }
// Parse the shadow value and extract the values. // Parse the shadow value and extract the values.
function parseShadows(shadow) { function parseShadows(shadow) {
var parsedShadows = []; var parsedShadows = [];
var parsePosition = 0; var parsePosition = 0;
var parseLength = shadow.length; var parseLength = shadow.length;
function findInset() { function findInset() {
var m = /^inset\b/.exec(shadow.substring(parsePosition)); var m = /^inset\b/.exec(shadow.substring(parsePosition));
if (m !== null && m.length > 0) { if (m !== null && m.length > 0) {
parsedShadow.inset = true; parsedShadow.inset = true;
parsePosition += m[0].length; parsePosition += m[0].length;
return true; return true;
} }
return false; return false;
} }
function findOffsets() { function findOffsets() {
var m = /^(-?[0-9\.]+)(?:px)?\s+(-?[0-9\.]+)(?:px)?(?:\s+(-?[0-9\.]+)(?:px)?)?(?:\s+(-?[0-9\.]+)(?:px)?)?/.exec(shadow.substring(parsePosition)); var m = /^(-?[0-9\.]+)(?:px)?\s+(-?[0-9\.]+)(?:px)?(?:\s+(-?[0-9\.]+)(?:px)?)?(?:\s+(-?[0-9\.]+)(?:px)?)?/.exec(
if (m !== null && m.length > 0) { shadow.substring(parsePosition)
parsedShadow.left = parseInt(m[1], 10); );
parsedShadow.top = parseInt(m[2], 10); if (m !== null && m.length > 0) {
parsedShadow.blur = (m[3] ? parseInt(m[3], 10) : 0); parsedShadow.left = parseInt(m[1], 10);
parsedShadow.spread = (m[4] ? parseInt(m[4], 10) : 0); parsedShadow.top = parseInt(m[2], 10);
parsePosition += m[0].length; parsedShadow.blur = (m[3] ? parseInt(m[3], 10) : 0);
return true; parsedShadow.spread = (m[4] ? parseInt(m[4], 10) : 0);
} parsePosition += m[0].length;
return false; return true;
} }
function findColor() { return false;
var m = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/.exec(shadow.substring(parsePosition)); }
if (m !== null && m.length > 0) { function findColor() {
parsedShadow.color = [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16), 1]; var m = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/.exec(shadow.substring(parsePosition));
parsePosition += m[0].length; if (m !== null && m.length > 0) {
return true; parsedShadow.color = [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16), 1];
} parsePosition += m[0].length;
m = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/.exec(shadow.substring(parsePosition)); return true;
if (m !== null && m.length > 0) { }
parsedShadow.color = [parseInt(m[1], 16) * 17, parseInt(m[2], 16) * 17, parseInt(m[3], 16) * 17, 1]; m = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/.exec(shadow.substring(parsePosition));
parsePosition += m[0].length; if (m !== null && m.length > 0) {
return true; parsedShadow.color = [parseInt(m[1], 16) * 17, parseInt(m[2], 16) * 17, parseInt(m[3], 16) * 17, 1];
} parsePosition += m[0].length;
m = /^rgb\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition)); return true;
if (m !== null && m.length > 0) { }
parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), 1]; m = /^rgb\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition));
parsePosition += m[0].length; if (m !== null && m.length > 0) {
return true; parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), 1];
} parsePosition += m[0].length;
m = /^rgba\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition)); return true;
if (m !== null && m.length > 0) { }
parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), parseFloat(m[4])]; m = /^rgba\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition));
parsePosition += m[0].length; if (m !== null && m.length > 0) {
return true; parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), parseFloat(m[4])];
} parsePosition += m[0].length;
return false; return true;
} }
function findWhiteSpace() { return false;
var m = /^\s+/.exec(shadow.substring(parsePosition)); }
if (m !== null && m.length > 0) { function findWhiteSpace() {
parsePosition += m[0].length; var m = /^\s+/.exec(shadow.substring(parsePosition));
return true; if (m !== null && m.length > 0) {
} parsePosition += m[0].length;
return false; return true;
} }
function findComma() { return false;
var m = /^\s*,\s*/.exec(shadow.substring(parsePosition)); }
if (m !== null && m.length > 0) { function findComma() {
parsePosition += m[0].length; var m = /^\s*,\s*/.exec(shadow.substring(parsePosition));
return true; if (m !== null && m.length > 0) {
} parsePosition += m[0].length;
return false; return true;
} }
function normalizeShadow(shadow) { return false;
if ($.isPlainObject(shadow)) { }
var i, sColor, cLength = 0, color = []; function normalizeShadow(shadow) {
if ($.isArray(shadow.color)) { if ($.isPlainObject(shadow)) {
sColor = shadow.color; var i, sColor, cLength = 0, color = [];
cLength = sColor.length; if ($.isArray(shadow.color)) {
} sColor = shadow.color;
for(i = 0; i < 4; i++) { cLength = sColor.length;
if (i < cLength) { }
color.push(sColor[i]); for(i = 0; i < 4; i++) {
} else if (i === 3) { if (i < cLength) {
color.push(1); color.push(sColor[i]);
} else { } else if (i === 3) {
color.push(0); color.push(1);
} } else {
} color.push(0);
} }
return $.extend({ }
'left': 0, }
'top': 0, return $.extend({
'blur': 0, 'left': 0,
'spread': 0 'top': 0,
}, shadow); 'blur': 0,
} 'spread': 0
var parsedShadow = normalizeShadow(); }, shadow);
}
var parsedShadow = normalizeShadow();
while (parsePosition < parseLength) { while (parsePosition < parseLength) {
if (findInset()) { if (findInset()) {
findWhiteSpace(); findWhiteSpace();
} else if (findOffsets()) { } else if (findOffsets()) {
findWhiteSpace(); findWhiteSpace();
} else if (findColor()) { } else if (findColor()) {
findWhiteSpace(); findWhiteSpace();
} else if (findComma()) { } else if (findComma()) {
parsedShadows.push(normalizeShadow(parsedShadow)); parsedShadows.push(normalizeShadow(parsedShadow));
parsedShadow = {}; parsedShadow = {};
} else { } else {
break; break;
} }
} }
parsedShadows.push(normalizeShadow(parsedShadow)); parsedShadows.push(normalizeShadow(parsedShadow));
return parsedShadows; return parsedShadows;
} }
}); });
}); });

View File

@ -1,3 +1,9 @@
/*eslint no-unused-vars: "off" */
/*eslint max-len: "off" */
/*eslint no-bitwise: "off" */
/*eslint no-cond-assign: "off" */
/*eslint no-new-func: "off" */
/*eslint no-caller: "off" */
/** /**
* jscolor - JavaScript Color Picker * jscolor - JavaScript Color Picker
* *
@ -180,7 +186,7 @@ define([], function () {
document.detachEvent('onreadystatechange', arguments.callee); document.detachEvent('onreadystatechange', arguments.callee);
fireOnce(); fireOnce();
} }
}) });
// Fallback // Fallback
window.attachEvent('onload', fireOnce); window.attachEvent('onload', fireOnce);
@ -624,8 +630,8 @@ define([], function () {
case 'pad': case 'pad':
// if the slider is at the bottom, move it up // if the slider is at the bottom, move it up
switch (jsc.getSliderComponent(thisObj)) { switch (jsc.getSliderComponent(thisObj)) {
case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); }; break; case 's': if (thisObj.hsv[1] === 0) { thisObj.fromHSV(null, 100, null); } break;
case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); }; break; case 'v': if (thisObj.hsv[2] === 0) { thisObj.fromHSV(null, null, 100); } break;
} }
jsc.setPad(thisObj, e, 0, 0); jsc.setPad(thisObj, e, 0, 0);
break; break;
@ -655,7 +661,7 @@ define([], function () {
jsc.dispatchFineChange(thisObj); jsc.dispatchFineChange(thisObj);
break; break;
} }
} };
}, },
@ -809,7 +815,7 @@ define([], function () {
hGrad.type = 'gradient'; hGrad.type = 'gradient';
hGrad.method = 'linear'; hGrad.method = 'linear';
hGrad.angle = '90'; hGrad.angle = '90';
hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0' hGrad.colors = '16.67% #F0F, 33.33% #00F, 50% #0FF, 66.67% #0F0, 83.33% #FF0';
var hRect = document.createElement(jsc._vmlNS + ':rect'); var hRect = document.createElement(jsc._vmlNS + ':rect');
hRect.style.position = 'absolute'; hRect.style.position = 'absolute';
@ -1818,7 +1824,9 @@ define([], function () {
if (this.value) { if (this.value) {
// Try to set the color from the .value option and if unsuccessful, // Try to set the color from the .value option and if unsuccessful,
// export the current color // export the current color
this.fromString(this.value) || this.exportColor(); if (!this.fromString(this.value)) {
this.exportColor();
}
} else { } else {
this.importColor(); this.importColor();
} }

View File

@ -1,4 +1,5 @@
/*eslint no-var: "error"*/ /*eslint no-var: "error" */
/*eslint no-unused-vars: "off" */
/*eslint-env es6*/ /*eslint-env es6*/
// Put this file in path/to/plugin/amd/src // Put this file in path/to/plugin/amd/src
// You can call it anything you like // You can call it anything you like
@ -25,7 +26,7 @@ define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/aj
} }
// make sure all uint type numbers are not able to go below 0 // make sure all uint type numbers are not able to go below 0
$(document).on('input', "input[type=number].uint", function (evt) { $(document).on('input', "input[type=number].uint", function (e) {
let $this = $(this); let $this = $(this);
if ($this.val() < 0) { if ($this.val() < 0) {
$this.val(0); $this.val(0);
@ -33,7 +34,7 @@ define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/aj
}); });
// On click handler for add level link // On click handler for add level link
$("a[data-action=addlevel]").on('click', function (evt) { $("a[data-action=addlevel]").on('click', function (e) {
self.add_levelrow(-255, '', '7F7F7F'); self.add_levelrow(-255, '', '7F7F7F');
}); });
@ -80,7 +81,7 @@ define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/aj
id: Number($this.attr('data-rowid')), id: Number($this.attr('data-rowid')),
points: $this.find("input[data-name=points]").val(), points: $this.find("input[data-name=points]").val(),
badgecolor: $this.find("input[data-name=color]").val(), badgecolor: $this.find("input[data-name=color]").val(),
} };
if (row.points === "") { row.points = -255; } if (row.points === "") { row.points = -255; }
row.points = Number(row.points); row.points = Number(row.points);
@ -110,7 +111,7 @@ define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/aj
id: Number($this.attr('data-rowid')), id: Number($this.attr('data-rowid')),
points: -255, // means: delete row points: -255, // means: delete row
badgecolor: "", // totally irrelevent when requesting a delete badgecolor: "", // totally irrelevent when requesting a delete
} };
level_data.push(row); level_data.push(row);
}); });
@ -137,7 +138,6 @@ define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/aj
} }
let $inputs = $tbody.find("input[data-name='points']"); let $inputs = $tbody.find("input[data-name='points']");
let orig_border = $inputs.css('border-left-color');
$inputs $inputs
.animate({ boxShadow: '0px 0px 5px 3px #3FDFCF'}, 400) .animate({ boxShadow: '0px 0px 5px 3px #3FDFCF'}, 400)
.delay(200) .delay(200)

View File

@ -9,7 +9,7 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
let self = { let self = {
init: function init() { init: function init() {
// Put whatever you like here. $ is available // Put whatever you like here. $ is available
// to you as normal. // to you as normal.
$("figure.levelbadge").each(function () { $("figure.levelbadge").each(function () {
@ -76,7 +76,7 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
y: 0.47, y: 0.47,
scale: 0.7, // scale to this fraction of image size scale: 0.7, // scale to this fraction of image size
} }
} };
debug.info(" Config", config); debug.info(" Config", config);
debug.info(" Colors", colors); debug.info(" Colors", colors);
debug.info(" Props", props); debug.info(" Props", props);
@ -97,7 +97,7 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2, 0, 2 * Math.PI); ctx.arc(0.5 * config.size, 0.5 * config.size, config.size / 2, 0, 2 * Math.PI);
ctx.fill(); ctx.fill();
// draw main reflection // draw main reflection
let rflOffset = Math.asin(config.reflection.offset); let rflOffset = Math.asin(config.reflection.offset);
let rflAngleRad = (config.reflection.angle / 360.0) * 2 * Math.PI; let rflAngleRad = (config.reflection.angle / 360.0) * 2 * Math.PI;
@ -155,7 +155,7 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
if (props.image) { if (props.image) {
let iconImg = new Image(); let iconImg = new Image();
iconImg.onload = function () { iconImg.onload = function () {
let imPos = { let imPos = {
x: 0, // to be determined later x: 0, // to be determined later
y: 0, // to be determined later y: 0, // to be determined later
w: config.size * config.icon.scale, w: config.size * config.icon.scale,
@ -172,13 +172,13 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
// calculate x and y // calculate x and y
imPos.x = (config.size * config.icon.x) - (imPos.w / 2); imPos.x = (config.size * config.icon.x) - (imPos.w / 2);
imPos.y = (config.size * config.icon.y) - (imPos.h / 2); imPos.y = (config.size * config.icon.y) - (imPos.h / 2);
ctx.drawImage(this, imPos.x, imPos.y, imPos.w, imPos.h); ctx.drawImage(this, imPos.x, imPos.y, imPos.w, imPos.h);
} };
//debug.info("Image: ",props.image); //debug.info("Image: ",props.image);
iconImg.src = props.image; iconImg.src = props.image;
} }
// complete // complete
}, },
fetchProperties: function fetchProperties(figure) { fetchProperties: function fetchProperties(figure) {
@ -200,6 +200,7 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
}, },
shadeBlendConvert: function shadeBlendConvert(p, from, to) { shadeBlendConvert: function shadeBlendConvert(p, from, to) {
/* eslint-disable no-bitwise, max-len, curly, no-var, no-unused-expressions */
// Code for this function was taken from https://github.com/PimpTrizkit/PJs pSBC.js // Code for this function was taken from https://github.com/PimpTrizkit/PJs pSBC.js
if (typeof (p) != "number" || p < -1 || p > 1 || typeof (from) != "string" || (from[0] != 'r' && from[0] != '#') || (to && typeof (to) != "string")) return null; //ErrorCheck if (typeof (p) != "number" || p < -1 || p > 1 || typeof (from) != "string" || (from[0] != 'r' && from[0] != '#') || (to && typeof (to) != "string")) return null; //ErrorCheck
if (!this.sbcRip) this.sbcRip = (d) => { if (!this.sbcRip) this.sbcRip = (d) => {
@ -215,12 +216,12 @@ define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], functio
if (l == 9 || l == 5) RGB[3] = r((RGB[2] / 255) * 10000) / 10000, RGB[2] = RGB[1], RGB[1] = RGB[0], RGB[0] = d >> 24 & 255; if (l == 9 || l == 5) RGB[3] = r((RGB[2] / 255) * 10000) / 10000, RGB[2] = RGB[1], RGB[1] = RGB[0], RGB[0] = d >> 24 & 255;
} }
return RGB; return RGB;
} };
var i = parseInt, r = Math.round, h = from.length > 9, h = typeof (to) == "string" ? to.length > 9 ? true : to == "c" ? !h : false : h, b = p < 0, p = b ? p * -1 : p, to = to && to != "c" ? to : b ? "#000000" : "#FFFFFF", f = this.sbcRip(from), t = this.sbcRip(to); var i = parseInt, r = Math.round, h = from.length > 9, h = typeof (to) == "string" ? to.length > 9 ? true : to == "c" ? !h : false : h, b = p < 0, p = b ? p * -1 : p, to = to && to != "c" ? to : b ? "#000000" : "#FFFFFF", f = this.sbcRip(from), t = this.sbcRip(to);
if (!f || !t) return null; //ErrorCheck if (!f || !t) return null; //ErrorCheck
if (h) return "rgb" + (f[3] > -1 || t[3] > -1 ? "a(" : "(") + r((t[0] - f[0]) * p + f[0]) + "," + r((t[1] - f[1]) * p + f[1]) + "," + r((t[2] - f[2]) * p + f[2]) + (f[3] < 0 && t[3] < 0 ? ")" : "," + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000 : t[3] < 0 ? f[3] : t[3]) + ")"); if (h) return "rgb" + (f[3] > -1 || t[3] > -1 ? "a(" : "(") + r((t[0] - f[0]) * p + f[0]) + "," + r((t[1] - f[1]) * p + f[1]) + "," + r((t[2] - f[2]) * p + f[2]) + (f[3] < 0 && t[3] < 0 ? ")" : "," + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 10000) / 10000 : t[3] < 0 ? f[3] : t[3]) + ")");
else return "#" + (0x100000000 + r((t[0] - f[0]) * p + f[0]) * 0x1000000 + r((t[1] - f[1]) * p + f[1]) * 0x10000 + r((t[2] - f[2]) * p + f[2]) * 0x100 + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 255) : t[3] > -1 ? r(t[3] * 255) : f[3] > -1 ? r(f[3] * 255) : 255)).toString(16).slice(1, f[3] > -1 || t[3] > -1 ? undefined : -2); else return "#" + (0x100000000 + r((t[0] - f[0]) * p + f[0]) * 0x1000000 + r((t[1] - f[1]) * p + f[1]) * 0x10000 + r((t[2] - f[2]) * p + f[2]) * 0x100 + (f[3] > -1 && t[3] > -1 ? r(((t[3] - f[3]) * p + f[3]) * 255) : t[3] > -1 ? r(t[3] * 255) : f[3] > -1 ? r(f[3] * 255) : 255)).toString(16).slice(1, f[3] > -1 || t[3] > -1 ? undefined : -2);
/* eslint-enable no-bitwise, max-len, curly, no-var, no-unused-expressions */
}, },
}; };

View File

@ -1,10 +1,13 @@
/*eslint no-var: "error"*/ /*eslint no-var: "error"*/
/*eslint no-unused-vars: "off" */
/*eslint-env es6*/ /*eslint-env es6*/
// Put this file in path/to/plugin/amd/src // Put this file in path/to/plugin/amd/src
// You can call it anything you like // You can call it anything you like
define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/renderbadge', 'block_gradelevel/handlers', define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/renderbadge', 'block_gradelevel/handlers',
'block_gradelevel/debugger', 'core/modal_factory','core/modal_events'], function ($, str, ajax, mdlcfg, renderbadge, handlers, Debugger, ModalFactory, ModalEvents) { 'block_gradelevel/debugger', 'core/modal_factory', 'core/modal_events'],
function ($, str, ajax, mdlcfg, renderbadge, handlers, Debugger, ModalFactory, ModalEvents)
{
let debug = Debugger("skilleditor"); let debug = Debugger("skilleditor");
debug.enable(); debug.enable();
@ -23,7 +26,7 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
}); });
debug.info("Attaching function to addskill link"); debug.info("Attaching function to addskill link");
$skillset_div.find("a[data-action='addskill']").on('click', function (ev) { $skillset_div.find("a[data-action='addskill']").on('click', function (e) {
let promises = ajax.call([{ let promises = ajax.call([{
methodname: 'block_gradelevel_add_skill', methodname: 'block_gradelevel_add_skill',
args: { name: null, icon: null }, args: { name: null, icon: null },
@ -39,7 +42,6 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
$newskill.find('figure.levelbadge').each(function () { $newskill.find('figure.levelbadge').each(function () {
renderbadge.setup_badge(this); renderbadge.setup_badge(this);
}); });
}); });
}); });
@ -50,7 +52,7 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
let skill_id = $li.data('id'); let skill_id = $li.data('id');
// Attach edit name pencil // Attach edit name pencil
$li.find("a[data-action='editname']").on('click', function (evt) { $li.find("a[data-action='editname']").on('click', function (e) {
let $span = $li.find("figcaption span[data-type='label']"); let $span = $li.find("figcaption span[data-type='label']");
if ($span.length > 0) { if ($span.length > 0) {
let name = $span.text(); let name = $span.text();
@ -73,7 +75,7 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
promises[0].fail(handlers.fail_report_exception).done(function (data) { promises[0].fail(handlers.fail_report_exception).done(function (data) {
$input.replaceWith($("<span data-type='label'>" + data.name + "</span>")); $input.replaceWith($("<span data-type='label'>" + data.name + "</span>"));
}); });
} }
if (keycode == '27') { if (keycode == '27') {
debug.info("Cancelled editing"); debug.info("Cancelled editing");
@ -93,16 +95,16 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
}); });
// Attach edit icon pencil // Attach edit icon pencil
$li.find("a[data-action='editicon']").on('click', function (ev) { $li.find("a[data-action='editicon']").on('click', function (e) {
let $uploader = $("<input type='file' style='display: none;' accept='" + uploadFilter + "'/>"); let $uploader = $("<input type='file' style='display: none;' accept='" + uploadFilter + "'/>");
$uploader.on('change', function (ev) { $uploader.on('change', function (e) {
ev.stopPropagation(); e.stopPropagation();
ev.preventDefault(); e.preventDefault();
let file = ev.originalEvent.target.files[0]; let file = e.originalEvent.target.files[0];
let fr = new FileReader(); let fr = new FileReader();
$(fr).on('load', function (ev) { $(fr).on('load', function (e) {
let dataURI = ev.target.result; let dataURI = e.target.result;
let promises = ajax.call([{ let promises = ajax.call([{
methodname: 'block_gradelevel_update_skill', methodname: 'block_gradelevel_update_skill',
@ -134,7 +136,8 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
}); });
// Attach edit levels link // Attach edit levels link
$li.find("a[data-action='editlevels']").attr('href', mdlcfg.wwwroot + "/blocks/gradelevel/cfg_skilllevels.php?skill_id=" + skill_id); $li.find("a[data-action='editlevels']").attr('href',
mdlcfg.wwwroot + "/blocks/gradelevel/cfg_skilllevels.php?skill_id=" + skill_id);
// Attach delete function to any existing functional delete link // Attach delete function to any existing functional delete link
$li.find("a[data-action='deleteskill']").each(function () { $li.find("a[data-action='deleteskill']").each(function () {
@ -164,33 +167,13 @@ define(['jquery', 'core/str', 'core/ajax', 'core/config', 'block_gradelevel/rend
if (data.deleted) { if (data.deleted) {
$li.remove(); $li.remove();
} }
}); });
}); });
}); });
}); });
}, },
success_refill_table: function success_refill_table(response) {
//console.info("Response from webservice: ", response);
let $tbody = $skill_table.find('tbody');
$tbody.empty();
for (let idx in response) {
let lvl = response[idx];
//console.info("Level:", lvl);
self.add_levelrow(lvl.id, lvl.points, lvl.badgecolor);
}
},
fail_report_exception: function fail_report_exception(ex) {
if (ex.error != undefined) {
console.error("Error from webservice: ", ex.error, "\n" , ex.debuginfo, "\n---Stack trace---\n", ex.stacktrace, "\n", ex);
}
else {
console.error("Exception from webservice: ", ex.message, "\n", ex.debuginfo, "\n---Stack trace---\n", ex.backtrace, "\n", ex);
}
},
}; };
return self; return self;
}); });

View File

@ -71,7 +71,7 @@ class block_gradelevel extends block_base {
if(has_capability('block/gradelevel:viewresults', $coursecontext)) if(has_capability('block/gradelevel:viewresults', $coursecontext))
{ {
$this->content->footer .= "\n<div class='teachermode'><a href='#'>".get_string('teacher_view_results','block_gradelevel')."</a></div>"; $this->content->footer .= "\n<div class='teachermode'><a href='{$CFG->wwwroot}/blocks/gradelevel/view-results.php?courseid={$COURSE->id}'>".get_string('teacher_view_results','block_gradelevel')."</a></div>";
} }
} }
return $this->content; return $this->content;

View File

@ -6,14 +6,14 @@ require_once($CFG->dirroot.'/grade/querylib.php');
class block_gradelevel_levelset { class block_gradelevel_levelset {
const UNDEFINED_BADGE_COLOR="#3F3F3F"; const UNDEFINED_BADGE_COLOR="#3F3F3F";
const NULL_BADGE_COLOR = "#000000"; const NULL_BADGE_COLOR = "#320000";
const DEFAULT_ICON = "/blocks/gradelevel/pix/undefinedskill.svg"; const DEFAULT_ICON = "/blocks/gradelevel/pix/undefinedskill.svg";
const GLOBAL_DEFAULTS = array( const GLOBAL_DEFAULTS = array(
0 => "#000000", 0 => "#320000",
250 => "#2ad4ff", // + 250 250 => "#2ad4ff", // + 250
750 => "#cd7f32", // + 500 750 => "#cd7f32", // + 500
1750 => "#a6a6a6", // + 1000 1750 => "#92A1A6", // + 1000
2750 => "#f6ae00", // + 2000 2750 => "#f6ae00", // + 2000
); );
@ -244,13 +244,11 @@ class block_gradelevel_levelset {
{ {
if(!$DB->update_record('block_gradelevel_levelset',$this->data)){ if(!$DB->update_record('block_gradelevel_levelset',$this->data)){
print_error('updateerror', 'block_gradelevel'); print_error('updateerror', 'block_gradelevel');
error_log('UPDATE-ERROR\n', 3, '/tmp/moodledevlog.log');
} }
} }
else else
{ {
print_error('datarowchanged_error', 'block_gradelevel'); print_error('datarowchanged_error', 'block_gradelevel');
error_log('DATAROW-INVALID\n', 3, '/tmp/moodledevlog.log');
} }
} }

View File

@ -8,7 +8,7 @@ require_once($CFG->dirroot.'/grade/querylib.php');
class block_gradelevel_skillmgmtservice extends external_api class block_gradelevel_skillmgmtservice extends external_api
{ {
const DEBUG = true; // enable debug logging const DEBUG = false; // enable debug logging
const DEMOBADGE_SIZE = 150; // size of demo badge const DEMOBADGE_SIZE = 150; // size of demo badge
private static function log($message) private static function log($message)
@ -458,7 +458,7 @@ class block_gradelevel_skillmgmtservice extends external_api
if(!$single){ if(!$single){
$s .= "<a data-action='editlevels' href='#'>"; $s .= "<a data-action='editlevels' href='#'>";
if(count($skill->list_courses()) ){ if(count($skill->list_courses()) == 0){
$s .= "<a class='deleteskill' data-action='deleteskill' onclick='return false;' href='#'><i class='icon fa fa-minus-circle fa-fw' title='".get_string('tooltip_deleteskill','block_gradelevel')."'></i></a>"; $s .= "<a class='deleteskill' data-action='deleteskill' onclick='return false;' href='#'><i class='icon fa fa-minus-circle fa-fw' title='".get_string('tooltip_deleteskill','block_gradelevel')."'></i></a>";
} }
} }

View File

@ -69,20 +69,14 @@ class block_gradelevel_edit_form extends block_edit_form {
$currentskill = block_gradelevel_levelset::find_by_course($COURSE->id); $currentskill = block_gradelevel_levelset::find_by_course($COURSE->id);
if(isset($currentskill)) if(isset($currentskill))
{ {
$this->debug("deetaching...");
$currentskill->detach_course($COURSE->id); $currentskill->detach_course($COURSE->id);
} }
$skill = block_gradelevel_levelset::find_by_id($data->attached_skill); $skill = block_gradelevel_levelset::find_by_id($data->attached_skill);
if(isset($skill)){ if(isset($skill)){
$this->debug("attaching...");
$skill->attach_course($COURSE->id); $skill->attach_course($COURSE->id);
} }
} }
} }
private function debug($msg)
{
error_log($msg, 3, '/tmp/moodledevlog.log');
}
} }

View File

@ -5,7 +5,7 @@ $string['title'] = 'Progress level';
$string['gradelevel:addinstance'] = 'Add a new Grade Level block'; $string['gradelevel:addinstance'] = 'Add a new Grade Level block';
$string['gradelevel:myaddinstance'] = 'Add a new Grade Level block to the My Moodle page'; $string['gradelevel:myaddinstance'] = 'Add a new Grade Level block to the My Moodle page';
$string['blockstring'] = 'Text in the block'; $string['blockstring'] = 'Text in the block';
$string['levelup_at'] = 'Next level: '; $string['levelup_at'] = 'Progress: ';
$string['levelup_done'] = 'Complete'; $string['levelup_done'] = 'Complete';
$string['unattached_course'] = 'Please attach this course to a skill in the block settings'; $string['unattached_course'] = 'Please attach this course to a skill in the block settings';
@ -20,6 +20,9 @@ $string['cfgpage_skilllevels'] = "Edit levels";
$string['cfgpage_skills'] = "Manage skills"; $string['cfgpage_skills'] = "Manage skills";
$string['cfgpage_editskill'] = "Edit skill"; $string['cfgpage_editskill'] = "Edit skill";
$string['results_heading'] = "Results for skill ";
$string['results_ungrouped'] = "Other";
$string['descconfig'] = "Configuration for Grade Level block"; $string['descconfig'] = "Configuration for Grade Level block";
$string['labeltitle'] = "Title of gradelevel block"; $string['labeltitle'] = "Title of gradelevel block";

View File

@ -94,6 +94,44 @@ table.level_config tr[data-rowid='-255'] input[data-name='points'] {
background-color: #F0F0F0; background-color: #F0F0F0;
} }
div.block_gradelevel_results ul {
padding-left: 0px;
margin-left: 0px;
}
div .block_gradelevel_results li.result_badge {
position: relative; /* needed to have absolute positions be relative to this li */
list-style: none;
display: inline-block;
width: 190px;
height: 210px;
border-color: #ccc;
border-width: 1px;
border-style: solid;
margin: 5px;
padding: 5px;
padding-top: 10px;
}
div.block_gradelevel_results li.result_badge figcaption {
text-align: center;
height: 3em;
margin-bottom: 0.5rem;
}
div.block_gradelevel_results li.result_badge div.pointinfo {
font-size: 85%;
}
div.block_gradelevel_results li.result_badge figcaption span.namepart {
break-inside: avoid;
display: inline-block;
}
div.block_gradelevel_results figure.levelset_icon {
margin-bottom: 0.5rem;
}
figure.levelset_icon { figure.levelset_icon {
background-color: #ccc; background-color: #ccc;

102
view-results.php Normal file
View File

@ -0,0 +1,102 @@
<?php
if(isset($_SERVER['SCRIPT_FILENAME']))
{
// If SCRIPT_FILENAME is set, use that so the symlinked directories the developmen environment uses are handled correctly
$root = dirname(dirname(dirname($_SERVER['SCRIPT_FILENAME'])));
error_log("Using {$root}/config.php");
require_once($root."/config.php");
}
else
{
// If not, assume the cwd is not symlinked and proceed as we are used to
require_once("../../config.php");
}
global $DB;
global $CFG;
const BADGE_SIZE = 100;
// Do sanity and access checks on course
$courseid = required_param('courseid', PARAM_INT);
$COURSE = get_course($courseid);
$coursecontext = context_course::instance($courseid);
$skill = block_gradelevel_levelset::find_by_course($courseid);
require_login($COURSE);
require_capability('block/gradelevel:viewresults', $coursecontext);
$PAGE->set_url('/blocks/gradelevel/view-results.php', array('courseid' => $courseid));
$PAGE->set_pagelayout('standard');
$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init');
print $OUTPUT->header();
print $OUTPUT->heading(get_string('results_heading', 'block_gradelevel') . " " . $skill->getName());
print "<p>".get_string('course', 'core')." " . $COURSE->fullname."</p>";
//retrieve groups
$course_groups = groups_get_all_groups($COURSE->id);
// retrieve users
$remaining_users = get_enrolled_users($coursecontext);
print "<div class='block_gradelevel_results'>";
if(count($course_groups > 0))
{
// loop through all groups first
foreach($course_groups as $grp)
{
// Get members
$members = get_enrolled_users($coursecontext,'mod/assignment:submit',$grp->id);
$count_members = count($members);
// show group name
print $OUTPUT->heading($grp->name." ({$count_members})",4,array('groupname'));
// Sort on last name
usort( $members, function( $a, $b) {
return ( $a->lastname < $b->lastname ) ? -1 : 1;
} );
print "<ul class='skill_results'>";
foreach($members as $usr)
{
$pointstotal = $skill->get_levelset_grade($usr->id);
$level_info = $skill->calculate_level($pointstotal);
print "<li class='result_badge'>";
print $skill->render_badge($pointstotal,BADGE_SIZE);
print "<figcaption><span class='namepart'>{$usr->firstname}</span> <span class='namepart'>{$usr->lastname}</span></figcaption>";
print "<div class='pointinfo'>".get_string('levelup_at','block_gradelevel')." <span class='currentpoints'>{$level_info->points_in_level}</span>/<span class='leveluppoints'>{$level_info->levelup_total}</span></div>";
print "</li>";
unset($remaining_users[$usr->id]);
}
print "</ul>";
}
$count_members = count($remaining_users);
print $OUTPUT->heading(get_string('results_ungrouped','block_gradelevel')." ({$count_members})" ,4,array('groupname'));
}
usort( $remaining_users, function( $a, $b) {
return ( $a->lastname < $b->lastname ) ? -1 : 1;
} );
print "<ul class='skill_results other'>";
foreach($remaining_users as $usr)
{
$pointstotal = $skill->get_levelset_grade($usr->id);
$level_info = $skill->calculate_level($pointstotal);
print "<li class='result_badge'>";
print $skill->render_badge($pointstotal,BADGE_SIZE);
print "<figcaption><span class='namepart'>{$usr->firstname}</span> <span class='namepart'>{$usr->lastname}</span></figcaption>";
print "<div class='pointinfo'>".get_string('levelup_at','block_gradelevel')." <span class='currentpoints'>{$level_info->points_in_level}</span>/<span class='leveluppoints'>{$level_info->levelup_total}</span></div>";
print "</li>";
}
print "</ul>";
print "</div>";
print $OUTPUT->footer();