Commit f5ab5eac authored by Astor Bizard's avatar Astor Bizard
Browse files

Added support for groups and groupings.

parent 3309a776
......@@ -35,6 +35,7 @@ $outcome->error = '';
try {
$id = required_param( 'id', PARAM_INT );
$nactivities = required_param( 'nactivities', PARAM_INT );
$group = optional_param( 'group', 0, PARAM_INT );
if ($nactivities == 0) {
throw new Exception();
......@@ -50,7 +51,7 @@ try {
$bestdist = PHP_INT_MAX;
for ($seed = 0; $seed <= 250; $seed++) {
$assignees = randomactivity_get_assignees($activities, $seed, $context);
$assignees = randomactivity_get_assignees($activities, $seed, $context, $group);
foreach ($assignees as &$cmassignees) {
$cmassignees = count($cmassignees);
}
......
......@@ -36,8 +36,9 @@ try {
$id = required_param( 'id', PARAM_INT);
$activities = required_param( 'activities', PARAM_RAW );
$seed = required_param( 'seed', PARAM_RAW );
$group = optional_param( 'group', 0, PARAM_INT );
$context = context_module::instance($id);
$outcome->response->assignees = randomactivity_get_assignees_formatted($activities, $seed, $context);
$outcome->response->assignees = randomactivity_get_assignees_formatted($activities, $seed, $context, $group);
} catch ( Exception $e ) {
$outcome->success = false;
$outcome->error = $e->getMessage();
......
define(["jquery","jqueryui","core/url","mod_randomactivity/orderabletable"],function(a,b,c,d){function e(b,c){var d=b.find("tbody tr");if(d.length>1)b.find(".empty-row").remove();else if(0==d.length){var e=b.find("thead th").length;b.find("tbody").append('<tr class="empty-row lastrow"><td colspan="'+e+'"></td></tr>')}var f="";b.find("tbody tr:not(.empty-row)").each(function(b){a(this).find("td:first-child").html(b+1),f+=a(this).data("cmid")+" "}).removeClass("lastrow").last().addClass("lastrow"),c.val(f.trim())}return{setup:function(){var b=a("#randomactivity-activities-table"),f=a("#form-randomactivity-activities"),g=f.find("[name=activities]"),h=f.find("[name=seed]");e(b,g),d.makeOrderable(a(".activitytable"),function(){e(b,g),f.change()}),a(".activitytable .removebutton").click(function(){a(this).closest("tr").remove(),e(b,g),f.change()});var i=function(a){a.preventDefault(),a.returnValue=""},j=!1;f.change(function(){a("#apply-assign-button").removeAttr("disabled"),j||(j=!0,window.addEventListener("beforeunload",i))}),a("#cancel-button").click(function(){window.removeEventListener("beforeunload",i)});var k=a("#confirm-reassign").dialog({autoOpen:!1,dialogClass:"popup-dialog",title:M.util.get_string("confirm","moodle"),modal:!0,buttons:[{text:M.util.get_string("confirm","moodle"),class:"btn btn-primary",click:function(){window.removeEventListener("beforeunload",i),f.submit()}},{text:M.util.get_string("cancel","moodle"),class:"btn btn-secondary",click:function(){a(this).dialog("close")}}],open:function(){a(":focus").blur()}});a("#apply-assign-button").attr("disabled","disabled").click(function(){k.dialog("open")}),a("#seed-timestamp").click(function(a){a.preventDefault(),h.val((new Date).getTime()),f.change()});var l=c.relativeUrl("/mod/randomactivity/ajax");a("#seed-balance").click(function(b){b.preventDefault();var c=a(".load-icon");c.show(),h.attr("disabled","disabled");var d=f.find("[name=id]").val(),e=g.val(),i=0;""!=e&&(i=e.split(" ").length),a.ajax(l+"/balanceseed.json.php?id="+d+"&nactivities="+i).done(function(a){a.success&&(h.val(a.response.seed),f.change())}).always(function(){h.removeAttr("disabled"),c.hide()})}),a(".refresh-assignees").click(function(){var c=f.find("[name=id]").val(),d=g.val(),e=h.val();a.ajax(l+"/refresh.json.php?id="+c+"&activities="+d+"&seed="+e).done(function(c){c.success&&b.find("tbody tr td:nth-child(3)").each(function(b){a(this).html(c.response.assignees[b])})})});var m={$selector:a(".activity-type-selector"),$dropdown:a(".activity-type-dropdown"),$selectmenu:a(".activity-type-selector, .activity-type-dropdown"),$selectedvalue:a(".activity-type-selected span"),$search:a("#activity-search")},n=function(){var b=m.$selectedvalue.data("cmtype"),c=m.$search.val(),d=g.val().split(" "),e=!0;a(".activities-to-add-list .section").each(function(){var f=!0,g=a(this).is(".expanded");a(this).find(".activity-to-add").each(function(){var e=a(this).data("cmid"),h=a(this).data("cmtype"),i=a(this).find("label").text(),j=(!b||h==b)&&!d.includes(e+"")&&(""===c||i.toLowerCase().includes(c.toLowerCase()));j&&g?a(this).show():a(this).hide(),j&&(f=!1)}),f?a(this).hide():(e=!1,a(this).show())}),e?a("#no-activity-to-add-message").show():a("#no-activity-to-add-message").hide()},o=a("#activities-choice").dialog({autoOpen:!1,dialogClass:"popup-dialog",title:M.util.get_string("addactivities","mod_randomactivity"),modal:!0,buttons:[{text:M.util.get_string("addselectedactivities","mod_randomactivity"),class:"btn btn-primary",click:function(){a(".activity-to-add").each(function(){a(this).find('input[type="checkbox"]').prop("checked")&&a(this).find("tr").clone(!0,!0).appendTo(b).css("display","")}),a(this).dialog("close"),e(b,g),f.change()}},{text:M.util.get_string("cancel","moodle"),class:"btn btn-secondary",click:function(){a(this).dialog("close")}}],open:function(){a(":focus").blur(),a('.activity-to-add input[type="checkbox"]').prop("checked",!1),a(".activities-to-add-list .section").addClass("expanded"),a(".activities-to-add-list").scrollTop(0),m.$selectedvalue.html(a(".activity-type").first().html()).data("cmtype",""),m.$selector.removeClass("expanded").addClass("collapsed"),m.$selectmenu.width(""),m.$search.val("").keyup(),n()}});a("#add-activities").click(function(){o.dialog("open")}),m.$selectmenu.click(function(){if(m.$selector.toggleClass("collapsed expanded"),m.$selector.is(".expanded")){var a=2*m.$dropdown.width()-m.$dropdown.prop("clientWidth");m.$selectmenu.width(Math.max(a,m.$selector.width()))}else m.$selectmenu.width("")}),a(".activity-type").click(function(){m.$selectedvalue.html(a(this).html()).data("cmtype",a(this).data("cmtype")),n()}),m.$search.keyup(function(){a(this).toggleClass("empty",""===a(this).val()),n()}),a(".search-remove").click(function(){m.$search.val("").keyup()}),a(".search-icon").click(function(){m.$search.focus()}),a(".activities-to-add-list .section .toggle-all").click(function(b){b.stopImmediatePropagation(),a(this).parents(".section").find('.activity-to-add:visible input[type="checkbox"]').prop("checked","select"==a(this).data("action"))}),a(".activities-to-add-list .section-header").click(function(){a(this).parents(".section").toggleClass("expanded"),n()})}}});
\ No newline at end of file
define(["jquery","jqueryui","core/url","mod_randomactivity/orderabletable"],function(a,b,c,d){function e(b,c){var d=b.find("tbody tr");if(d.length>1)b.find(".empty-row").remove();else if(0==d.length){var e=b.find("thead th").length;b.find("tbody").append('<tr class="empty-row lastrow"><td colspan="'+e+'"></td></tr>')}var f="";b.find("tbody tr:not(.empty-row)").each(function(b){a(this).find("td:first-child").html(b+1),f+=a(this).data("cmid")+" "}).removeClass("lastrow").last().addClass("lastrow"),c.val(f.trim())}return{setup:function(){var b=a("#randomactivity-activities-table"),f=a("#form-randomactivity-activities"),g=f.find("[name=activities]"),h=f.find("[name=seed]");e(b,g),d.makeOrderable(a(".activitytable"),function(){e(b,g),f.change()}),a(".activitytable .removebutton").click(function(){a(this).closest("tr").remove(),e(b,g),f.change()});var i=function(a){a.preventDefault(),a.returnValue=""},j=!1;f.change(function(){a("#apply-assign-button").removeAttr("disabled"),j||(j=!0,window.addEventListener("beforeunload",i))}),a("#cancel-button").click(function(){window.removeEventListener("beforeunload",i)});var k=a("#confirm-reassign").dialog({autoOpen:!1,dialogClass:"popup-dialog",title:M.util.get_string("confirm","moodle"),modal:!0,buttons:[{text:M.util.get_string("confirm","moodle"),class:"btn btn-primary",click:function(){window.removeEventListener("beforeunload",i),f.submit()}},{text:M.util.get_string("cancel","moodle"),class:"btn btn-secondary",click:function(){a(this).dialog("close")}}],open:function(){a(":focus").blur()}});a("#apply-assign-button").attr("disabled","disabled").click(function(){k.dialog("open")}),a("#seed-timestamp").click(function(a){a.preventDefault(),h.val((new Date).getTime()),f.change()});var l=c.relativeUrl("/mod/randomactivity/ajax");a("#seed-balance").click(function(b){b.preventDefault();var c=a(".load-icon");c.show(),h.attr("disabled","disabled");var d=f.find("[name=id]").val(),e=f.find("[name=group]").val(),i=g.val(),j=0;""!=i&&(j=i.split(" ").length),a.ajax(l+"/balanceseed.json.php?id="+d+"&nactivities="+j+"&group="+e).done(function(a){a.success&&(h.val(a.response.seed),f.change())}).always(function(){h.removeAttr("disabled"),c.hide()})}),a(".refresh-assignees").click(function(){var c=f.find("[name=id]").val(),d=f.find("[name=group]").val(),e=g.val(),i=h.val();a.ajax(l+"/refresh.json.php?id="+c+"&activities="+e+"&seed="+i+"&group="+d).done(function(c){c.success&&b.find("tbody tr td:nth-child(3)").each(function(b){a(this).html(c.response.assignees[b])})})});var m={$selector:a(".activity-type-selector"),$dropdown:a(".activity-type-dropdown"),$selectmenu:a(".activity-type-selector, .activity-type-dropdown"),$selectedvalue:a(".activity-type-selected span"),$search:a("#activity-search")},n=function(){var b=m.$selectedvalue.data("cmtype"),c=m.$search.val(),d=g.val().split(" "),e=!0;a(".activities-to-add-list .section").each(function(){var f=!0,g=a(this).is(".expanded");a(this).find(".activity-to-add").each(function(){var e=a(this).data("cmid"),h=a(this).data("cmtype"),i=a(this).find("label").text(),j=(!b||h==b)&&!d.includes(e+"")&&(""===c||i.toLowerCase().includes(c.toLowerCase()));j&&g?a(this).show():a(this).hide(),j&&(f=!1)}),f?a(this).hide():(e=!1,a(this).show())}),e?a("#no-activity-to-add-message").show():a("#no-activity-to-add-message").hide()},o=a("#activities-choice").dialog({autoOpen:!1,dialogClass:"popup-dialog",title:M.util.get_string("addactivities","mod_randomactivity"),modal:!0,buttons:[{text:M.util.get_string("addselectedactivities","mod_randomactivity"),class:"btn btn-primary",click:function(){a(".activity-to-add").each(function(){a(this).find('input[type="checkbox"]').prop("checked")&&a(this).find("tr").clone(!0,!0).appendTo(b).css("display","")}),a(this).dialog("close"),e(b,g),f.change()}},{text:M.util.get_string("cancel","moodle"),class:"btn btn-secondary",click:function(){a(this).dialog("close")}}],open:function(){a(":focus").blur(),a('.activity-to-add input[type="checkbox"]').prop("checked",!1),a(".activities-to-add-list .section").addClass("expanded"),a(".activities-to-add-list").scrollTop(0),m.$selectedvalue.html(a(".activity-type").first().html()).data("cmtype",""),m.$selector.removeClass("expanded").addClass("collapsed"),m.$selectmenu.width(""),m.$search.val("").keyup(),n()}});a("#add-activities").click(function(){o.dialog("open")}),m.$selectmenu.click(function(){if(m.$selector.toggleClass("collapsed expanded"),m.$selector.is(".expanded")){var a=2*m.$dropdown.width()-m.$dropdown.prop("clientWidth");m.$selectmenu.width(Math.max(a,m.$selector.width()))}else m.$selectmenu.width("")}),a(".activity-type").click(function(){m.$selectedvalue.html(a(this).html()).data("cmtype",a(this).data("cmtype")),n()}),m.$search.keyup(function(){a(this).toggleClass("empty",""===a(this).val()),n()}),a(".search-remove").click(function(){m.$search.val("").keyup()}),a(".search-icon").click(function(){m.$search.focus()}),a(".activities-to-add-list .section .toggle-all").click(function(b){b.stopImmediatePropagation(),a(this).parents(".section").find('.activity-to-add:visible input[type="checkbox"]').prop("checked","select"==a(this).data("action"))}),a(".activities-to-add-list .section-header").click(function(){a(this).parents(".section").toggleClass("expanded"),n()})}}});
\ No newline at end of file
......@@ -148,12 +148,13 @@ define(['jquery', 'jqueryui', 'core/url', 'mod_randomactivity/orderabletable'],
$seed.attr('disabled', 'disabled');
var id = $form.find('[name=id]').val();
var group = $form.find('[name=group]').val();
var activities = $activities.val();
var nactivities = 0;
if (activities != '') {
nactivities = activities.split(' ').length;
}
$.ajax(baseurl + '/balanceseed.json.php?id=' + id + '&nactivities=' + nactivities)
$.ajax(baseurl + '/balanceseed.json.php?id=' + id + '&nactivities=' + nactivities + '&group=' + group)
.done(function(outcome) {
if (outcome.success) {
$seed.val(outcome.response.seed);
......@@ -169,9 +170,10 @@ define(['jquery', 'jqueryui', 'core/url', 'mod_randomactivity/orderabletable'],
// Button "Refresh assignees preview".
$('.refresh-assignees').click(function() {
var id = $form.find('[name=id]').val();
var group = $form.find('[name=group]').val();
var activities = $activities.val();
var seed = $seed.val();
$.ajax(baseurl + '/refresh.json.php?id=' + id + '&activities=' + activities + '&seed=' + seed)
$.ajax(baseurl + '/refresh.json.php?id=' + id + '&activities=' + activities + '&seed=' + seed + '&group=' + group)
.done(function(outcome) {
if (outcome.success) {
$table.find('tbody tr td:nth-child(3)').each(function(i) {
......
......@@ -44,6 +44,7 @@ class grade_observer {
$grade = $event->get_grade();
$gradeitem = $grade->grade_item;
$courseid = $gradeitem->courseid;
$userid = $grade->userid;
if ($gradeitem->itemtype == 'mod' && $gradeitem->itemmodule != 'randomactivity') {
$randomactivities = get_fast_modinfo($courseid, -1)->get_instances_of('randomactivity');
......@@ -51,9 +52,9 @@ class grade_observer {
foreach ($randomactivities as $cminfo) {
$modinstance = $DB->get_record('randomactivity', array( 'id' => $cminfo->instance ));
if ($modinstance->grade != 0 && ($modinstance->duedate == 0 || $modinstance->duedate >= time())) {
$cmid = randomactivity_get_assigned_activity($modinstance->activities, $grade->userid, $modinstance->seed);
$cmid = randomactivity_get_assigned_activity($cminfo, $modinstance->activities, $userid, $modinstance->seed);
if ($cmid == $gradedcm->id) {
randomactivity_update_grade($modinstance, $grade->userid, $grade);
randomactivity_update_grade($modinstance, $userid, $grade);
}
}
}
......
......@@ -90,6 +90,8 @@ $table->size = array(
null
);
$cminfo = get_fast_modinfo($course, -1)->get_cm($cm->id);
if ($userid == 0) {
$users = get_enrolled_users($context);
$table->id = 'gradestable';
......@@ -103,7 +105,7 @@ foreach ($users as $user) {
if ( has_capability( 'mod/randomactivity:manage', $context, $user ) ) {
$username = '<em>' . $username . '</em>';
}
$assignedcmid = randomactivity_get_assigned_activity($module->activities, $user->id, $module->seed);
$assignedcmid = randomactivity_get_assigned_activity($cminfo, $module->activities, $user->id, $module->seed);
$assignedcm = get_fast_modinfo($course, -1)->get_cm($assignedcmid);
$gradeobj = grade_get_grades($course->id, 'mod', 'randomactivity', $cm->instance, $user->id)->items[0]->grades[$user->id];
$grade = '<span value="' . $gradeobj->grade .'">' . $gradeobj->str_long_grade . '</span>';
......
......@@ -63,6 +63,12 @@ $string['dynamicdisplay'] = 'Dynamic display on course page';
$string['dynamicdisplay_help'] = 'If set to "Yes", this activity will display on the course page as the activity it points to. This will only affect students.';
$string['filters'] = 'Filters:';
$string['groupbyseeding'] = 'Group by seeding';
$string['grouping'] = 'grouping {$a}';
$string['groupmode'] = 'Group mode';
$string['groupmode_help'] = 'This activity is set to use groups. Members of a same group will be assigned to the same activity.<br>
If a grouping is set, then only the groups of this grouping will be considered.<br>
If a user doesn\'t belong to any group, or belongs to more than one group, they will be assigned individually.';
$string['groupmodedetails'] = 'Group mode ({$a}).';
$string['modulenotfound'] = 'Module not found';
$string['noactivityerror'] = 'No activity has been configured.';
$string['noactivitytoadd'] = 'No activity available to add.';
......@@ -86,6 +92,7 @@ students assigned to the first activity of one Random activity will be assigned
$string['seedingn'] = 'Seeding #{$a}';
$string['seedtobalance'] = 'Seed to balance users';
$string['seedtotimestamp'] = 'Seed to current timestamp';
$string['showonlymembersof'] = 'Show only members of:';
$string['unknown'] = 'Unknown';
$string['viewall'] = 'View all';
$string['viewingradebook'] = 'View in gradebook';
\ No newline at end of file
......@@ -123,6 +123,10 @@ function randomactivity_supports($feature) {
switch($feature) {
case FEATURE_MOD_INTRO :
return false;
case FEATURE_GROUPS :
return true;
case FEATURE_GROUPINGS :
return true;
case FEATURE_GRADE_HAS_GRADE :
return true;
case FEATURE_GRADE_OUTCOMES :
......@@ -219,20 +223,20 @@ function randomactivity_get_user_grades($modinstanceid, $userid = 0) {
global $DB;
$modinstance = $DB->get_record( 'randomactivity', array( 'id' => $modinstanceid ) );
$course = $modinstance->course;
$cminfo = get_fast_modinfo($course, -1)->get_instances_of('randomactivity')[$modinstance->id];
if ($userid != 0) {
$user = new stdClass();
$user->id = $userid;
$users = array( $user );
} else {
$cm = get_fast_modinfo($course, -1)->get_instances_of('randomactivity')[$modinstance->id];
$context = context_module::instance( $cm->id );
$context = context_module::instance( $cminfo->id );
$users = get_enrolled_users($context);
}
$grades = array();
foreach ($users as $user) {
$gradedetails = array( 'userid' => $user->id, 'rawgrade' => null, 'finalgrade' => null );
if ($modinstance->activities != '') {
$assignedcmid = randomactivity_get_assigned_activity($modinstance->activities, $user->id, $modinstance->seed);
$assignedcmid = randomactivity_get_assigned_activity($cminfo, $modinstance->activities, $user->id, $modinstance->seed);
$assignedcm = get_fast_modinfo($course, -1)->get_cm($assignedcmid);
$gradeitems = grade_get_grades($course, 'mod', $assignedcm->modname, $assignedcm->instance, $user->id)->items;
if (count( $gradeitems ) > 0) {
......@@ -292,7 +296,8 @@ function randomactivity_user_outline($course, $user, $cm, $modinstance) {
if ($modinstance->activities == '') {
$outline->info = '';
} else {
$assignedcmid = randomactivity_get_assigned_activity($modinstance->activities, $user->id, $modinstance->seed);
$cminfo = get_fast_modinfo($course, -1)->get_cm($cm->id);
$assignedcmid = randomactivity_get_assigned_activity($cminfo, $modinstance->activities, $user->id, $modinstance->seed);
$outline->info = '-> ' . randomactivity_activity_icon_and_name(get_fast_modinfo($course, -1)->get_cm($assignedcmid));
}
return $outline;
......@@ -326,7 +331,7 @@ function randomactivity_cm_info_dynamic(cm_info $cm) {
&& !has_capability('moodle/course:manageactivities', context_course::instance( $cm->course ))
&& $module->dynamicdisplay) {
// Change activity appearance to the one it will redirect to.
$redirectid = randomactivity_get_assigned_activity($module->activities, $USER->id, $module->seed);
$redirectid = randomactivity_get_assigned_activity($cm, $module->activities, $USER->id, $module->seed);
$redirectcm = get_fast_modinfo($cm->course, -1)->get_cm($redirectid);
$cm->set_name($redirectcm->get_formatted_name());
$cm->set_icon_url($redirectcm->get_icon_url());
......
......@@ -31,20 +31,29 @@ define('RANDOMACTIVITY_STATUS_ERROR', 2);
/**
* Returns the activity an user is assigned to.
* @param cm_info $cminfo Random activity course module info.
* @param string|array $activities The activity pool from which to draw.
* @param int $userid User id.
* @param int|string $seed Seed used for attribution.
* @return int|null Assigned course module id or null if none.
*/
function randomactivity_get_assigned_activity($activities, $userid, $seed) {
function randomactivity_get_assigned_activity($cminfo, $activities, $userid, $seed) {
if (!$activities) {
return null;
}
if (is_string($activities)) {
$activities = explode(' ', $activities);
}
$effectiveuserid = $userid;
if ($cminfo->effectivegroupmode != NOGROUPS) {
$groups = groups_get_all_groups($cminfo->course, $userid, $cminfo->groupingid);
if (count($groups) == 1) {
// Assign user with their group only if they are part of exactly one group.
$effectiveuserid = array_shift($groups)->id;
}
}
srand( substr( $seed, -9, 9 ) ); // Trim the seed to an int that is not too big.
$x = hexdec( substr( hash( 'md5', rand() + $userid ), 0, 4 ) );
$x = hexdec( substr( hash( 'md5', rand() + $effectiveuserid ), 0, 4 ) );
return $activities[$x % count( $activities )];
}
......@@ -53,19 +62,52 @@ function randomactivity_get_assigned_activity($activities, $userid, $seed) {
* @param string|array $activities The activity pool.
* @param int|string $seed Seed used for attribution.
* @param context $context Course module context.
* @param int $groupid Group id - if provided, only members of this group will be considered.
* @return array Assignees for every activity, indexed by cmid.
*/
function randomactivity_get_assignees($activities, $seed, $context) {
function randomactivity_get_assignees($activities, $seed, $context, $groupid = 0) {
$assignees = array();
$assignedgroups = array();
if ($activities != '') {
$cminfo = get_fast_modinfo($context->get_course_context()->instanceid, -1)->get_cm($context->instanceid);
foreach (get_enrolled_users($context) as $user) {
if (!has_capability('mod/randomactivity:manage', $context, $user)
&& !has_capability('mod/randomactivity:viewactivities', $context, $user)) {
$assignedcm = randomactivity_get_assigned_activity($activities, $user->id, $seed);
&& !has_capability('mod/randomactivity:viewactivities', $context, $user)
&& ($groupid == 0 || groups_is_member($groupid, $user->id))) {
$assignedcm = randomactivity_get_assigned_activity($cminfo, $activities, $user->id, $seed);
if (! isset($assignees[$assignedcm])) {
$assignees[$assignedcm] = array();
}
$assignees[$assignedcm][] = fullname($user);
if ($cminfo->effectivegroupmode == NOGROUPS) {
// Assign user individually.
$assignees[$assignedcm][] = fullname($user);
} else {
// This Random activity is set to use groups.
$groups = groups_get_all_groups($cminfo->course, $user->id, $cminfo->groupingid);
if (count($groups) == 1) {
// User belongs to exactly one group: assign them with their group.
$group = array_shift($groups);
if (! isset($assignedgroups[$assignedcm])) {
$assignedgroups[$assignedcm] = array();
}
$assignedgroups[$assignedcm][$group->id] = $group->name;
} else {
// User belongs to no group or more than one group: assign them individually.
$assignees[$assignedcm][] = fullname($user);
}
}
}
}
// Process assigned groups for a nice display.
foreach ($assignedgroups as $cmid => $cmgroups) {
foreach ($cmgroups as $id => $groupname) {
$groupmembers = array();
foreach (groups_get_members($id) as $member) {
$groupmembers[] = fullname($member);
}
$assignees[$cmid][] = '<span class="group-assignee" title="' . implode(', ', $groupmembers) . '">' .
'<i class="fa fa-fw fa-group"></i>&nbsp;' . $groupname .
'</span>';
}
}
}
......@@ -77,12 +119,13 @@ function randomactivity_get_assignees($activities, $seed, $context) {
* @param string|array $activities The activity pool.
* @param int|string $seed Seed used for attribution.
* @param context $context Course module context.
* @param int $groupid Group id - if provided, only members of this group will be considered.
* @return array Assignees for every activity.
*/
function randomactivity_get_assignees_formatted($activities, $seed, $context) {
function randomactivity_get_assignees_formatted($activities, $seed, $context, $groupid = 0) {
$ret = array();
if ($activities != '') {
$assignees = randomactivity_get_assignees($activities, $seed, $context);
$assignees = randomactivity_get_assignees($activities, $seed, $context, $groupid);
foreach (explode(' ', $activities) as $cmid) {
if (! isset($assignees[$cmid])) {
$cmassignees = get_string('none');
......
......@@ -27,6 +27,10 @@
margin-top: 1em;
}
.path-mod-randomactivity .activitytable .group-assignee {
cursor: default;
}
.path-mod-randomactivity #apply-assign-button {
background-color: red;
color: white;
......@@ -64,7 +68,7 @@
.path-mod-randomactivity .popup-dialog {
background-color: white;
z-index: 500;
z-index: 1000;
box-shadow: 4px 3px 4px lightblue;
border: 1px solid gray;
padding: 1em;
......@@ -244,6 +248,14 @@
display: none;
}
.path-mod-randomactivity .group-panel {
margin-bottom: 1em;
}
.path-mod-randomactivity .group-panel label {
display: none;
}
.path-mod-randomactivity #index-orderby-select .urlselect {
display: inline-block;
}
\ No newline at end of file
......@@ -25,6 +25,7 @@
Context variables required for this template:
* id Course module ID.
* group Currently selected group (0 for all groups).
* activities Space-separated list of course module IDs of current activities pool.
* seed Current seed.
* seedhelpbutton HTML fragment containing help button for seed.
......@@ -33,6 +34,7 @@
Example context (json):
{
"id": "2",
"group": "0",
"activities": "6 8 19",
"seed": "0",
"seedhelpbutton": "<a class=\"btn btn-link p-0\"><i class=\"icon fa fa-question-circle text-info fa-fw\"></i></a>",
......@@ -41,6 +43,7 @@
}}
<form id="form-randomactivity-activities" class="form-inline">
<input name="id" type="hidden" value="{{id}}">
<input name="group" type="hidden" value="{{group}}">
<input name="activities" type="hidden" value="{{activities}}">
<div id="form-seed">
{{# str}} seed, mod_randomactivity {{/ str}}{{{seedhelpbutton}}}
......
......@@ -25,12 +25,14 @@
Context variables required for this template:
* id Course module ID.
* group Currently selected group (0 for all groups).
* editmode Whether editing is turned on for the activities form.
* allowedit Whether editing can be turned on for the activities form.
Example context (json):
{
"id": "2",
"group": "0",
"editmode": true,
"allowedit": true
}
......@@ -45,12 +47,12 @@
<span class="button-icon">{{# pix}} reassign, mod_randomactivity {{/ pix}}</span>
{{# str}} applychangesreassign, mod_randomactivity {{/ str}}
</button>
<a id="cancel-button" class="btn btn-secondary" href="?id={{id}}">
<a id="cancel-button" class="btn btn-secondary" href="?id={{id}}{{# group}}&group={{group}}{{/ group}}">
{{# str}} cancel {{/ str}}
</a>
{{/ editmode}}
{{# allowedit}}
<a class="btn btn-secondary" href="?id={{id}}&edit=1">
<a class="btn btn-secondary" href="?id={{id}}&edit=1{{# group}}&group={{group}}{{/ group}}">
{{# pix}} edit, mod_randomactivity {{/ pix}}
{{# str}} edit {{/ str}}
</a>
......
......@@ -23,8 +23,8 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2021040900;
$plugin->version = 2021041500;
$plugin->requires = 2018112800;
$plugin->maturity = MATURITY_STABLE;
$plugin->release = '1.3.1';
$plugin->release = '1.4';
$plugin->component = 'mod_randomactivity';
\ No newline at end of file
......@@ -31,11 +31,13 @@ global $PAGE, $OUTPUT, $DB, $USER;
$id = required_param('id', PARAM_INT);
$edit = optional_param('edit', 0, PARAM_INT);
$group = optional_param('group', 0, PARAM_INT);
$cm = get_coursemodule_from_id( 'randomactivity', $id );
$course = $DB->get_record( 'course', array( 'id' => $cm->course ) );
$context = context_module::instance( $cm->id );
$module = $DB->get_record( 'randomactivity', array ( 'id' => $cm->instance ) );
$cminfo = get_fast_modinfo($course, -1)->get_cm($id);
// Page setup.
$PAGE->set_cm( $cm, $course, $module );
......@@ -56,7 +58,7 @@ if ( !has_capability('mod/randomactivity:manage', $context)
echo $OUTPUT->footer();
die();
}
$redirectid = randomactivity_get_assigned_activity($module->activities, $USER->id, $module->seed);
$redirectid = randomactivity_get_assigned_activity($cminfo, $module->activities, $USER->id, $module->seed);
$redirectcm = get_fast_modinfo($course, -1)->get_cm($redirectid);
if ($module->duedate > 0 && $module->duedate < time()) {
echo $OUTPUT->header();
......@@ -100,6 +102,26 @@ echo $OUTPUT->header();
echo $OUTPUT->heading_with_help($module->name, 'pluginname', 'randomactivity');
echo $OUTPUT->box_start();
// Group mode info / group selection.
$grouppanel = '';
if ($cminfo->effectivegroupmode != NOGROUPS) {
if ($cminfo->groupingid > 0) {
$groupingname = groups_get_all_groupings($course->id)[$cminfo->groupingid]->name;
$details = get_string('grouping', RANDOMACTIVITY, $groupingname);
} else {
$details = get_string('allgroups');
}
$grouppanel .= get_string('groupmodedetails', RANDOMACTIVITY, $details);
$grouppanel .= $OUTPUT->help_icon('groupmode', RANDOMACTIVITY);
} else {
if (count(groups_get_all_groups($course->id)) > 0) {
$grouppanel .= get_string('showonlymembersof', RANDOMACTIVITY);
$grouppanel .= groups_allgroups_course_menu($course, $PAGE->url, true, $group);
}
}
echo html_writer::nonempty_tag('div', $grouppanel, array('class' => 'group-panel'));
// Main activity pool table.
$table = new html_table();
$table->id = 'randomactivity-activities-table';
......@@ -139,7 +161,7 @@ if ($module->activities == '') {
} else {
// Populate table with current activities.
$i = 0;
$assignees = randomactivity_get_assignees_formatted($module->activities, $module->seed, $context);
$assignees = randomactivity_get_assignees_formatted($module->activities, $module->seed, $context, $group);
foreach (explode(' ', $module->activities) as $cmid) {
$cmassignees = $assignees[$i++];
try {
......@@ -156,6 +178,7 @@ echo html_writer::table( $table );
// Seed field and global hidden form definition.
$templatedata = new stdClass();
$templatedata->id = $id;
$templatedata->group = $group;
$templatedata->activities = $module->activities;
$templatedata->seed = $module->seed;
$templatedata->editmode = $editmode;
......@@ -220,6 +243,7 @@ if ($editmode) {
// Main buttons.
$templatedata = new stdClass();
$templatedata->id = $id;
$templatedata->group = $group;
$templatedata->editmode = $editmode;
$templatedata->allowedit = !$editmode && has_capability('mod/randomactivity:manage', $context);
echo $OUTPUT->render_from_template('mod_randomactivity/navigationbuttons', $templatedata);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment