Added web service for managing levelsets (now mostly called "skills")

Default levels can be configured.
Working on management interface for predefined skills.
This commit is contained in:
pmk 2018-09-21 22:30:09 +02:00
parent 9452a578bc
commit 6b16559201
14 changed files with 704 additions and 118 deletions

View File

@ -2,58 +2,116 @@
// 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', 'core/str', 'core/ajax', 'block_gradelevel/jscolor'], function ($, str, ajax, jscolor) {
let skill_id = null;
let $skill_table = null;
let self = { let self = {
init: function init() { init: function init() {
$("input[type=number].uint").on('change', function (evt) {
// Find skill table and skill id
$skill_table = $("table#level_config");
skill_id = Number($skill_table.attr('data-skill'));
if (!skill_id && skill_id !== 0 && skill_id !== '0') {
console.error("Cannot find configured skill id");
return;
}
// load and fill the level table
self.refresh();
// make sure all uint type numbers are not able to go below 0
$(document).on('change', "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);
} }
}); });
// On click handler for add level link
$("a[data-action=addlevel]").on('click', function (evt) { $("a[data-action=addlevel]").on('click', function (evt) {
let $newtr = $("<tr data-rowid=''>" self.add_levelrow(-255, '', '7F7F7F');
+ "<td><input data-name='points' type='number' class='uint'></td>"
+ "<td><input type='text' data-name='color' class='jscolor' value='7F7F7F'></td></tr>");
let $tbody = $("table#level_config tbody");
// apply jscolor to new row
$newtr.find("input.jscolor").each(function () {
let picker = new jscolor(this);
});
// and add
$tbody.append($newtr);
}); });
// On click handler for save changes button
$("button[data-action=savechanges]").on('click', self.submit); $("button[data-action=savechanges]").on('click', self.submit);
},
add_levelrow: function (id, points, color) {
// create new row
let $newtr = $("<tr data-rowid='"+id+"'>"
+ "<td><input data-name='points' type='number' class='uint' value='"+points+"'></td>"
+ "<td><input type='text' data-name='color' class='jscolor' value='"+color+"'></td></tr>");
// apply jscolor to new row
$newtr.find("input.jscolor").each(function () {
let picker = new jscolor(this);
});
// and add to the body of the table
$skill_table.find("tbody").append($newtr);
},
refresh: function refresh() {
console.info("Attempting to refresh");
// perform refresh call
let promises = ajax.call([{
methodname: 'block_gradelevel_list_levels',
args: { skill_id: skill_id },
}]);
// and link promise returns to callbacks
promises[0].done(self.success_refill_table).fail(self.fail_report_exception);
}, },
submit: function submit(evt) { submit: function submit(evt) {
let $table = $("table#level_config"); let $table = $("table#level_config");
let data = { skill_id: $table.attr('data-skill'), levels: [] }; let level_data = [];
$table.find("tbody tr[data-rowid]").each(function () { $table.find("tbody tr[data-rowid]").each(function () {
let $this = $(this); let $this = $(this);
let row = { let row = {
id: $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(),
color: $this.find("input[data-name=color]").val(), badgecolor: $this.find("input[data-name=color]").val(),
} }
data.levels.push(row);
if (row.points === "") { row.points = -255; }
row.points = Number(row.points);
level_data.push(row);
}); });
console.info("Attempting to submit", data); //console.info("Attempting to submit", level_data);
$.post("#", { action: "submitchanges", data: data }, function (result) { // perform ajax call
console.info('result: ', result); let promises = ajax.call([{
window.location.href = '#'; 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(self.fail_report_exception);
},
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

@ -11,7 +11,7 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
let props = self.fetchProperties(this); let props = self.fetchProperties(this);
let $this = $(this); let $this = $(this);
let $canvas = $("<canvas height= '"+props.height +"' width = '"+props.width+"'/>"); let $canvas = $("<canvas height= '"+props.height +"' width = '"+props.width+"'/>");
console.info("$canvas", $canvas, $canvas[0]); //console.info("$canvas", $canvas, $canvas[0]);
$('canvas', this).remove();// clear out any existing canvas $('canvas', this).remove();// clear out any existing canvas
$this.append($canvas); // Put the canvas in there $this.append($canvas); // Put the canvas in there
self.render($canvas[0], props); self.render($canvas[0], props);
@ -61,9 +61,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); //console.info("Config", config);
console.info("Colors", colors); //console.info("Colors", colors);
console.info("Props", props); //console.info("Props", props);
// draw main circle // draw main circle
let baseGradient = ctx.createRadialGradient( let baseGradient = ctx.createRadialGradient(
@ -159,7 +159,7 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
ctx.drawImage(this, 15, 15, 120, 120);//imPos.x, imPos.y, imPos.w, imPos.h); ctx.drawImage(this, 15, 15, 120, 120);//imPos.x, imPos.y, imPos.w, imPos.h);
} }
console.info("Image: ",props.image); //console.info("Image: ",props.image);
iconImg.src = props.image; iconImg.src = props.image;
} }
@ -177,7 +177,7 @@ define(['jquery', 'core/str', 'core/ajax'], function ($, str, ajax) {
progress: $figure.attr("data-progress"), progress: $figure.attr("data-progress"),
width: $figure.attr("data-width"), width: $figure.attr("data-width"),
height: $figure.attr("data-height"), height: $figure.attr("data-height"),
color: $figure.attr("data-color"), color: "#"+$figure.attr("data-color"),
level: $figure.attr("data-level"), level: $figure.attr("data-level"),
image: image, image: image,
}; };

View File

@ -44,6 +44,7 @@ class block_gradelevel extends block_base {
public function get_content() { public function get_content() {
global $USER; global $USER;
global $COURSE;
if ($this->content !== null) { if ($this->content !== null) {
return $this->content; return $this->content;
@ -55,7 +56,7 @@ class block_gradelevel extends block_base {
$pointstotal = $this->levelset->get_levelset_grade($USER->id); $pointstotal = $this->levelset->get_levelset_grade($USER->id);
$level_info = $this->levelset->calculate_level($pointstotal); $level_info = $this->levelset->calculate_level($pointstotal);
$this->content->text = $this->render_badge($level_info->badge_color,$level_info->progress,$this->levelset->getIcon(),$level_info->level); $this->content->text = $this->levelset->render_badge($pointstotal);
if($level_info->levelup_total > 0) if($level_info->levelup_total > 0)
{ {
@ -66,38 +67,23 @@ class block_gradelevel extends block_base {
$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);
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>";
}
return $this->content; return $this->content;
} }
public function hide_header() { return false; } public function hide_header() { return !get_config('gradelevel', 'showtitle'); }
public function has_config() { return true; } public function has_config() { return true; }
private function render_badge($basecolor,$progress,$image=null,$level="1"){
global $CFG;
if(strncmp($image,"data: ",6) != 0)
{
$image_url = $CFG->wwwroot.$image;
}
else
{
$image_url = $image;
}
$html = "<figure class='levelbadge' data-color='{$basecolor}' data-progress='{$progress}' data-width='150' data-height='150' data-level='{$level}'>";
if(!empty($image))
{
$html .= "<img style='display:none' src='{$image_url}' />";
}
$html .= "</figure>";
return $html;
}
} }

View File

@ -10,11 +10,11 @@ class block_gradelevel_levelset {
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 => "#000000",
25 => "#2ad4ff", 250 => "#2ad4ff", // + 250
50 => "#cd7f32", 750 => "#cd7f32", // + 500
100 => "#a6a6a6", 1750 => "#a6a6a6", // + 1000
200 => "#f6ae00", 2750 => "#f6ae00", // + 2000
); );
private $id; private $id;
@ -85,6 +85,11 @@ class block_gradelevel_levelset {
} }
public function getId() : string
{
return $this->id;
}
public function setName(string $name) public function setName(string $name)
{ {
$this->data->name = $name; $this->data->name = $name;
@ -136,6 +141,19 @@ 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)
{
$levelset = $DB->get_record('block_gradelevel_levelset', array('id' => array_values($records)[0]->levelset_id));
if($levelset)
{
return new static($levelset->id,$levelset);
}
else
{
return null;
}
}
/** /**
* List attached courses for this levelset * List attached courses for this levelset
@ -190,8 +208,6 @@ class block_gradelevel_levelset {
print_error('updateerror', 'block_gradelevel'); print_error('updateerror', 'block_gradelevel');
} }
} }
} }
} }
@ -436,4 +452,43 @@ class block_gradelevel_levelset {
} }
public function render_badge(int $points,int $size=150){
global $CFG;
$info = $this->calculate_level($points);
$image = $this->getIcon();
if(strncmp($image,"data: ",6) != 0)
{
$image_url = $CFG->wwwroot.$image;
}
else
{
$image_url = $image;
}
$html = "<figure class='levelbadge'";
$html .= " data-color='{$info->badge_color}'";
$html .= " data-progress='{$info->progress}'";
$html .= " data-level='{$info->level}'";
$html .= " data-width='{$size}'";
$html .= " data-height='{$size}'";
$html .= ">";
if(!empty($image))
{
$html .= "<img style='display:none' src='{$image_url}' />";
}
$html .= "</figure>";
return $html;
}
public function render_demo_badge(int $size=100)
{
$levels = $this->badgelevels();
$maxpoints = array_pop(array_keys($levels));
return $this->render_badge($maxpoints,$size);
}
} }

View File

@ -0,0 +1,406 @@
<?php
require_once($CFG->libdir.'/gradelib.php');
require_once($CFG->libdir.'/externallib.php');
require_once($CFG->dirroot.'/grade/querylib.php');
//namespace block_gradelevel;
class block_gradelevel_skillmgmtservice extends external_api
{
const DEBUG = false; // enable debug logging
const DEMOBADGE_SIZE = 100; // size of demo badge
private static function log($message)
{
if(self::DEBUG)
{
error_log($message."\n",3,"/tmp/block_gradelevel.log");
}
}
private static function list_courses($skill_id)
{
global $DB;
$list = array();
$links = $DB->get_records('block_gradelevel_course_link', array('levelset_id' => $skill_id));
foreach($links as $link)
{
$list[] = $link->course_id;
}
return $list;
}
// Input parameter config
public static function submit_levels_parameters()
{
return new external_function_parameters(
array(
'skill_id' => new external_value(PARAM_INT, 'id of skill'),
'levels' => new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
)
)
);
}
public static function list_levels_parameters()
{
return new external_function_parameters(
array(
'skill_id' => new external_value(PARAM_INT, 'id of skill'),
)
);
}
public static function list_skills_parameters()
{
return new external_function_parameters( array() );
}
public static function get_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'id of skill'),
)
);
}
public static function update_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
)
);
}
public static function add_skill_parameters()
{
return new external_function_parameters(
array(
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
)
);
}
public static function delete_skill_parameters()
{
return new external_function_parameters(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
)
);
}
// Output parameter config
public static function submit_levels_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
);
}
public static function list_levels_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'id of level'),
'points' => new external_value(PARAM_INT, 'number of points for this level'),
'badgecolor' => new external_value(PARAM_TEXT, 'color of level badge'),
)
)
);
}
public static function list_skills_returns()
{
return new external_multiple_structure(
new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
)
);
}
public static function get_skill_returns()
{
return new external_single_structure(
array(
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function update_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function add_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'name' => new external_value(PARAM_TEXT, 'Name of skill'),
'icon' => new external_value(PARAM_RAW, 'Icon for skill'),
'html' => new external_value(PARAM_RAW, 'Demo badge'),
)
);
}
public static function delete_skill_returns()
{
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Id of skill'),
'deleted' => new external_value(PARAM_BOOL, 'Deletion succesful'),
)
);
}
// Actual functions
public static function submit_levels(int $skill_id, array $levels)
{
global $CFG, $DB;
self::log("submit_levels called, skill_id: {$skill_id}, levels: \n".print_r($levels,true));
$systemcontext = context_system::instance();
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)
{
// convert level array to stdObj
$lvl = (object) $lvl_raw;
$lvl->levelset_id = $skill_id;
self::log("Processing level: ".print_r($lvl,true));
if($lvl->points >= 0)
{
if($lvl->id >= 0)
{
// Update record
self::log("updating row {$lvl->id}: {$lvl->points}, {$lvl->badgecolor} @ {$lvl->levelset_id}");
$DB->update_record('block_gradelevel_levels',$lvl);
}
else
{
// unset invalid id before insert
unset($lvl->id);
self::log("inserting new row {$lvl->points}, {$lvl->badgecolor} @ {$lvl->levelset_id}");
// Insert record
$DB->insert_record('block_gradelevel_levels',$lvl);
}
}
else
{
// points is empty: delete record if we have a valid id.
if($lvl->id >= 0)
{
self::log("deleting empty row {$lvl->id}");
$DB->delete_records('block_gradelevel_levels', array('id' => $lvl->id));
}
else
{
self::log("ignoring empty row");
}
}/**/
}
return static::list_levels($skill_id);
}
public static function list_levels(int $skill_id)
{
global $CFG, $DB;
$levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => $skill_id));
// Sort by points
usort( $levels, function( $a, $b) {
return ( $a->points < $b->points ) ? -1 : 1;
} );
return $levels;
}
public static function list_skills()
{
global $CFG, $DB;
$skills = $DB->get_records('block_gradelevel_levelset');
// Sort by points
usort( $skills, function( $a, $b) {
return ( $a->name < $b->name) ? -1 : 1;
} );
foreach($skills as $skill )
{
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
}
return $skills;
}
public static function get_skill(int $id)
{
global $CFG, $DB;
$skill = $DB->get_record('block_gradelevel_levels', array('id' => $id));
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function update_skill(int $id, string $name, string $icon )
{
global $CFG, $DB;
$skill = $DB->get_record('block_gradelevel_levelset', array('id' => $id));
$skill->name = $name;
$skill->icon = $icon;
$DB->update_record('block_gradelevel_levelset',$skill);
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function add_skill(string $name, string $icon)
{
global $CFG, $DB;
$skill = stdObj;
$skill->name = $name;
$skill->icon = $icon;
$id = $DB->insert_record('block_gradelevel_levelset',$skill, true);
$skill->id = $id;
$skill->html = block_gradelevel_levelset::find_by_id($skill->id)->render_demo_badge(static::DEMOBADGE_SIZE);
return $skill;
}
public static function delete_skill(int $id)
{
global $CFG, $DB;
$result = stdObj;
$result->id = $id;
$result->id = ($DB->delete_record('block_gradelevel_levelset',array('id' => $id)))?true:false;
return $result;
}
// Other public functions
public static function render_leveltable($skill_id)
{
$levels = static::list_levels($skill_id);
$s = "<p>".get_string('levelcfg_description','block_gradelevel')."</p>";
$s .= "<table id='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 .= "<tbody>";
foreach($levels as $lvl)
{
$color = ltrim($lvl->badgecolor,"#"); // trim any leading hashes
$s .= "<tr data-rowid='{$lvl->id}'><td><input data-name='points' type='number' class='uint' value='{$lvl->points}'></td><td><input type='text' data-name='color' class='jscolor' value='{$color}'></td></tr>";
}
$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 .= "</table>";
$s .= "<p><button data-action='savechanges'>".get_string('savechanges','core')."</button></p>";
return $s;
}
public static function render_skill_list()
{
$skills = block_gradelevel_levelset::list_all();
$s = "<div class='skill_set'><ul>";
foreach($skills as $skill)
{
$skill_id = $skill->getId();
$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></div>";
}
}

View File

@ -23,4 +23,27 @@
'clonepermissionsfrom' => 'moodle/site:manageblocks' 'clonepermissionsfrom' => 'moodle/site:manageblocks'
), ),
'block/gradelevel:skillmanager' => array(
'riskbitmask' => RISK_CONFIG | RISK_DATALOSS | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'manager' => CAP_ALLOW
),
),
'block/gradelevel:viewresults' => array(
'riskbitmask' => RISK_DATALOSS | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_BLOCK,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
),
); );

View File

@ -21,7 +21,7 @@
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="levelset_id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Reference to specific levelset"/> <FIELD NAME="levelset_id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Reference to specific levelset"/>
<FIELD NAME="points" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Number of points needed to reach this level"/> <FIELD NAME="points" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Number of points needed to reach this level"/>
<FIELD NAME="bagdecolor" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Color of the level badge. Leave null to use default color (of the levelset 0 set)"/> <FIELD NAME="badgecolor" TYPE="char" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Color of the level badge. Leave null to use default color (of the levelset 0 set)"/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/> <KEY NAME="primary" TYPE="primary" FIELDS="id"/>

93
db/services.php Normal file
View File

@ -0,0 +1,93 @@
<?php
$services = array(
"Gradelevel Level Management" => array(
'functions' => array('block_gradelevel_submit_levels', 'block_gradelevel_list_levels'),
'requiredcapability' => 'block/gradelevel:changelevels',
'shortname'=> 'block_gradelevel_levelmgmt',
'restrictedusers' => 0,
'enabled' => 0,
'ajax' => true,
),
);
$functions = array(
'block_gradelevel_submit_levels' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'submit_levels', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'Update level settings for a given skill', //human readable description of the web service function
'type' => 'write', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_list_levels' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'list_levels', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'List level settings for a given skill', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_list_skills' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'list_skills', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'List skills', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_get_skill' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'get_skill', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'Retrieve skill information', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_update_skill' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'update_skill', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'Update a skill', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_add_skill' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'add_skill', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'Add a new skill', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
'block_gradelevel_delete_skill' => array( //web service function name
'classname' => 'block_gradelevel_skillmgmtservice', //class containing the external function
'methodname' => 'delete_skill', //external function name
'classpath' => 'blocks/gradelevel/skillmgmtservice.php', //file containing the class/external function
'description' => 'Delete a skill', //human readable description of the web service function
'type' => 'read', //database rights of the web service function (read, write)
'ajax' => true,
'capabilities' => 'block/gradelevel:skillmanager',
'loginrequired' => true,
'services' => array('block_gradelevel_levelmgmt'),
),
);

View File

@ -157,7 +157,6 @@ COURSE: stdClass Object
[shortname] => PIC-MCU3 [shortname] => PIC-MCU3
[idnumber] => [idnumber] =>
[summary] => Programmeren van PIC18 microcontrollers van microchip. [summary] => Programmeren van PIC18 microcontrollers van microchip.
[summaryformat] => 1 [summaryformat] => 1
[format] => topics [format] => topics
[showgrades] => 1 [showgrades] => 1

View File

@ -29,7 +29,9 @@ class block_gradelevel_edit_form extends block_edit_form {
$mform->addElement('filepicker', 'levelset_icon', get_string('levelset_icon_new', 'block_gradelevel'), null, $mform->addElement('filepicker', 'levelset_icon', get_string('levelset_icon_new', 'block_gradelevel'), null,
array('maxbytes' => $maxbytes, 'accepted_types' => array('.png', '.svg'))); 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)

View File

@ -3,6 +3,7 @@ if(isset($_SERVER['SCRIPT_FILENAME']))
{ {
// If SCRIPT_FILENAME is set, use that so the symlinked directories the developmen environment uses are handled correctly // 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']))); $root = dirname(dirname(dirname($_SERVER['SCRIPT_FILENAME'])));
error_log("Using {$root}/config.php");
require_once($root."/config.php"); require_once($root."/config.php");
} }
else else
@ -15,61 +16,19 @@ else
require_once($CFG->libdir.'/adminlib.php'); require_once($CFG->libdir.'/adminlib.php');
admin_externalpage_setup("block_gradelevel_default_levels"); admin_externalpage_setup("block_gradelevel_default_levels");
$action = optional_param('action', null, PARAM_ALPHA); $systemcontext = context_system::instance();
$data = optional_param('data', null, PARAM_ALPHA); // Check if user has capability to manage skills
if(!empty($data)) require_capability('block/gradelevel:skillmanager', $systemcontext);
{
$data = json_decode($data);
}
if(!empty($action) && confirm_sesskey())
{
switch($action) {
case 'submitchanges':
print_r($data);
$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init');
print $OUTPUT->header();
print $OUTPUT->heading(get_string('cfgpage_globallevels', 'block_gradelevel'));
// render page for skill level 0 (global)
print block_gradelevel_skillmgmtservice::render_leveltable(0);
redirect($PAGE->url); print $OUTPUT->footer();
break;
}
}
else
{
$PAGE->requires->js_call_amd('block_gradelevel/leveleditor', 'init');
print $OUTPUT->header();
print $OUTPUT->heading(get_string('cfgpage_globallevels', 'block_gradelevel'));
$global_levels = $DB->get_records('block_gradelevel_levels', array('levelset_id' => 0));
usort( $global_levels, function( $a, $b) {
return ( $a->points < $b->points ) ? -1 : 1;
} );
$skill_id = 0;
print "<p>".get_string('levelcfg_description','block_gradelevel')."</p>";
print "<table id='level_config' data-skill='{$skill_id}'>";
print "<thead><tr><th>".get_string('levelcfg_head_points','block_gradelevel')."</th><th>".get_string('levelcfg_head_color','block_gradelevel')."</th></tr></thead>";
print "<tbody>";
foreach($global_levels as $lvl)
{
$color = ltrim($lvl->badgecolor,"#");
print "<tr data-rowid='{$lvl->id}'><td><input data-name='points' type='number' class='uint' value='{$lvl->points}'></td><td><input type='text' data-name='color' class='jscolor' value='{$color}'></td></tr>";
}
print "</tbody>";
print "<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>";
print "</table>";
print "<p><button data-action='savechanges'>".get_string('savechanges','core')."</button></p>";
print $OUTPUT->footer();
}

View File

@ -8,6 +8,8 @@ $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['teacher_view_results'] = 'View student results';
$string['levelset_name'] = "Skill name"; $string['levelset_name'] = "Skill name";
$string['levelset_icon_cur'] = "Current skill icon (for level badge)"; $string['levelset_icon_cur'] = "Current skill icon (for level badge)";
$string['levelset_icon_new'] = "New skill icon (for level badge)"; $string['levelset_icon_new'] = "New skill icon (for level badge)";

View File

@ -17,6 +17,9 @@ div.pointinfo {
div.pointinfo span.leveluppoints { div.pointinfo span.leveluppoints {
font-weight: bold; font-weight: bold;
} }
div.teachermode {
text-align: center;
}
td.block_gradelevel_addlevel { td.block_gradelevel_addlevel {
text-align: right; text-align: right;

View File

@ -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 = 2018091600; // YYYYMMDDHH (year, month, day, 24-hr time) $plugin->version = 2018092101; // 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)