Finished level management
On assigning the block to a course, a skill needs to be selected in the config, instead of creating a new skill by default
This commit is contained in:
parent
6b16559201
commit
fa285134cb
52
amd/src/debugger.js
Normal file
52
amd/src/debugger.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*eslint no-var: "error"*/
|
||||||
|
/*eslint no-console: "off"*/
|
||||||
|
/*eslint-env es6*/
|
||||||
|
// Put this file in path/to/plugin/amd/src
|
||||||
|
// You can call it anything you like
|
||||||
|
|
||||||
|
define([], function () {
|
||||||
|
|
||||||
|
return (function (name) {
|
||||||
|
let handle = name;
|
||||||
|
let output_enabled = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
write: function debugger_write() {
|
||||||
|
if (output_enabled) {
|
||||||
|
let args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(handle + ": ");
|
||||||
|
console.info.apply(console, args);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
info: function debugger_info() {
|
||||||
|
if (output_enabled) {
|
||||||
|
let args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(handle + ": ");
|
||||||
|
console.info.apply(console, args);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
warn: function debugger_warn() {
|
||||||
|
if (output_enabled) {
|
||||||
|
let args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(handle + ": ");
|
||||||
|
console.warn.apply(console, args);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function debugger_error() {
|
||||||
|
if (output_enabled) {
|
||||||
|
let args = Array.prototype.slice.call(arguments);
|
||||||
|
args.unshift(handle + ": ");
|
||||||
|
console.error.apply(console, args);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enable: function debugger_enable() {
|
||||||
|
output_enabled = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
disable: function debugger_disable() {
|
||||||
|
output_enabled = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
22
amd/src/handlers.js
Normal file
22
amd/src/handlers.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*eslint no-var: "error"*/
|
||||||
|
/*eslint no-console: "off"*/
|
||||||
|
/*eslint-env es6*/
|
||||||
|
// Put this file in path/to/plugin/amd/src
|
||||||
|
// You can call it anything you like
|
||||||
|
|
||||||
|
define([], function () {
|
||||||
|
let debug_enabled = false;
|
||||||
|
|
||||||
|
let self = {
|
||||||
|
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;
|
||||||
|
});
|
235
amd/src/jquery.animate-shadow.js
Normal file
235
amd/src/jquery.animate-shadow.js
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/**!
|
||||||
|
* @preserve Shadow animation 1.11
|
||||||
|
* http://www.bitstorm.org/jquery/shadow-animation/
|
||||||
|
* Copyright 2011, 2013 Edwin Martin
|
||||||
|
* Contributors: Mark Carver, Xavier Lepretre and Jason Redding
|
||||||
|
* Released under the MIT and GPL licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(['jquery'], function (jQuery) {
|
||||||
|
|
||||||
|
return jQuery(function($, undefined) {
|
||||||
|
/**
|
||||||
|
* Check whether the browser supports RGBA color mode.
|
||||||
|
*
|
||||||
|
* Author Mehdi Kabab <http://pioupioum.fr>
|
||||||
|
* @return {boolean} True if the browser support RGBA. False otherwise.
|
||||||
|
*/
|
||||||
|
function isRGBACapable() {
|
||||||
|
var $script = $('script:first'),
|
||||||
|
color = $script.css('color'),
|
||||||
|
result = false;
|
||||||
|
if (/^rgba/.test(color)) {
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
result = (color !== $script.css('color', 'rgba(0, 0, 0, 0.5)').css('color'));
|
||||||
|
$script.css('color', color);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$script.removeAttr('style');
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.extend(true, $, {
|
||||||
|
support: {
|
||||||
|
'rgba': isRGBACapable()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*************************************/
|
||||||
|
|
||||||
|
// First define which property to use
|
||||||
|
var styles = $('html').prop('style');
|
||||||
|
var boxShadowProperty;
|
||||||
|
$.each(['boxShadow', 'MozBoxShadow', 'WebkitBoxShadow'], function(i, property) {
|
||||||
|
var val = styles[property];
|
||||||
|
if (typeof val !== 'undefined') {
|
||||||
|
boxShadowProperty = property;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extend the animate-function
|
||||||
|
if (boxShadowProperty) {
|
||||||
|
$['Tween']['propHooks']['boxShadow'] = {
|
||||||
|
get: function(tween) {
|
||||||
|
return $(tween.elem).css(boxShadowProperty);
|
||||||
|
},
|
||||||
|
set: function(tween) {
|
||||||
|
var style = tween.elem.style;
|
||||||
|
var p_begin = parseShadows($(tween.elem)[0].style[boxShadowProperty] || $(tween.elem).css(boxShadowProperty));
|
||||||
|
var p_end = parseShadows(tween.end);
|
||||||
|
var maxShadowCount = Math.max(p_begin.length, p_end.length);
|
||||||
|
var i;
|
||||||
|
for(i = 0; i < maxShadowCount; i++) {
|
||||||
|
p_end[i] = $.extend({}, p_begin[i], p_end[i]);
|
||||||
|
if (p_begin[i]) {
|
||||||
|
if (!('color' in p_begin[i]) || $.isArray(p_begin[i].color) === false) {
|
||||||
|
p_begin[i].color = p_end[i].color || [0, 0, 0, 0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p_begin[i] = parseShadows('0 0 0 0 rgba(0,0,0,0)')[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tween['run'] = function(progress) {
|
||||||
|
var rs = calculateShadows(p_begin, p_end, progress);
|
||||||
|
style[boxShadowProperty] = rs;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate an in-between shadow.
|
||||||
|
function calculateShadows(beginList, endList, pos) {
|
||||||
|
var shadows = [];
|
||||||
|
$.each(beginList, function(i) {
|
||||||
|
var parts = [], begin = beginList[i], end = endList[i];
|
||||||
|
|
||||||
|
if (begin.inset) {
|
||||||
|
parts.push('inset');
|
||||||
|
}
|
||||||
|
if (typeof end.left !== 'undefined') {
|
||||||
|
parts.push(parseFloat(begin.left + pos * (end.left - begin.left)) + 'px '
|
||||||
|
+ parseFloat(begin.top + pos * (end.top - begin.top)) + 'px');
|
||||||
|
}
|
||||||
|
if (typeof end.blur !== 'undefined') {
|
||||||
|
parts.push(parseFloat(begin.blur + pos * (end.blur - begin.blur)) + 'px');
|
||||||
|
}
|
||||||
|
if (typeof end.spread !== 'undefined') {
|
||||||
|
parts.push(parseFloat(begin.spread + pos * (end.spread - begin.spread)) + 'px');
|
||||||
|
}
|
||||||
|
if (typeof end.color !== 'undefined') {
|
||||||
|
var color = 'rgb' + ($.support['rgba'] ? 'a' : '') + '('
|
||||||
|
+ 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[2] + pos * (end.color[2] - begin.color[2])), 10);
|
||||||
|
if ($.support['rgba']) {
|
||||||
|
color += ',' + parseFloat(begin.color[3] + pos * (end.color[3] - begin.color[3]));
|
||||||
|
}
|
||||||
|
color += ')';
|
||||||
|
parts.push(color);
|
||||||
|
}
|
||||||
|
shadows.push(parts.join(' '));
|
||||||
|
});
|
||||||
|
return shadows.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the shadow value and extract the values.
|
||||||
|
function parseShadows(shadow) {
|
||||||
|
var parsedShadows = [];
|
||||||
|
var parsePosition = 0;
|
||||||
|
var parseLength = shadow.length;
|
||||||
|
|
||||||
|
function findInset() {
|
||||||
|
var m = /^inset\b/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsedShadow.inset = true;
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function findOffsets() {
|
||||||
|
var m = /^(-?[0-9\.]+)(?:px)?\s+(-?[0-9\.]+)(?:px)?(?:\s+(-?[0-9\.]+)(?:px)?)?(?:\s+(-?[0-9\.]+)(?:px)?)?/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsedShadow.left = parseInt(m[1], 10);
|
||||||
|
parsedShadow.top = parseInt(m[2], 10);
|
||||||
|
parsedShadow.blur = (m[3] ? parseInt(m[3], 10) : 0);
|
||||||
|
parsedShadow.spread = (m[4] ? parseInt(m[4], 10) : 0);
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function findColor() {
|
||||||
|
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) {
|
||||||
|
parsedShadow.color = [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16), 1];
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m = /^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsedShadow.color = [parseInt(m[1], 16) * 17, parseInt(m[2], 16) * 17, parseInt(m[3], 16) * 17, 1];
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m = /^rgb\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), 1];
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
m = /^rgba\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsedShadow.color = [parseInt(m[1], 10), parseInt(m[2], 10), parseInt(m[3], 10), parseFloat(m[4])];
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function findWhiteSpace() {
|
||||||
|
var m = /^\s+/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function findComma() {
|
||||||
|
var m = /^\s*,\s*/.exec(shadow.substring(parsePosition));
|
||||||
|
if (m !== null && m.length > 0) {
|
||||||
|
parsePosition += m[0].length;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function normalizeShadow(shadow) {
|
||||||
|
if ($.isPlainObject(shadow)) {
|
||||||
|
var i, sColor, cLength = 0, color = [];
|
||||||
|
if ($.isArray(shadow.color)) {
|
||||||
|
sColor = shadow.color;
|
||||||
|
cLength = sColor.length;
|
||||||
|
}
|
||||||
|
for(i = 0; i < 4; i++) {
|
||||||
|
if (i < cLength) {
|
||||||
|
color.push(sColor[i]);
|
||||||
|
} else if (i === 3) {
|
||||||
|
color.push(1);
|
||||||
|
} else {
|
||||||
|
color.push(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $.extend({
|
||||||
|
'left': 0,
|
||||||
|
'top': 0,
|
||||||
|
'blur': 0,
|
||||||
|
'spread': 0
|
||||||
|
}, shadow);
|
||||||
|
}
|
||||||
|
var parsedShadow = normalizeShadow();
|
||||||
|
|
||||||
|
while (parsePosition < parseLength) {
|
||||||
|
if (findInset()) {
|
||||||
|
findWhiteSpace();
|
||||||
|
} else if (findOffsets()) {
|
||||||
|
findWhiteSpace();
|
||||||
|
} else if (findColor()) {
|
||||||
|
findWhiteSpace();
|
||||||
|
} else if (findComma()) {
|
||||||
|
parsedShadows.push(normalizeShadow(parsedShadow));
|
||||||
|
parsedShadow = {};
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsedShadows.push(normalizeShadow(parsedShadow));
|
||||||
|
return parsedShadows;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -18,7 +18,7 @@ define([], function () {
|
||||||
//if (!window.jscolor) { window.jscolor = (function () {
|
//if (!window.jscolor) { window.jscolor = (function () {
|
||||||
return (function () {
|
return (function () {
|
||||||
|
|
||||||
console.info("Initializing JSColor");
|
//console.info("Initializing JSColor");
|
||||||
|
|
||||||
var jsc = {
|
var jsc = {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
|
/*eslint no-var: "error"*/
|
||||||
|
/*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', 'block_gradelevel/jscolor'], function ($, str, ajax, jscolor) {
|
define(['jquery', 'block_gradelevel/jquery.animate-shadow', 'core/str', 'core/ajax', 'block_gradelevel/jscolor',
|
||||||
|
'block_gradelevel/handlers', 'block_gradelevel/debugger'], function ($, $shadow, str, ajax, jscolor, handlers, Debugger) {
|
||||||
|
|
||||||
|
let debug = new Debugger("leveleditor");
|
||||||
|
debug.enable();
|
||||||
|
|
||||||
let skill_id = null;
|
let skill_id = null;
|
||||||
let $skill_table = null;
|
let $skill_table = null;
|
||||||
|
|
||||||
|
@ -13,15 +20,12 @@ define(['jquery', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function
|
||||||
skill_id = Number($skill_table.attr('data-skill'));
|
skill_id = Number($skill_table.attr('data-skill'));
|
||||||
|
|
||||||
if (!skill_id && skill_id !== 0 && skill_id !== '0') {
|
if (!skill_id && skill_id !== 0 && skill_id !== '0') {
|
||||||
console.error("Cannot find configured skill id");
|
debug.error("Cannot find configured skill id");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// load and fill the level table
|
|
||||||
self.refresh();
|
|
||||||
|
|
||||||
// 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('change', "input[type=number].uint", function (evt) {
|
$(document).on('input', "input[type=number].uint", function (evt) {
|
||||||
let $this = $(this);
|
let $this = $(this);
|
||||||
if ($this.val() < 0) {
|
if ($this.val() < 0) {
|
||||||
$this.val(0);
|
$this.val(0);
|
||||||
|
@ -35,6 +39,8 @@ define(['jquery', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function
|
||||||
|
|
||||||
// On click handler for save changes button
|
// On click handler for save changes button
|
||||||
$("button[data-action=savechanges]").on('click', self.submit);
|
$("button[data-action=savechanges]").on('click', self.submit);
|
||||||
|
// On click handler for save changes button
|
||||||
|
$("button[data-action=resetlevels]").on('click', self.resetlevels);
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -53,7 +59,7 @@ define(['jquery', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function
|
||||||
$skill_table.find("tbody").append($newtr);
|
$skill_table.find("tbody").append($newtr);
|
||||||
},
|
},
|
||||||
refresh: function refresh() {
|
refresh: function refresh() {
|
||||||
console.info("Attempting to refresh");
|
debug.info("Attempting to refresh");
|
||||||
|
|
||||||
// perform refresh call
|
// perform refresh call
|
||||||
let promises = ajax.call([{
|
let promises = ajax.call([{
|
||||||
|
@ -82,7 +88,7 @@ define(['jquery', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function
|
||||||
level_data.push(row);
|
level_data.push(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
//console.info("Attempting to submit", level_data);
|
//debug.info("Attempting to submit", level_data);
|
||||||
|
|
||||||
// perform ajax call
|
// perform ajax call
|
||||||
let promises = ajax.call([{
|
let promises = ajax.call([{
|
||||||
|
@ -91,27 +97,54 @@ define(['jquery', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
// and link promise returns to callbacks
|
// and link promise returns to callbacks
|
||||||
promises[0].done(self.success_refill_table).fail(self.fail_report_exception);
|
promises[0].done(self.success_refill_table).fail(handlers.fail_report_exception);
|
||||||
|
},
|
||||||
|
resetlevels: function resetlevels(evt) {
|
||||||
|
let $table = $("table#level_config");
|
||||||
|
|
||||||
|
// Send a request to delete all rows
|
||||||
|
let level_data = [];
|
||||||
|
$table.find("tbody tr[data-rowid]").each(function () {
|
||||||
|
let $this = $(this);
|
||||||
|
let row = {
|
||||||
|
id: Number($this.attr('data-rowid')),
|
||||||
|
points: -255, // means: delete row
|
||||||
|
badgecolor: "", // totally irrelevent when requesting a delete
|
||||||
|
}
|
||||||
|
|
||||||
|
level_data.push(row);
|
||||||
|
});
|
||||||
|
|
||||||
|
//debug.info("Attempting to submit", level_data);
|
||||||
|
|
||||||
|
// perform ajax call
|
||||||
|
let promises = ajax.call([{
|
||||||
|
methodname: 'block_gradelevel_submit_levels',
|
||||||
|
args: { skill_id: skill_id, levels: level_data },
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// and link promise returns to callbacks
|
||||||
|
promises[0].done(self.success_refill_table).fail(handlers.fail_report_exception);
|
||||||
},
|
},
|
||||||
success_refill_table: function success_refill_table(response) {
|
success_refill_table: function success_refill_table(response) {
|
||||||
//console.info("Response from webservice: ", response);
|
//debug.info("Response from webservice: ", response);
|
||||||
let $tbody = $skill_table.find('tbody');
|
let $tbody = $skill_table.find('tbody');
|
||||||
$tbody.empty();
|
$tbody.empty();
|
||||||
for (let idx in response) {
|
for (let idx in response) {
|
||||||
let lvl = response[idx];
|
let lvl = response[idx];
|
||||||
//console.info("Level:", lvl);
|
//debug.info("Level:", lvl);
|
||||||
self.add_levelrow(lvl.id, lvl.points, lvl.badgecolor);
|
self.add_levelrow(lvl.id, lvl.points, lvl.badgecolor);
|
||||||
}
|
}
|
||||||
|
let $inputs = $tbody.find("input[data-name='points']");
|
||||||
|
|
||||||
|
let orig_border = $inputs.css('border-left-color');
|
||||||
|
$inputs
|
||||||
|
.animate({ boxShadow: '0px 0px 5px 3px #3FDFCF'}, 400)
|
||||||
|
.delay(200)
|
||||||
|
.animate({ boxShadow: 'none'}, 800);
|
||||||
|
|
||||||
},
|
},
|
||||||
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;
|
||||||
|
|
|
@ -1,23 +1,39 @@
|
||||||
|
/*eslint no-var: "error"*/
|
||||||
|
/*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'], function ($, str, ajax) {
|
define(['jquery', 'core/str', 'core/ajax','block_gradelevel/debugger' ], function ($, str, ajax, Debugger) {
|
||||||
|
let debug = Debugger("renderbadge");
|
||||||
|
//debug.enable();
|
||||||
|
|
||||||
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 () {
|
||||||
let props = self.fetchProperties(this);
|
self.setup_badge(this,true);
|
||||||
let $this = $(this);
|
|
||||||
let $canvas = $("<canvas height= '"+props.height +"' width = '"+props.width+"'/>");
|
|
||||||
//console.info("$canvas", $canvas, $canvas[0]);
|
|
||||||
$('canvas', this).remove();// clear out any existing canvas
|
|
||||||
$this.append($canvas); // Put the canvas in there
|
|
||||||
self.render($canvas[0], props);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
setup_badge: function setup_Badge(figure, allowskip) {
|
||||||
|
let $figure = $(figure);
|
||||||
|
let props = $(figure).data('badge-props');
|
||||||
|
debug.info("Setting up skill badge on ", figure, props);
|
||||||
|
if (props && allowskip) {
|
||||||
|
debug.info(" skill badge was already configured. Skipping process...");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
props = self.fetchProperties(figure);
|
||||||
|
let $canvas = $("<canvas height= '" + props.height + "' width = '" + props.width + "'/>");
|
||||||
|
$('canvas', figure).remove();// clear out any existing canvas
|
||||||
|
$figure.append($canvas); // Put the new canvas in there
|
||||||
|
self.render($canvas[0], props);
|
||||||
|
// Store properties
|
||||||
|
$figure.data("badge-props", props);
|
||||||
|
}
|
||||||
|
},
|
||||||
render: function render(canvas, props) {
|
render: function render(canvas, props) {
|
||||||
let ctx = canvas.getContext("2d");
|
let ctx = canvas.getContext("2d");
|
||||||
// Color configuration
|
// Color configuration
|
||||||
|
@ -61,9 +77,9 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
|
||||||
scale: 0.7, // scale to this fraction of image size
|
scale: 0.7, // scale to this fraction of image size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//console.info("Config", config);
|
debug.info(" Config", config);
|
||||||
//console.info("Colors", colors);
|
debug.info(" Colors", colors);
|
||||||
//console.info("Props", props);
|
debug.info(" Props", props);
|
||||||
|
|
||||||
// draw main circle
|
// draw main circle
|
||||||
let baseGradient = ctx.createRadialGradient(
|
let baseGradient = ctx.createRadialGradient(
|
||||||
|
@ -72,7 +88,7 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
|
||||||
(config.size ) * colors.radialGradient.r0,
|
(config.size ) * colors.radialGradient.r0,
|
||||||
config.size * colors.radialGradient.x1,
|
config.size * colors.radialGradient.x1,
|
||||||
config.size * colors.radialGradient.y1,
|
config.size * colors.radialGradient.y1,
|
||||||
(config.size ) * colors.radialGradient.r1,
|
(config.size ) * colors.radialGradient.r1
|
||||||
);
|
);
|
||||||
baseGradient.addColorStop(0, colors.lightPoint);
|
baseGradient.addColorStop(0, colors.lightPoint);
|
||||||
baseGradient.addColorStop(1, colors.base);
|
baseGradient.addColorStop(1, colors.base);
|
||||||
|
@ -157,9 +173,9 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
|
||||||
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, 15, 15, 120, 120);//imPos.x, imPos.y, imPos.w, imPos.h);
|
ctx.drawImage(this, imPos.x, imPos.y, imPos.w, imPos.h);
|
||||||
}
|
}
|
||||||
//console.info("Image: ",props.image);
|
//debug.info("Image: ",props.image);
|
||||||
iconImg.src = props.image;
|
iconImg.src = props.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
196
amd/src/skilleditor.js
Normal file
196
amd/src/skilleditor.js
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/*eslint no-var: "error"*/
|
||||||
|
/*eslint-env es6*/
|
||||||
|
// Put this file in path/to/plugin/amd/src
|
||||||
|
// You can call it anything you like
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
let debug = Debugger("skilleditor");
|
||||||
|
debug.enable();
|
||||||
|
|
||||||
|
let $skillset_div = null;
|
||||||
|
const uploadFilter = ".png,.svg";
|
||||||
|
|
||||||
|
let self = {
|
||||||
|
init: function init() {
|
||||||
|
// Find skill table and skill id
|
||||||
|
$skillset_div = $("div#skill_set");
|
||||||
|
// Run initialization code on all items.
|
||||||
|
debug.info("Initializing editors");
|
||||||
|
$skillset_div.find("li.skill_info").each(function () {
|
||||||
|
self.initialize_item(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
debug.info("Attaching function to addskill link");
|
||||||
|
$skillset_div.find("a[data-action='addskill']").on('click', function (ev) {
|
||||||
|
let promises = ajax.call([{
|
||||||
|
methodname: 'block_gradelevel_add_skill',
|
||||||
|
args: { name: null, icon: null },
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// and link promise returns to callbacks
|
||||||
|
promises[0].fail(handlers.fail_report_exception).done(function (data) {
|
||||||
|
let $newskill = $(data.html);
|
||||||
|
$skillset_div.find('ul').append($newskill);
|
||||||
|
$newskill.each(function () {
|
||||||
|
self.initialize_item(this);
|
||||||
|
});
|
||||||
|
$newskill.find('figure.levelbadge').each(function () {
|
||||||
|
renderbadge.setup_badge(this);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
initialize_item: function initialize_item(li) {
|
||||||
|
let $li = $(li);
|
||||||
|
let skill_id = $li.data('id');
|
||||||
|
|
||||||
|
// Attach edit name pencil
|
||||||
|
$li.find("a[data-action='editname']").on('click', function (evt) {
|
||||||
|
let $span = $li.find("figcaption span[data-type='label']");
|
||||||
|
if ($span.length > 0) {
|
||||||
|
let name = $span.text();
|
||||||
|
let $input = $("<input type='text'/>").val(name);// value='" + name + "' />");
|
||||||
|
|
||||||
|
$span.replaceWith($input);
|
||||||
|
$input.on("keyup", function input_keypress(e) {
|
||||||
|
let keycode = (e.keyCode ? e.keyCode : e.which);
|
||||||
|
if (keycode == '13') {
|
||||||
|
debug.info("Saving name");
|
||||||
|
// save the new name
|
||||||
|
let new_name = $input.val();
|
||||||
|
|
||||||
|
let promises = ajax.call([{
|
||||||
|
methodname: 'block_gradelevel_update_skill',
|
||||||
|
args: { id: skill_id, name: new_name, icon: null },
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// and link promise returns to callbacks
|
||||||
|
promises[0].fail(handlers.fail_report_exception).done(function (data) {
|
||||||
|
$input.replaceWith($("<span data-type='label'>" + data.name + "</span>"));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
if (keycode == '27') {
|
||||||
|
debug.info("Cancelled editing");
|
||||||
|
$input.replaceWith($("<span data-type='label'>" + name + "</span>"));
|
||||||
|
}
|
||||||
|
}).on("focusout", function input_cancel(e) {
|
||||||
|
debug.info("Cancelled editing");
|
||||||
|
$input.replaceWith($("<span data-type='label'>" + name + "</span>"));
|
||||||
|
});
|
||||||
|
$input.focus();
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let $textinput = $li.find("figurecaption input[type=text]");
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attach edit icon pencil
|
||||||
|
$li.find("a[data-action='editicon']").on('click', function (ev) {
|
||||||
|
let $uploader = $("<input type='file' style='display: none;' accept='" + uploadFilter + "'/>");
|
||||||
|
|
||||||
|
$uploader.on('change', function (ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
let file = ev.originalEvent.target.files[0];
|
||||||
|
let fr = new FileReader();
|
||||||
|
$(fr).on('load', function (ev) {
|
||||||
|
let dataURI = ev.target.result;
|
||||||
|
|
||||||
|
let promises = ajax.call([{
|
||||||
|
methodname: 'block_gradelevel_update_skill',
|
||||||
|
args: { id: skill_id, name: null, icon: dataURI },
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// and link promise returns to callbacks
|
||||||
|
promises[0].fail(handlers.fail_report_exception).done(function (data) {
|
||||||
|
|
||||||
|
let $figure = $li.find("figure.levelbadge");
|
||||||
|
|
||||||
|
$figure.empty();
|
||||||
|
$figure.append($("<img style='display:none;' src='"+data.icon+"'/>"));
|
||||||
|
|
||||||
|
$figure.each(function () {
|
||||||
|
renderbadge.setup_badge(this);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$uploader.remove(); // delete the uploader after it's done
|
||||||
|
});
|
||||||
|
fr.readAsDataURL(file);
|
||||||
|
|
||||||
|
});
|
||||||
|
$li.append($uploader);
|
||||||
|
$uploader.trigger('click');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Attach edit levels link
|
||||||
|
$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
|
||||||
|
$li.find("a[data-action='deleteskill']").each(function () {
|
||||||
|
let $trigger = $(this);
|
||||||
|
// Attach delete button code
|
||||||
|
ModalFactory.create({
|
||||||
|
type: ModalFactory.types.SAVE_CANCEL,
|
||||||
|
title: str.get_string('title_confirmdelete', 'block_gradelevel'),
|
||||||
|
body: str.get_string('dialog_confirmdeleteskill', 'block_gradelevel'),
|
||||||
|
}, $trigger).done(function (modal) {
|
||||||
|
// Do what you want with your new modal.
|
||||||
|
debug.info("Modal done", modal);
|
||||||
|
modal.setSaveButtonText(str.get_string('delete', 'core'));
|
||||||
|
modal.getRoot().on(ModalEvents.save, function (e) {
|
||||||
|
debug.info("Delete Confirmed");
|
||||||
|
//e.preventDefault(); if you don't want to close the window
|
||||||
|
|
||||||
|
// call the delete function
|
||||||
|
let promises = ajax.call([{
|
||||||
|
methodname: 'block_gradelevel_delete_skill',
|
||||||
|
args: { id: skill_id},
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// and link promise returns to callbacks
|
||||||
|
promises[0].fail(handlers.fail_report_exception).done(function (data) {
|
||||||
|
|
||||||
|
if (data.deleted) {
|
||||||
|
$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;
|
||||||
|
});
|
|
@ -24,13 +24,6 @@ class block_gradelevel extends block_base {
|
||||||
|
|
||||||
// find or create the levelset for this course
|
// find or create the levelset for this course
|
||||||
$this->levelset = block_gradelevel_levelset::find_by_course($COURSE->id);
|
$this->levelset = block_gradelevel_levelset::find_by_course($COURSE->id);
|
||||||
if(empty($this->levelset))
|
|
||||||
{
|
|
||||||
// create a new levelset with the name of this course and attach
|
|
||||||
$this->levelset = block_gradelevel_levelset::create_new($COURSE->shortname);
|
|
||||||
$this->levelset->attach_course($COURSE->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The PHP tag and the curly bracket for the class definition
|
// The PHP tag and the curly bracket for the class definition
|
||||||
|
@ -43,6 +36,7 @@ class block_gradelevel extends block_base {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_content() {
|
public function get_content() {
|
||||||
|
global $CFG;
|
||||||
global $USER;
|
global $USER;
|
||||||
global $COURSE;
|
global $COURSE;
|
||||||
|
|
||||||
|
@ -52,28 +46,34 @@ class block_gradelevel extends block_base {
|
||||||
|
|
||||||
$this->content = new stdClass;
|
$this->content = new stdClass;
|
||||||
|
|
||||||
// below can be a single call to $this->levelset->get_user_leveldata() once the need for debugging (fixed point total) is gone
|
if(empty($this->levelset))
|
||||||
$pointstotal = $this->levelset->get_levelset_grade($USER->id);
|
{
|
||||||
$level_info = $this->levelset->calculate_level($pointstotal);
|
$this->content->text = "<figure class='dummybadge'><img height='150px' width='150px' src='{$CFG->wwwroot}/blocks/gradelevel/pix/brokenbadge.svg' /></figure>";
|
||||||
|
$this->content->footer = get_string("unattached_course",'block_gradelevel');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// below can be a single call to $this->levelset->get_user_leveldata() once the need for debugging (fixed point total) is gone
|
||||||
|
$pointstotal = $this->levelset->get_levelset_grade($USER->id);
|
||||||
|
$level_info = $this->levelset->calculate_level($pointstotal);
|
||||||
|
|
||||||
$this->content->text = $this->levelset->render_badge($pointstotal);
|
$this->content->text = $this->levelset->render_badge($pointstotal);
|
||||||
|
|
||||||
if($level_info->levelup_total > 0)
|
if($level_info->levelup_total > 0)
|
||||||
{
|
{
|
||||||
$this->content->footer = "<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>";
|
$this->content->footer = "<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>";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$this->content->footer = "<div class='pointinfo complete'>".get_string('levelup_done','block_gradelevel')."</div>";
|
$this->content->footer = "<div class='pointinfo complete'>".get_string('levelup_done','block_gradelevel')."</div>";
|
||||||
}
|
}
|
||||||
|
|
||||||
$coursecontext = context_course::instance($COURSE->id);
|
$coursecontext = context_course::instance($COURSE->id);
|
||||||
|
|
||||||
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='#'>".get_string('teacher_view_results','block_gradelevel')."</a></div>";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return $this->content;
|
return $this->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
48
cfg_skilllevels.php
Normal file
48
cfg_skilllevels.php
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// HOW DID WE ENSURE ONLY ADMINS CAN VIEW THIS PAGE?
|
||||||
|
|
||||||
|
require_once($CFG->libdir.'/adminlib.php');
|
||||||
|
|
||||||
|
|
||||||
|
admin_externalpage_setup("block_gradelevel_config_skills");
|
||||||
|
|
||||||
|
|
||||||
|
$skill_id = required_param('skill_id', PARAM_INT);
|
||||||
|
|
||||||
|
$systemcontext = context_system::instance();
|
||||||
|
// Check if user has capability to manage skills
|
||||||
|
require_capability('block/gradelevel:skillmanager', $systemcontext);
|
||||||
|
|
||||||
|
$skill = block_gradelevel_levelset::find_by_id($skill_id);
|
||||||
|
|
||||||
|
$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init');
|
||||||
|
$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init');
|
||||||
|
$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init');
|
||||||
|
|
||||||
|
print $OUTPUT->header();
|
||||||
|
|
||||||
|
// render skill editor
|
||||||
|
print $OUTPUT->heading(get_string('cfgpage_editskill','block_gradelevel')." ".$skill->getName());
|
||||||
|
print block_gradelevel_skillmgmtservice::render_skill_editor($skill_id);
|
||||||
|
|
||||||
|
// render level editor
|
||||||
|
print $OUTPUT->heading(get_string('cfgpage_skilllevels','block_gradelevel'));
|
||||||
|
print block_gradelevel_skillmgmtservice::render_leveltable($skill_id);
|
||||||
|
|
||||||
|
// add back button to return to skill management page
|
||||||
|
$cfg_skills_url = $CFG->wwwroot."/blocks/gradelevel/cfg_skills.php";
|
||||||
|
print "<button onclick='window.location=\"{$cfg_skills_url}\";'>".get_string('back','core')."</button>";
|
||||||
|
print $OUTPUT->footer();
|
35
cfg_skills.php
Normal file
35
cfg_skills.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// HOW DID WE ENSURE ONLY ADMINS CAN VIEW THIS PAGE?
|
||||||
|
|
||||||
|
require_once($CFG->libdir.'/adminlib.php');
|
||||||
|
|
||||||
|
|
||||||
|
admin_externalpage_setup("block_gradelevel_config_skills");
|
||||||
|
|
||||||
|
$systemcontext = context_system::instance();
|
||||||
|
// Check if user has capability to manage skills
|
||||||
|
require_capability('block/gradelevel:skillmanager', $systemcontext);
|
||||||
|
|
||||||
|
|
||||||
|
$PAGE->requires->js_call_amd('block_gradelevel/skilleditor', 'init');
|
||||||
|
$PAGE->requires->js_call_amd('block_gradelevel/renderbadge', 'init');
|
||||||
|
|
||||||
|
print $OUTPUT->header();
|
||||||
|
print $OUTPUT->heading(get_string('cfgpage_skills', 'block_gradelevel'));
|
||||||
|
|
||||||
|
// render page for skill level 0 (global)
|
||||||
|
print block_gradelevel_skillmgmtservice::render_skill_list(0);
|
||||||
|
print $OUTPUT->footer();
|
|
@ -141,9 +141,11 @@ class block_gradelevel_levelset {
|
||||||
return null; // return null if no current levelset linked
|
return null; // return null if no current levelset linked
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function find_by_id($id)
|
static public function find_by_id(int $id)
|
||||||
{
|
{
|
||||||
$levelset = $DB->get_record('block_gradelevel_levelset', array('id' => array_values($records)[0]->levelset_id));
|
global $DB;
|
||||||
|
|
||||||
|
$levelset = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
|
||||||
if($levelset)
|
if($levelset)
|
||||||
{
|
{
|
||||||
return new static($levelset->id,$levelset);
|
return new static($levelset->id,$levelset);
|
||||||
|
@ -397,7 +399,6 @@ class block_gradelevel_levelset {
|
||||||
// If we have levels defined, use those, otherwise use the global levels
|
// If we have levels defined, use those, otherwise use the global levels
|
||||||
if(!empty($this->levels))
|
if(!empty($this->levels))
|
||||||
{
|
{
|
||||||
print ("EXSTING_LEVELS");
|
|
||||||
if(array_values($this->levels)[0]->points > 0)
|
if(array_values($this->levels)[0]->points > 0)
|
||||||
{
|
{
|
||||||
// insert level 0
|
// insert level 0
|
||||||
|
@ -411,16 +412,13 @@ class block_gradelevel_levelset {
|
||||||
if(!empty($lvl->badgecolor)) {
|
if(!empty($lvl->badgecolor)) {
|
||||||
$color = $lvl->badgecolor;
|
$color = $lvl->badgecolor;
|
||||||
}
|
}
|
||||||
elseif(isset($this->global_levels[$i]))
|
|
||||||
{
|
|
||||||
$color = $this->global_levels[$i]->badgecolor;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$color = static::UNDEFINED_BADGE_COLOR;
|
$color = static::UNDEFINED_BADGE_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
$level_info[$lvl->points];
|
$level_info[$lvl->points] = $color;
|
||||||
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -458,7 +456,7 @@ class block_gradelevel_levelset {
|
||||||
$info = $this->calculate_level($points);
|
$info = $this->calculate_level($points);
|
||||||
|
|
||||||
$image = $this->getIcon();
|
$image = $this->getIcon();
|
||||||
if(strncmp($image,"data: ",6) != 0)
|
if(strncmp($image,"data:",5) != 0)
|
||||||
{
|
{
|
||||||
$image_url = $CFG->wwwroot.$image;
|
$image_url = $CFG->wwwroot.$image;
|
||||||
}
|
}
|
||||||
|
@ -487,7 +485,7 @@ class block_gradelevel_levelset {
|
||||||
$levels = $this->badgelevels();
|
$levels = $this->badgelevels();
|
||||||
$maxpoints = array_pop(array_keys($levels));
|
$maxpoints = array_pop(array_keys($levels));
|
||||||
|
|
||||||
return $this->render_badge($maxpoints,$size);
|
return $this->render_badge($maxpoints, $size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ require_once($CFG->dirroot.'/grade/querylib.php');
|
||||||
|
|
||||||
class block_gradelevel_skillmgmtservice extends external_api
|
class block_gradelevel_skillmgmtservice extends external_api
|
||||||
{
|
{
|
||||||
const DEBUG = false; // enable debug logging
|
const DEBUG = true; // enable debug logging
|
||||||
const DEMOBADGE_SIZE = 100; // size of demo badge
|
const DEMOBADGE_SIZE = 150; // size of demo badge
|
||||||
|
|
||||||
private static function log($message)
|
private static function log($message)
|
||||||
{
|
{
|
||||||
|
@ -199,28 +199,6 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
$systemcontext = context_system::instance();
|
$systemcontext = context_system::instance();
|
||||||
self::validate_context($systemcontext);
|
self::validate_context($systemcontext);
|
||||||
|
|
||||||
if(skill_id == 0)
|
|
||||||
{
|
|
||||||
// Check if user has capability to manage global levels
|
|
||||||
require_capability('block/gradelevel:managelevels', $systemcontext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if user has teacher or manager capability in any of the attached courses
|
|
||||||
$capability = false;
|
|
||||||
$courses = self::list_courses($skill_id);
|
|
||||||
foreach($courses as $course_id)
|
|
||||||
{
|
|
||||||
$coursecontext = context_course::instance($course_id);
|
|
||||||
$capability |= has_capability('block/gradelevel:changelevels', $coursecontext);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$capability)
|
|
||||||
{
|
|
||||||
throw new Exception("Access denied - you do not have editing capabilities for one of the attached courses");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach($levels as $lvl_raw)
|
foreach($levels as $lvl_raw)
|
||||||
{
|
{
|
||||||
|
@ -273,13 +251,35 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
|
|
||||||
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $skill_id));
|
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $skill_id));
|
||||||
|
|
||||||
// Sort by points
|
if($skill_id == 0 || count($levels) > 0)
|
||||||
usort( $levels, function( $a, $b) {
|
{
|
||||||
return ( $a->points < $b->points ) ? -1 : 1;
|
// If global level, or skills are defined, return those
|
||||||
} );
|
|
||||||
|
// Sort by points
|
||||||
|
usort( $levels, function( $a, $b) {
|
||||||
|
return ( $a->points < $b->points ) ? -1 : 1;
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
return $levels;
|
return $levels;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Else, return a nameless clone of the default levels).
|
||||||
|
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0));
|
||||||
|
|
||||||
|
// Sort by points
|
||||||
|
usort( $levels, function( $a, $b) {
|
||||||
|
return ( $a->points < $b->points ) ? -1 : 1;
|
||||||
|
} );
|
||||||
|
|
||||||
|
foreach($levels as $lvl)
|
||||||
|
{
|
||||||
|
$lvl->id = -255; // replace level id with -255, which is code for "new level" when returned
|
||||||
|
}
|
||||||
|
|
||||||
|
return $levels;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,35 +316,51 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function update_skill(int $id, string $name, string $icon )
|
public static function update_skill(int $id, $name, $icon )
|
||||||
{
|
{
|
||||||
global $CFG, $DB;
|
global $CFG, $DB;
|
||||||
|
|
||||||
$skill = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
|
$skill = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
|
||||||
|
|
||||||
$skill->name = $name;
|
if($name != null){
|
||||||
$skill->icon = $icon;
|
$skill->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($icon != null){
|
||||||
|
$skill->icon = $icon;
|
||||||
|
}
|
||||||
|
|
||||||
$DB->update_record('block_gradelevel_levelset',$skill);
|
$DB->update_record('block_gradelevel_levelset',$skill);
|
||||||
|
|
||||||
|
|
||||||
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
|
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
|
||||||
|
|
||||||
return $skill;
|
return $skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function add_skill(string $name, string $icon)
|
public static function add_skill($name, $icon)
|
||||||
{
|
{
|
||||||
global $CFG, $DB;
|
global $CFG, $DB;
|
||||||
|
|
||||||
$skill = stdObj;
|
$skill = new stdClass;
|
||||||
|
|
||||||
$skill->name = $name;
|
if(empty($name)){
|
||||||
$skill->icon = $icon;
|
$skill->name = get_string('defaults_name','block_gradelevel');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$skill->name = $name;
|
||||||
|
}
|
||||||
|
if(empty($icon)){
|
||||||
|
$skill->icon = "/blocks/gradelevel/pix/undefinedskill.svg";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$skill->icon = $icon;
|
||||||
|
}
|
||||||
|
|
||||||
$id = $DB->insert_record('block_gradelevel_levelset',$skill, true);
|
$id = $DB->insert_record('block_gradelevel_levelset',$skill, true);
|
||||||
|
|
||||||
$skill->id = $id;
|
$skill->id = $id;
|
||||||
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
|
$skill->html = static::single_skill_editor_item(block_gradelevel_levelset::find_by_id($skill->id));
|
||||||
|
|
||||||
return $skill;
|
return $skill;
|
||||||
}
|
}
|
||||||
|
@ -353,10 +369,14 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
{
|
{
|
||||||
global $CFG, $DB;
|
global $CFG, $DB;
|
||||||
|
|
||||||
$result = stdObj;
|
$skill = block_gradelevel_levelset::find_by_id($id);
|
||||||
$result->id = $id;
|
if(count($skill->list_courses()) > 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Cannot delete skills that have courses attached");
|
||||||
|
}
|
||||||
|
|
||||||
$result->id = ($DB->delete_record('block_gradelevel_levelset',array('id' => $id)))?true:false;
|
$result = array('id' => $id);
|
||||||
|
$result['deleted'] = ($DB->delete_records('block_gradelevel_levelset',array('id' => $id)))?true:false;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +388,7 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
$levels = static::list_levels($skill_id);
|
$levels = static::list_levels($skill_id);
|
||||||
|
|
||||||
$s = "<p>".get_string('levelcfg_description','block_gradelevel')."</p>";
|
$s = "<p>".get_string('levelcfg_description','block_gradelevel')."</p>";
|
||||||
$s .= "<table id='level_config' data-skill='{$skill_id}'>";
|
$s .= "<table id='level_config' class='level_config' data-skill='{$skill_id}'>";
|
||||||
$s .= "<thead><tr><th>".get_string('levelcfg_head_points','block_gradelevel')."</th><th>".get_string('levelcfg_head_color','block_gradelevel')."</th></tr></thead>";
|
$s .= "<thead><tr><th>".get_string('levelcfg_head_points','block_gradelevel')."</th><th>".get_string('levelcfg_head_color','block_gradelevel')."</th></tr></thead>";
|
||||||
$s .= "<tbody>";
|
$s .= "<tbody>";
|
||||||
foreach($levels as $lvl)
|
foreach($levels as $lvl)
|
||||||
|
@ -380,7 +400,12 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
$s .= "</tbody>";
|
$s .= "</tbody>";
|
||||||
$s .= "<tfoot><tr><td class='block_gradelevel_addlevel' colspan='2'><a data-action='addlevel' href='#' onclick='return false;'>".get_string("levelcfg_addlevel",'block_gradelevel')."</a></td></td></tfoot>";
|
$s .= "<tfoot><tr><td class='block_gradelevel_addlevel' colspan='2'><a data-action='addlevel' href='#' onclick='return false;'>".get_string("levelcfg_addlevel",'block_gradelevel')."</a></td></td></tfoot>";
|
||||||
$s .= "</table>";
|
$s .= "</table>";
|
||||||
$s .= "<p><button data-action='savechanges'>".get_string('savechanges','core')."</button></p>";
|
$s .= "<p><button data-action='savechanges'>".get_string('savechanges','core')."</button>";
|
||||||
|
if($skill_id > 0)
|
||||||
|
{
|
||||||
|
$s .= " <button data-action='resetlevels'>".get_string('cfg_resetlevels','block_gradelevel')."</button>";
|
||||||
|
}
|
||||||
|
$s .= "</p>";
|
||||||
|
|
||||||
return $s;
|
return $s;
|
||||||
|
|
||||||
|
@ -388,19 +413,61 @@ class block_gradelevel_skillmgmtservice extends external_api
|
||||||
|
|
||||||
public static function render_skill_list()
|
public static function render_skill_list()
|
||||||
{
|
{
|
||||||
|
global $CFG;
|
||||||
$skills = block_gradelevel_levelset::list_all();
|
$skills = block_gradelevel_levelset::list_all();
|
||||||
|
|
||||||
$s = "<div class='skill_set'><ul>";
|
// Sort by points
|
||||||
|
usort( $skills, function( $a, $b) {
|
||||||
|
return ( $a->getName() < $b->getName()) ? -1 : 1;
|
||||||
|
} );
|
||||||
|
|
||||||
|
$s = "<div id='skill_set' class='skill_set'><ul>";
|
||||||
foreach($skills as $skill)
|
foreach($skills as $skill)
|
||||||
{
|
{
|
||||||
$skill_id = $skill->getId();
|
$s .= static::single_skill_editor_item($skill);
|
||||||
$s .= "<li class='skill_info' data-id='{$skill_id}'>".$skill->render_demo_badge(DEMOBADGE_SIZE);
|
|
||||||
$s .= "<figcaption data-for='name'>".$skill->getName()."</figcaption>";
|
|
||||||
$s .= "</li>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$s .= "</ul>";
|
||||||
|
$s .= "<a href='#' onclick='return false;' data-action='addskill'>".get_string('cfg_addskill','block_gradelevel')."</a>";
|
||||||
|
$s .= "</div>";
|
||||||
|
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function render_skill_editor(int $skill_id)
|
||||||
|
{
|
||||||
|
$skill = block_gradelevel_levelset::find_by_id($skill_id);
|
||||||
|
|
||||||
|
$s = "<div id='skill_set' class='skill_set'><ul>";
|
||||||
|
$s .= static::single_skill_editor_item($skill,true);
|
||||||
$s .= "</ul></div>";
|
$s .= "</ul></div>";
|
||||||
|
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function single_skill_editor_item($skill,$single=false)
|
||||||
|
{
|
||||||
|
global $OUTPUT;
|
||||||
|
|
||||||
|
$skill_id = $skill->getId();
|
||||||
|
$s = "<li class='skill_info' data-id='{$skill_id}'>";
|
||||||
|
if(!$single){
|
||||||
|
$s .= "<a data-action='editlevels' href='#'>";
|
||||||
|
}
|
||||||
|
$s .= $skill->render_demo_badge(static::DEMOBADGE_SIZE)."</a>";
|
||||||
|
|
||||||
|
if(!$single){
|
||||||
|
$s .= "<a data-action='editlevels' href='#'>";
|
||||||
|
if(count($skill->list_courses()) ){
|
||||||
|
$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='editicon' data-action='editicon' onclick='return false;' href='#'><i class='icon fa fa-pencil fa-fw' title='".get_string('tooltip_editicon','block_gradelevel')."'></i></a>";
|
||||||
|
$s .= "<figcaption data-for='name'><span data-type='label'>".$skill->getName()."</span>";
|
||||||
|
$s .= "<a class='editname' data-action='editname' onclick='return false;' href='#'><i class='icon fa fa-pencil fa-fw' title='".get_string('tooltip_editname','block_gradelevel')."'></i></a>";
|
||||||
|
$s .= "</figcaption></li>";
|
||||||
|
return $s;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -13,35 +13,35 @@ class block_gradelevel_edit_form extends block_edit_form {
|
||||||
// Section header title according to language file.
|
// Section header title according to language file.
|
||||||
$mform->addElement('header', 'config_header', get_string('blocksettings', 'block'));
|
$mform->addElement('header', 'config_header', get_string('blocksettings', 'block'));
|
||||||
|
|
||||||
// A sample string variable with a default value.
|
$skills = block_gradelevel_levelset::list_all();
|
||||||
$mform->addElement('text', 'levelset_name', get_string('levelset_name', 'block_gradelevel'));
|
// sort by name
|
||||||
|
usort( $skills, function( $a, $b) {
|
||||||
$icon = $levelset->getIcon();
|
return ( $a->getName() < $b->getName()) ? -1 : 1;
|
||||||
if(strncmp($icon,"data: ",6) != 0)
|
} );
|
||||||
|
|
||||||
|
$options = array( '-1' => get_string('edit_noneskill', 'block_gradelevel'));
|
||||||
|
foreach($skills as $skill)
|
||||||
{
|
{
|
||||||
$icon = $CFG->wwwroot.$icon;
|
$options[$skill->getId()] = $skill->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
$icon_title = get_string('levelset_icon_cur', 'block_gradelevel');
|
|
||||||
$mform->addElement('html',"<div class='form-group row fitem'><div class='col-md-3'>{$icon_title}</div><div class='col-md-9'><figure class='levelset_icon'><img src='{$icon}' /></figure></div></div>");
|
|
||||||
|
|
||||||
// A sample string variable with a default value.
|
// A sample string variable with a default value.
|
||||||
$mform->addElement('filepicker', 'levelset_icon', get_string('levelset_icon_new', 'block_gradelevel'), null,
|
$mform->addElement('select', 'attached_skill', get_string('edit_pickskill', 'block_gradelevel'), $options);
|
||||||
array('maxbytes' => $maxbytes, 'accepted_types' => array('.png', '.svg')));
|
|
||||||
|
|
||||||
$mform->addElement('header', 'config_header', get_string('levelset_levels', 'block_gradelevel'));
|
|
||||||
$mform->addElement('html',print block_gradelevel_managelevelservice::render_leveltable(0));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_data($defaults)
|
public function set_data($defaults)
|
||||||
{
|
{
|
||||||
|
global $COURSE;
|
||||||
|
|
||||||
|
$defaults->attached_skill = -1;
|
||||||
// retrieve levelset
|
// retrieve levelset
|
||||||
$levelset = $this->block->levelset;
|
$skill = block_gradelevel_levelset::find_by_course($COURSE->id);
|
||||||
|
if(isset($skill)){
|
||||||
|
$defaults->attached_skill = $skill->getId();
|
||||||
|
}
|
||||||
|
|
||||||
$defaults->levelset_name = $levelset->getName();
|
|
||||||
|
|
||||||
$defaults->levelset_icon = $levelset->getIcon();
|
|
||||||
|
|
||||||
parent::set_data($defaults);
|
parent::set_data($defaults);
|
||||||
}
|
}
|
||||||
|
@ -61,50 +61,26 @@ class block_gradelevel_edit_form extends block_edit_form {
|
||||||
|
|
||||||
protected function save_data($data)
|
protected function save_data($data)
|
||||||
{
|
{
|
||||||
|
global $COURSE;
|
||||||
// retrieve levelset
|
// retrieve levelset
|
||||||
$levelset = $this->block->levelset;
|
|
||||||
|
|
||||||
$this->debug("data: ".print_r($data,true));
|
if(isset($data->attached_skill))
|
||||||
|
|
||||||
|
|
||||||
if(isset($data->levelset_name)){
|
|
||||||
$levelset->setName($data->levelset_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($data->levelset_icon))
|
|
||||||
{
|
{
|
||||||
$filename = $this->get_new_filename('levelset_icon');
|
$currentskill = block_gradelevel_levelset::find_by_course($COURSE->id);
|
||||||
$contents = $this->get_file_content('levelset_icon');
|
if(isset($currentskill))
|
||||||
|
|
||||||
$imageData = base64_encode($contents);
|
|
||||||
|
|
||||||
$pi = pathinfo($filename);
|
|
||||||
if($pi['extension'] == 'svg')
|
|
||||||
{
|
{
|
||||||
$mime = "image/svg+xml";
|
$this->debug("deetaching...");
|
||||||
}
|
$currentskill->detach_course($COURSE->id);
|
||||||
else if($pi['extension'] == 'png')
|
|
||||||
{
|
|
||||||
$mime = "image/png";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$mime = "binary/octet-stream"; // no idea what it is
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$skill = block_gradelevel_levelset::find_by_id($data->attached_skill);
|
||||||
$dataSrc = 'data: '.$mime.';base64,'.$imageData;
|
if(isset($skill)){
|
||||||
|
$this->debug("attaching...");
|
||||||
$levelset->setIcon($dataSrc);
|
$skill->attach_course($COURSE->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->debug("levelset: ".print_r($levelset,true));
|
|
||||||
|
|
||||||
$levelset->save_data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private function debug($msg)
|
private function debug($msg)
|
||||||
{
|
{
|
||||||
error_log($msg, 3, '/tmp/moodledevlog.log');
|
error_log($msg, 3, '/tmp/moodledevlog.log');
|
||||||
|
|
|
@ -7,16 +7,18 @@ $string['gradelevel:myaddinstance'] = 'Add a new Grade Level block to the My Moo
|
||||||
$string['blockstring'] = 'Text in the block';
|
$string['blockstring'] = 'Text in the block';
|
||||||
$string['levelup_at'] = 'Next level: ';
|
$string['levelup_at'] = 'Next level: ';
|
||||||
$string['levelup_done'] = 'Complete';
|
$string['levelup_done'] = 'Complete';
|
||||||
|
$string['unattached_course'] = 'Please attach this course to a skill in the block settings';
|
||||||
|
|
||||||
$string['teacher_view_results'] = 'View student results';
|
$string['teacher_view_results'] = 'View student results';
|
||||||
|
|
||||||
$string['levelset_name'] = "Skill name";
|
$string['edit_pickskill'] = "Attach to skill";
|
||||||
$string['levelset_icon_cur'] = "Current skill icon (for level badge)";
|
$string['edit_noneskill'] = "None";
|
||||||
$string['levelset_icon_new'] = "New skill icon (for level badge)";
|
|
||||||
|
|
||||||
$string['cfgpage_generic'] = "Grade Level settings";
|
$string['cfgpage_generic'] = "Grade Level settings";
|
||||||
$string['cfgpage_globallevels'] = "Default levels";
|
$string['cfgpage_globallevels'] = "Default levels";
|
||||||
|
$string['cfgpage_skilllevels'] = "Edit levels";
|
||||||
|
$string['cfgpage_skills'] = "Manage skills";
|
||||||
|
$string['cfgpage_editskill'] = "Edit skill";
|
||||||
|
|
||||||
$string['descconfig'] = "Configuration for Grade Level block";
|
$string['descconfig'] = "Configuration for Grade Level block";
|
||||||
|
|
||||||
|
@ -34,3 +36,16 @@ $string['levelcfg_description'] = "Levels will be sorted based on points. Make s
|
||||||
$string['levelcfg_head_points'] = "Points";
|
$string['levelcfg_head_points'] = "Points";
|
||||||
$string['levelcfg_head_color'] = "Medal color";
|
$string['levelcfg_head_color'] = "Medal color";
|
||||||
$string['levelcfg_addlevel'] = "Add level";
|
$string['levelcfg_addlevel'] = "Add level";
|
||||||
|
|
||||||
|
$string['tooltip_editicon'] = "Edit icon";
|
||||||
|
$string['tooltip_editname'] = "Edit name";
|
||||||
|
$string['tooltip_deleteskill'] = "Delete skill";
|
||||||
|
$string['tooltip_deleteskill_disabled'] = "Cannot delete skill, because there are attached courses";
|
||||||
|
|
||||||
|
$string['defaults_name'] = "New skill";
|
||||||
|
$string['cfg_resetlevels'] = "Reset levels to default";
|
||||||
|
$string['cfg_addskill'] = "Add skill";
|
||||||
|
|
||||||
|
$string['title_confirmdelete'] = "Confirm delete";
|
||||||
|
$string['dialog_confirmdeleteskill'] = "Are you sure you want to delete this skill?";
|
||||||
|
//$string[''] = "";
|
||||||
|
|
2601
pix/brokenbadge.svg
Normal file
2601
pix/brokenbadge.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 92 KiB |
21
settings.php
21
settings.php
|
@ -18,16 +18,23 @@ $settings->add(new admin_setting_configtext(
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
$ADMIN->add("block_gradelevel", $settings);
|
||||||
|
|
||||||
// Add the default levels page
|
// Add the default levels page
|
||||||
$external = new admin_externalpage(
|
$ADMIN->add("block_gradelevel", new admin_externalpage(
|
||||||
'block_gradelevel_default_levels',
|
'block_gradelevel_default_levels',
|
||||||
get_string('cfgpage_globallevels', 'block_gradelevel'),
|
get_string('cfgpage_globallevels', 'block_gradelevel'),
|
||||||
$CFG->wwwroot . '/blocks/gradelevel/globallevels.php'
|
$CFG->wwwroot . '/blocks/gradelevel/cfg_globallevels.php'
|
||||||
);
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$ADMIN->add("block_gradelevel", $settings);
|
// Add the skill configpage
|
||||||
$ADMIN->add("block_gradelevel", $external);
|
$ADMIN->add("block_gradelevel", new admin_externalpage(
|
||||||
|
'block_gradelevel_config_skills',
|
||||||
|
get_string('cfgpage_skills', 'block_gradelevel'),
|
||||||
|
$CFG->wwwroot . '/blocks/gradelevel/cfg_skills.php'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
$settings = null;
|
$settings = null;
|
86
styles.css
86
styles.css
|
@ -1,4 +1,4 @@
|
||||||
figure.levelbadge {
|
figure.levelbadge, figure.dummybadge {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,17 +6,19 @@ div.pointinfo {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: "Open Sans", Arial, helvetica, sans-serif;
|
font-family: "Open Sans", Arial, helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
div.pointinfo.complete {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.pointinfo span.currentpoints {
|
div.pointinfo.complete {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.pointinfo span.currentpoints {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pointinfo span.leveluppoints {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
div.pointinfo span.leveluppoints {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
div.teachermode {
|
div.teachermode {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +31,70 @@ input.jscolor[type=text] {
|
||||||
width: 5em;
|
width: 5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.skill_set ul {
|
||||||
|
padding-left: 0px;
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info {
|
||||||
|
position: relative; /* needed to have absolute positions be relative to this li */
|
||||||
|
list-style: none;
|
||||||
|
display: inline-block;
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
border-color: #ccc;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.skill_set li.skill_info figcaption {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info input[type=text] {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info a.editicon {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info a.deleteskill {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
div.skill_set li.skill_info a.deleteskill i.icon {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info a.deleteskill i.icon.disabled {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.skill_set li.skill_info a.editname {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.level_config tr[data-rowid='-255'] {
|
||||||
|
}
|
||||||
|
|
||||||
|
table.level_config tr[data-rowid='-255'] td {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table.level_config tr[data-rowid='-255'] input[data-name='points'] {
|
||||||
|
background-color: #F0F0F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
figure.levelset_icon {
|
figure.levelset_icon {
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
background-image: -moz-linear-gradient(45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(-45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #aaa 75%), -moz-linear-gradient(-45deg, transparent 75%, #aaa 75%);
|
background-image: -moz-linear-gradient(45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(-45deg, #aaa 25%, transparent 25%), -moz-linear-gradient(45deg, transparent 75%, #aaa 75%), -moz-linear-gradient(-45deg, transparent 75%, #aaa 75%);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
$plugin->component = 'block_gradelevel'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)
|
$plugin->component = 'block_gradelevel'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)
|
||||||
$plugin->version = 2018092101; // YYYYMMDDHH (year, month, day, 24-hr time)
|
$plugin->version = 2018092300; // YYYYMMDDHH (year, month, day, 24-hr time)
|
||||||
$plugin->requires = 2018050800; // YYYYMMDDHH (This is the release version for Moodle 3.5)
|
$plugin->requires = 2018050800; // YYYYMMDDHH (This is the release version for Moodle 3.5)
|
Loading…
Reference in New Issue
Block a user