This commit is contained in:
PMKuipers 2023-07-04 23:38:08 +02:00
parent 8fd188af3a
commit 252cb8cb2a
6 changed files with 90 additions and 59 deletions

View File

@ -661,17 +661,25 @@ export default {
</b-col> </b-col>
<b-col md="11"> <b-col md="11">
<b-card-body class="align-items-center"> <b-card-body class="align-items-center">
<r-progress-circle v-if='value.course.completion' <template v-if='value.course.completion'>
:value='value.course.completion.progress' <r-progress-circle v-if='["progress","incomplete"].includes(value.completion)'
:max='value.course.completion.count' :value='value.course.completion.progress'
:min='0' :max='value.course.completion.count'
:class="'r-course-result r-completion-'+value.completion" :min='0'
:title="text['completion_'+value.completion]" :class="'r-course-result r-completion-'+value.completion"
></r-progress-circle> :title="text['completion_'+value.completion]"
<i v-else v-b-popover.top ></r-progress-circle>
:class="'r-course-result fa fa-'+completion_icon(value.completion)+ <i v-else v-b-popover.top
' r-completion-'+value.completion" :class="'r-course-result fa fa-'+completion_icon(value.completion)+
:title="text['completion_'+value.completion]"></i> ' r-completion-'+value.completion"
:title="text['completion_'+value.completion]"></i>
</template>
<template v-else>
<i v-b-popover.top
:class="'r-course-result fa fa-'+completion_icon(value.completion)+
' r-completion-'+value.completion"
:title="text['completion_'+value.completion]"></i>
</template>
<a v-b-modal="'r-item-course-details-'+value.id" <a v-b-modal="'r-item-course-details-'+value.id"
:href="(!guestmode)?('/course/view.php?id='+value.course.id):'#'" :href="(!guestmode)?('/course/view.php?id='+value.course.id):'#'"
@click.prevent.stop='' @click.prevent.stop=''
@ -698,13 +706,17 @@ export default {
<div class="r-completion-detail-header"> <div class="r-completion-detail-header">
<template v-if='value.course.completion'> <template v-if='value.course.completion'>
{{text['completion_'+value.completion]}} {{text['completion_'+value.completion]}}
<r-progress-circle <r-progress-circle v-if='["progress","incomplete"].includes(value.completion)'
:value='value.course.completion.progress' :value='value.course.completion.progress'
:max='value.course.completion.count' :max='value.course.completion.count'
:min='0' :min='0'
:title="text['completion_'+value.completion]" :title="text['completion_'+value.completion]"
:class="'r-progress-circle-popup r-completion-'+value.completion" :class="'r-progress-circle-popup r-completion-'+value.completion"
></r-progress-circle> ></r-progress-circle>
<i v-else v-b-popover.top
:class="'fa fa-'+completion_icon(value.completion)+
' r-completion-'+value.completion"
:title="text['completion_'+value.completion]"></i>
</template> </template>
<template v-else> <template v-else>
{{text['completion_'+value.completion]}} {{text['completion_'+value.completion]}}
@ -905,12 +917,14 @@ export default {
<template v-for='cgroup in value.conditions'> <template v-for='cgroup in value.conditions'>
<tr> <tr>
<th colspan='2'>{{cgroup.title}}</th> <th colspan='2'>{{cgroup.title}}</th>
<th><r-progress-circle <th><r-progress-circle v-if="cgroup.progress < cgroup.count"
:value='cgroup.progress' :value='cgroup.progress'
:max='cgroup.count' :max='cgroup.count'
:class="'r-completion-'+cgroup.status" :class="'r-completion-'+cgroup.status"
:title="text['completion_'+cgroup.status]" :title="text['completion_'+cgroup.status]"
></r-progress-circle></th> ></r-progress-circle>
<i v-else :class="'fa fa-check-circle r-completion-'+cgroup.status"></i>
</th>
</tr> </tr>
<tr v-for='ci in cgroup.items'> <tr v-for='ci in cgroup.items'>
<td><span v-if='guestmode'>{{ci.title}}</span> <td><span v-if='guestmode'>{{ci.title}}</span>
@ -2042,7 +2056,7 @@ export default {
><strong><i class="fa fa-calendar-times-o r-completion-complete"></i> ><strong><i class="fa fa-calendar-times-o r-completion-complete"></i>
{{txt.badge.dateexpired}}:</strong> {{ value.badge.dateexpired }}</li> {{txt.badge.dateexpired}}:</strong> {{ value.badge.dateexpired }}</li>
<li><strong><i class="fa fa-share-alt r-completion-complete-pass"></i> <li><strong><i class="fa fa-share-alt r-completion-complete-pass"></i>
<a href="value.badge.issuedlink">{{txt.badge.share_badge}}</a></strong> </li> <a :href="value.badge.issuedlink">{{txt.badge.share_badge}}</a></strong> </li>
</ul> </ul>
<ul class="list-unstyled w-100 border-grey border-top border-bottom pt-1 pb-1 mb-1" <ul class="list-unstyled w-100 border-grey border-top border-bottom pt-1 pb-1 mb-1"
v-if="value.badge.criteria"><li v-for="crit in value.badge.criteria" v-if="value.badge.criteria"><li v-for="crit in value.badge.criteria"

View File

@ -135,7 +135,7 @@ class corecompletioninfo {
} }
public function editor_model() { public function editor_model() {
global $DB, $COMPLETION_CRITERIA_TYPES; global $DB, $CFG, $COMPLETION_CRITERIA_TYPES;
$conditions = []; $conditions = [];
$aggregation = "all"; // default $aggregation = "all"; // default
@ -211,7 +211,7 @@ class corecompletioninfo {
$details['requirement'][] = get_string('markingyourselfcomplete', 'completion'); $details['requirement'][] = get_string('markingyourselfcomplete', 'completion');
} elseif ($cm->completion == COMPLETION_TRACKING_AUTOMATIC) { } elseif ($cm->completion == COMPLETION_TRACKING_AUTOMATIC) {
if ($cm->completionview) { if ($cm->completionview) {
$modulename = core_text::strtolower(get_string('modulename', $criteria->module)); $modulename = \core_text::strtolower(get_string('modulename', $criteria->module));
$details['requirement'][] = get_string('viewingactivity', 'completion', $modulename); $details['requirement'][] = get_string('viewingactivity', 'completion', $modulename);
} }
@ -240,7 +240,7 @@ class corecompletioninfo {
"type" => get_string('coursegrade', 'completion'), "type" => get_string('coursegrade', 'completion'),
"criteria" => get_string('graderequired', 'completion'), "criteria" => get_string('graderequired', 'completion'),
// TODO: convert to selected representation (letter, percentage, etc) // TODO: convert to selected representation (letter, percentage, etc)
"requirement" => get_string('graderequired', 'completion').": ".format_float($criteria->gradepass, $decimalpoints), "requirement" => get_string('graderequired', 'completion').": ".format_float($criteria->gradepass, 1),
"status" => "", "status" => "",
]; ];
} }
@ -387,8 +387,9 @@ class corecompletioninfo {
} }
else if ($type == COMPLETION_CRITERIA_TYPE_GRADE){ else if ($type == COMPLETION_CRITERIA_TYPE_GRADE){
// Make sure we provide the current course grade // Make sure we provide the current course grade
$iinfo['grade'] = $this->get_course_grade($userid); $iinfo['grade'] = floatval($iinfo['details']['status']);
if($iinfo["grade"] > 0){ if($iinfo["grade"] > 0){
$iinfo["grade"] = format_float($iinfo["grade"], 1);
$iinfo["status"] = $completion->is_complete()?"complete-pass":"complete-fail"; $iinfo["status"] = $completion->is_complete()?"complete-pass":"complete-fail";
if ($cinfo["status"] == "incomplete"){ if ($cinfo["status"] == "incomplete"){
$cinfo["status"] = "progress"; $cinfo["status"] = "progress";
@ -440,7 +441,7 @@ class corecompletioninfo {
{ {
$scale = $gi->load_scale(); $scale = $gi->load_scale();
$grade = $gi->get_final($userid); // Get the grade for the specified user $grade = (object)$gi->get_final($userid); // Get the grade for the specified user
$result = new \stdClass; $result = new \stdClass;
// Check if the final grade is available and numeric (safety check) // Check if the final grade is available and numeric (safety check)
if(!empty($grade) && !empty($grade->finalgrade) && is_numeric($grade->finalgrade)){ if(!empty($grade) && !empty($grade->finalgrade) && is_numeric($grade->finalgrade)){
@ -571,10 +572,10 @@ class corecompletioninfo {
* Returns the percentage completed by a certain user, returns null if no completion data is available. * Returns the percentage completed by a certain user, returns null if no completion data is available.
* *
* @param int $userid The id of the user, 0 for the current user * @param int $userid The id of the user, 0 for the current user
* @return null|float The percentage, or null if completion is not supported in the course, * @return null|\stdClass The percentage, or null if completion is not supported in the course,
* or there are no activities that support completion. * or there are no activities that support completion.
*/ */
function get_advanced_progress_percentage($userid){ function get_advanced_progress_percentage($userid):\stdClass {
// First, let's make sure completion is enabled. // First, let's make sure completion is enabled.
if (!$this->completion->is_enabled()) { if (!$this->completion->is_enabled()) {
@ -591,44 +592,39 @@ class corecompletioninfo {
$critcount = []; $critcount = [];
// Before we check how many modules have been completed see if the course has completed. // Before we check how many modules have been completed see if the course has completed.
if ($this->completion->is_course_complete($userid)) { // count all completions, but treat
$completed = $count; foreach($completions as $completion){
} $crit = $completion->get_criteria();
else {
// count all completions, but treat
foreach($completions as $completion){
$crit = $completion->get_criteria();
// Make a new object for the type if it's not already there // Make a new object for the type if it's not already there
$type = $crit->criteriatype; $type = $crit->criteriatype;
if(!array_key_exists($type,$critcount)){ if(!array_key_exists($type,$critcount)){
$critcount[$type] = new \stdClass; $critcount[$type] = new \stdClass;
$critcount[$type]->count = 0; $critcount[$type]->count = 0;
$critcount[$type]->completed = 0; $critcount[$type]->completed = 0;
$critcount[$type]->aggregation = $this->completion->get_aggregation_method($type); $critcount[$type]->aggregation = $this->completion->get_aggregation_method($type);
}
// Get a reference to the counter object for this type
$typecount =& $critcount[$type];
$typecount->count += 1;
if($crit->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
// get the cm data object
$cm = $this->modinfo->get_cm($crit->moduleinstance);
// retrieve data for this object
$data = $this->completion->get_data($cm, false, $userid);
// Count complete, but failed as incomplete too...
if (($data->completionstate == COMPLETION_INCOMPLETE) || ($data->completionstate == COMPLETION_COMPLETE_FAIL)) {
$typecount->completed += 0;
} else {
$typecount->completed += 1;
}
}
else {
if($completion->is_complete()){
$typecount->completed += 1;
}
}
} }
// Get a reference to the counter object for this type
$typecount =& $critcount[$type];
$typecount->count += 1;
if($crit->criteriatype == COMPLETION_CRITERIA_TYPE_ACTIVITY) {
// get the cm data object
$cm = $this->modinfo->get_cm($crit->moduleinstance);
// retrieve data for this object
$data = $this->completion->get_data($cm, false, $userid);
// Count complete, but failed as incomplete too...
if (($data->completionstate == COMPLETION_INCOMPLETE) || ($data->completionstate == COMPLETION_COMPLETE_FAIL)) {
$typecount->completed += 0;
} else {
$typecount->completed += 1;
}
}
else {
if($completion->is_complete()){
$typecount->completed += 1;
}
}
} }
// Now that we have all completions sorted by type, we can be smart about how to do the count // Now that we have all completions sorted by type, we can be smart about how to do the count

View File

@ -136,12 +136,16 @@ class studentstudyplanservice extends \external_api
public static function get_invited_studyplan($invitekey) public static function get_invited_studyplan($invitekey)
{ {
global $CFG, $DB; global $CFG, $DB;
$invite = $DB->get_record_select("local_treestudyplan_invit", $DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"), ['invitekey' => $invitekey]); $invite = $DB->get_record_select("local_treestudyplan_invit", $DB->sql_compare_text("invitekey"). " = " . $DB->sql_compare_text(":invitekey"), ['invitekey' => $invitekey]);
if(empty($invite)){ if(empty($invite)){
return []; return [];
} }
// Validate context now
\external_api::validate_context(\context_system::instance());
$userid = $invite->user_id; $userid = $invite->user_id;
$map = []; $map = [];
@ -206,7 +210,11 @@ class studentstudyplanservice extends \external_api
public static function get_own_studyplan($id=null) public static function get_own_studyplan($id=null)
{ {
global $CFG, $DB, $USER; global $USER;
// Validate this call in the system context.
\external_api::validate_context(\context_system::instance());
$userid = $USER->id; $userid = $USER->id;
$studyplans = studyplan::find_for_user($userid); $studyplans = studyplan::find_for_user($userid);

View File

@ -141,6 +141,7 @@ $string['completion_passed'] = "Passed";
$string['cfg_grades'] = 'Configure grade & scale interpretation'; $string['cfg_grades'] = 'Configure grade & scale interpretation';
$string['cfg_plans'] = 'Manage study plans'; $string['cfg_plans'] = 'Manage study plans';
$string['cfg_help'] = "Studyplan plugin documentation";
$string['cfg_grades_desc_head'] = 'Configure how reuslts for goals are presented.'; $string['cfg_grades_desc_head'] = 'Configure how reuslts for goals are presented.';
$string['cfg_grades_desc'] = 'If failed results are supported, the threshold for progression is relevant. All results below this threshold will be considered failed. Empty results or 0 will always be read as not started. <br> The completion threshold always takes preference if it is equal to or lower than th progression threshold.'; $string['cfg_grades_desc'] = 'If failed results are supported, the threshold for progression is relevant. All results below this threshold will be considered failed. Empty results or 0 will always be read as not started. <br> The completion threshold always takes preference if it is equal to or lower than th progression threshold.';

View File

@ -143,6 +143,7 @@ $string['completion_passed'] = "Behaald";
$string['cfg_grades'] = 'Configureer betekenis van beoordelingen en schalen'; $string['cfg_grades'] = 'Configureer betekenis van beoordelingen en schalen';
$string['cfg_plans'] = 'Studieplannen beheren'; $string['cfg_plans'] = 'Studieplannen beheren';
$string['cfg_help'] = "Studieplan plugin documentatie (Engels)";
$string['cfg_grades_desc_head'] = 'Stel hier in op welke manier resultaten voor doelen worden geinterpreteerd.'; $string['cfg_grades_desc_head'] = 'Stel hier in op welke manier resultaten voor doelen worden geinterpreteerd.';
$string['cfg_grades_desc'] = 'Bij gebruik van onvoldoende beoordelingen is de drempelwaarde voor ontwikkeling relevant. Bij waarden onder deze drempel, wordt het resultaat weergegeven als onvoldoende. Een lege beoordeling wordt altijd gezien als niet gestart. <br> Als de drempel voor voltooing kleiner dan of gelijk is aan die voor ontwikkeling, dan krijgt die voor voltooing voorrang'; $string['cfg_grades_desc'] = 'Bij gebruik van onvoldoende beoordelingen is de drempelwaarde voor ontwikkeling relevant. Bij waarden onder deze drempel, wordt het resultaat weergegeven als onvoldoende. Een lege beoordeling wordt altijd gezien als niet gestart. <br> Als de drempel voor voltooing kleiner dan of gelijk is aan die voor ontwikkeling, dan krijgt die voor voltooing voorrang';

View File

@ -215,4 +215,15 @@ if ($hassiteconfig) {
get_string('cfg_grades', 'local_treestudyplan', null, true), get_string('cfg_grades', 'local_treestudyplan', null, true),
$CFG->wwwroot . '/local/treestudyplan/cfg_grades.php')); $CFG->wwwroot . '/local/treestudyplan/cfg_grades.php'));
/**************************************
*
* Add the help link (Temporary until a better place is found)
*
**************************************/
$ADMIN->add('local_treestudyplan', new admin_externalpage(
'local_treestudyplan_doc',
get_string('cfg_help', 'local_treestudyplan', null, true),
$CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm'));
} }