Polished up badge view for users

This commit is contained in:
PMKuipers 2023-11-01 23:47:54 +01:00
parent 3fcf0095ea
commit dd7fa5f620
9 changed files with 191 additions and 86 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -96,6 +96,8 @@ export default {
dateexpire: "dateexpire", dateexpire: "dateexpire",
badgeinfo: "badgeinfo", badgeinfo: "badgeinfo",
badgeissuedstats: "badgeissuedstats", badgeissuedstats: "badgeissuedstats",
completion_incomplete: "completion_incomplete_badge",
completion_completed: "completion_completed_badge",
}, },
course: { course: {
completion_incomplete: "completion_incomplete", completion_incomplete: "completion_incomplete",
@ -2261,7 +2263,7 @@ export default {
}, },
data() { data() {
return { return {
txt: strings text: strings.badge,
}; };
}, },
computed: { computed: {
@ -2293,17 +2295,60 @@ export default {
} else { } else {
return ""; // no path return ""; // no path
} }
},
arcpath_progress(){
if(this.value.badge.completion){
const fraction = this.value.badge.completion.progress/this.value.badge.completion.count;
return this.arcpath(0,fraction);
} else {
return ""; // no path
}
},
badgeinprogress(){
return ( this.value.badge.issued
|| this.teachermode
|| (this.value.badge.completion
&& this.value.badge.completion.progress >= this.value.badge.completion.count)
);
} }
}, },
methods: { methods: {
arcpath(start, end) { arcpath(start, end) {
const r = 44; const r = 44;
const t1 = start * 2*π; const t1 = start * 2*π;
const Δ = end * 2*π; const Δ = (end * 2*π-0.01);
return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π); return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π);
}, },
addTargetBlank(html) {
const m = /^([^<]*\< *a +)(.*)/.exec(html);
if(m){
return `${m[1]} target="_blank" ${m[2]}`;
} else {
return html;
}
},
completion_icon_rq(complete) {
if (complete) {
return "check-square-o";
} else {
return "square-o";
}
},
completion_icon(complete) {
if (complete) {
return "check-circle";
} else {
return "times-circle";
}
},
status(complete) {
if (complete) {
return "complete";
} else {
return "incomplete";
}
}
}, },
template: ` template: `
<div :class="'r-item-badge r-item-filter r-completion-'+completion" v-b-tooltip.hover :title="value.badge.name"> <div :class="'r-item-badge r-item-filter r-completion-'+completion" v-b-tooltip.hover :title="value.badge.name">
@ -2318,12 +2363,18 @@ export default {
</template> </template>
<circle v-else-if="value.badge.issued" cx="50" cy="50" r="46" <circle v-else-if="value.badge.issued" cx="50" cy="50" r="46"
style="stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;"/> style="stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;"/>
<template v-else-if="value.badge.completion">
<circle cx="50" cy="50" r="44"
style="stroke: #ccc; stroke-width: 8; fill: #ddd; fill-opacity: 0.8;"/>
<path :d="arcpath_progress"
:style="'stroke-width: 8; stroke: var(--info); fill: none;'"/>
</template>
<circle v-else cx="50" cy="50" r="46" <circle v-else cx="50" cy="50" r="46"
stroke-dasharray="6 9" stroke-dasharray="6 9"
style="stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;"/> style="stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;"/>
<image class="badge-image" clip-path="circle() fill-box" <image class="badge-image" clip-path="circle() fill-box"
:href="value.badge.imageurl" x="12" y="12" width="76" height="76" :href="value.badge.imageurl" x="12" y="12" width="76" height="76"
:style="(value.badge.issued||teachermode)?'':'opacity: 0.4;'" /> :style="(badgeinprogress)?'':'opacity: 0.4;'" />
</svg></a> </svg></a>
<b-modal <b-modal
@ -2343,9 +2394,9 @@ export default {
</div> </div>
<div class="r-course-detail-header-right" v-if="!teachermode"> <div class="r-course-detail-header-right" v-if="!teachermode">
<div class="r-completion-detail-header"> <div class="r-completion-detail-header">
{{ txt.completion['completion_'+completion] }} {{ text['completion_'+completion] }}
<i v-b-popover.hover :class="'fa fa-'+issued_icon+' r-completion-'+completion" <i v-b-popover.hover :class="'fa fa-'+issued_icon+' r-completion-'+completion"
:title="txt.completion['completion_'+completion]"></i> :title="text['completion_'+completion]"></i>
</div> </div>
</div> </div>
</template> </template>
@ -2355,29 +2406,59 @@ export default {
</b-col><b-col cols="9"> </b-col><b-col cols="9">
<p>{{value.badge.description}}</p> <p>{{value.badge.description}}</p>
<ul v-if="value.badge.issued" class="list-unstyled pt-1 mb-1 border-grey border-top"> <ul v-if="value.badge.issued" class="list-unstyled pt-1 mb-1 border-grey border-top">
<li><strong><i class="fa fa-calendar-check-o r-completion-complete-pass"></i> <li><strong><i class="fa fa-calendar-check-o r-completion-complete-pass"></i>
{{txt.badge.dateissued}}:</strong> {{ value.badge.dateissued }}</li> {{text.dateissued}}:</strong> {{ value.badge.dateissued }}</li>
<li v-if='value.badge.dateexpired' <li v-if='value.badge.dateexpired'
><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> {{text.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">{{text.share_badge}}</a></strong> </li>
</ul> </ul>
<table v-if='value.badge.completion && !value.badge.issued' class="r-item-course-grade-details mb-2">
<tr v-if="value.badge.completion.types.length > 1">
<th colspan="2"><span v-html="value.badge.completion.title"></span></th>
</tr>
<template v-for='cgroup in value.badge.completion.types' >
<tr>
<td colspan="2" v-if="value.badge.completion.types.length > 1"
><span v-html="cgroup.title"></span></td>
<th colspan="2" v-else><span v-html="cgroup.title"></span></th>
</tr>
<template v-for='ci in cgroup.criteria'>
<tr>
<td class="pl-3"><span v-if='guestmode'><span v-html="ci.title"></span></span>
<a target='_blank' v-else-if='ci.link' :href='ci.link'
><span v-html="ci.title"></span></a>
<span v-else><span v-html="ci.title"></span></span>
<td><i :class="'fa fa-'+completion_icon(ci.completed)+' r-completion-'+status(ci.completed)"
:title="text['completion_'+status(ci.completed)]"></i>
</td>
</tr>
<template v-if="ci.requirements.length > 1">
<tr v-for="rq in ci.requirements">
<td class="pl-4" colspan="2"
><i :class="'fa fa-'+completion_icon_rq(rq.completed)+' r-completion-incomplete'"
:title="text['completion_'+status(rq.completed)]"></i>
<span class="t-badge-criteria-requirement"><span v-html="rq.title"></span></span></td>
</tr>
</template>
</template>
</template>
</table>
<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"
><span v-html='crit'></span></li></ul> ><span v-html='crit'></span></li></ul>
<p v-if="(!guestmode)"><strong><i class="fa fa-link"></i> <p v-if="(!guestmode)"><strong><i class="fa fa-link"></i>
<a :href="value.badge.infolink" target="_blank" <a :href="value.badge.infolink" target="_blank"
>{{ txt.badge.badgeinfo }}</a></strong></p> >{{ text.badgeinfo }}</a></strong></p>
<p v-if="teachermode && !guestmode" <p v-if="teachermode && !guestmode"
>{{txt.badge.badgeissuedstats}}:<br> >{{text.badgeissuedstats}}:<br>
<r-completion-bar v-model="issuestats" :width="150" :height="15"></r-completion-bar> <r-completion-bar v-model="issuestats" :width="150" :height="15"></r-completion-bar>
</p> </p>
</b-col></b-row> </b-col></b-row>
</b-container> </b-container>
</b-modal> </b-modal>
</div> </div>
`, `,
}); });
}, },

View File

@ -27,6 +27,7 @@ require_once($CFG->libdir.'/externallib.php');
use award_criteria; use award_criteria;
use \core_badges\badge; use \core_badges\badge;
use moodle_url;
/** /**
* Handle badge information in the same style as the other classes * Handle badge information in the same style as the other classes
@ -176,6 +177,7 @@ class badgeinfo {
"dateexpire" => new \external_value(PARAM_TEXT, 'date the badge will expire', VALUE_OPTIONAL), "dateexpire" => new \external_value(PARAM_TEXT, 'date the badge will expire', VALUE_OPTIONAL),
"uniquehash" => new \external_value(PARAM_TEXT, 'badge issue hash', VALUE_OPTIONAL), "uniquehash" => new \external_value(PARAM_TEXT, 'badge issue hash', VALUE_OPTIONAL),
"issuedlink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL), "issuedlink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL),
"active" => new \external_value(PARAM_BOOL, 'badge is available'),
], "Badge info", $value); ], "Badge info", $value);
} }
@ -208,6 +210,7 @@ class badgeinfo {
'completion' => $this->badge_completion_data($userid), 'completion' => $this->badge_completion_data($userid),
'issued' => $issued, 'issued' => $issued,
'infolink' => (new \moodle_url('/badges/overview.php', ['id' => $this->badge->id]))->out(false), 'infolink' => (new \moodle_url('/badges/overview.php', ['id' => $this->badge->id]))->out(false),
"active" => $this->badge->is_active(),
]; ];
@ -235,13 +238,14 @@ class badgeinfo {
'criteria' => new \external_multiple_structure(new \external_single_structure([ 'criteria' => new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'criterion title'), "title" => new \external_value(PARAM_RAW, 'criterion title'),
"description" => new \external_value(PARAM_RAW, 'criterion description'), "description" => new \external_value(PARAM_RAW, 'criterion description'),
"link"=> new \external_value(PARAM_RAW, 'link to criterion resource',VALUE_OPTIONAL),
"requirements" => new \external_multiple_structure(new \external_single_structure([ "requirements" => new \external_multiple_structure(new \external_single_structure([
"title" => new \external_value(PARAM_RAW, 'requirment title'), "title" => new \external_value(PARAM_RAW, 'requirment title'),
"completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not'), "completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not', VALUE_OPTIONAL),
]), "criterion specific requirements", VALUE_OPTIONAL), ]), "criterion specific requirements", VALUE_OPTIONAL),
"completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not'), "completed" => new \external_value(PARAM_BOOL, 'criterion is completed or not'),
]),'specific criteria'), ]),'specific criteria'),
"type" => new \external_value(PARAM_TEXT, 'any|all'), "title" => new \external_value(PARAM_RAW, 'type title'),
"aggregation" => new \external_value(PARAM_TEXT, 'any|all'), "aggregation" => new \external_value(PARAM_TEXT, 'any|all'),
"count" => new \external_value(PARAM_INT, 'effective number of critera for type progress'), "count" => new \external_value(PARAM_INT, 'effective number of critera for type progress'),
"progress" => new \external_value(PARAM_INT, 'effective number of completed criteria for type progress'), "progress" => new \external_value(PARAM_INT, 'effective number of completed criteria for type progress'),
@ -251,6 +255,7 @@ class badgeinfo {
"count" => new \external_value(PARAM_INT, 'total number of critera for progress'), "count" => new \external_value(PARAM_INT, 'total number of critera for progress'),
"progress" => new \external_value(PARAM_INT, 'number of completed criteria for progress'), "progress" => new \external_value(PARAM_INT, 'number of completed criteria for progress'),
"fraction" => new \external_value(PARAM_FLOAT, 'fraction of completed criteria as float'), "fraction" => new \external_value(PARAM_FLOAT, 'fraction of completed criteria as float'),
"title" => new \external_value(PARAM_RAW, 'completion title'),
],'badge completion information', $value); ],'badge completion information', $value);
} }
@ -262,60 +267,61 @@ class badgeinfo {
$badgeagg = $this->badge->get_aggregation_method(); $badgeagg = $this->badge->get_aggregation_method();
$types = []; $types = [];
$f = fopen("/tmp/badgedebug","a");
fputs($f,date("Y-m-d H:M:S")." Badge criteria\n");
fputs($f,print_r($this->badge->criteria,true)."\n\n");
fclose($f);
foreach ($this->badge->criteria as $type => $bc) { foreach ($this->badge->criteria as $type => $bc) {
$typeagg = $this->badge->get_aggregation_method($type); if ($type != BADGE_CRITERIA_TYPE_OVERALL) {
$typecrit = $this->get_award_subcriteria($bc,$userid); $typeagg = $this->badge->get_aggregation_method($type);
$typecrit = $this->get_award_subcriteria($bc,$userid);
$typecount = count($typecrit); $typecount = count($typecrit);
$typeprogress = 0; $typeprogress = 0;
foreach ($typecrit as $subcrit) { foreach ($typecrit as $subcrit) {
// Quickly check if the subcriteria are completed. // Quickly check if the subcriteria are completed.
if ($subcrit["completed"]) { if ($subcrit["completed"]) {
$typeprogress++; $typeprogress++;
}
} }
}
// Determine how to process the progress data, depending on the TYPE's aggregation. // Determine how to process the progress data, depending on the TYPE's aggregation.
if ($typeagg == BADGE_CRITERIA_AGGREGATION_ANY) { if ($typeagg == BADGE_CRITERIA_AGGREGATION_ANY) {
$typecount = 1; $typecount = 1;
$typeprogress = ($typeprogress > 0)?1:0; $typeprogress = ($typeprogress > 0)?1:0;
}
// Determine how to patch this data into the overall progress numbers, depending on the OVERALL aggregation.
if($badgeagg == BADGE_CRITERIA_AGGREGATION_ANY) {
/* If ANY completion overall, count only the criteria type with the highest completion percentage -.
Overwrite data if current type is more complete */
$typefraction = $typeprogress / $typecount;
if ($typefraction > $fraction) {
$fraction = $typefraction;
$count = $typecount;
$progress = $typeprogress;
} }
} else {
/* If ALL completion overall, just add it up to the total */
$count += $typecount;
$progress += $typeprogress;
}
$typeinfo = [ // Determine how to patch this data into the overall progress numbers, depending on the OVERALL aggregation.
'type' => $type, if($badgeagg == BADGE_CRITERIA_AGGREGATION_ANY) {
'aggregation' => ($typeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any", /* If ANY completion overall, count only the criteria type with the highest completion percentage -.
'criteria' => $typecrit, Overwrite data if current type is more complete */
'count' => $typecount, $typefraction = ($typecount > 0)?($typeprogress / $typecount):0;
'progress' => $typeprogress, if ($typefraction > $fraction || ($fraction == 0 && $typecount > $count)) {
"fraction" => $typefraction, $fraction = $typefraction;
]; $count = $typecount;
$types[] = $typeinfo; $progress = $typeprogress;
}
} else {
/* If ALL completion overall, just add it up to the total */
$count += $typecount;
$progress += $typeprogress;
}
$aggrgation_handle = ($typeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
$typeinfo = [
'title' => ucfirst(get_string("criteria_descr_$type","badges", get_string($aggrgation_handle,"core"))),
'aggregation' => $aggrgation_handle,
'criteria' => $typecrit,
'count' => $typecount,
'progress' => $typeprogress,
"fraction" => $typefraction,
];
$types[] = $typeinfo;
}
} }
$aggrgation_handle = ($badgeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any";
return [ return [
"types" => $types, "types" => $types,
"aggregation" => ($typeagg == BADGE_CRITERIA_AGGREGATION_ALL)?"all":"any", "title" => ucfirst(get_string("criteria_descr_0","badges", mb_strtolower(get_string($aggrgation_handle,"core")))),
"aggregation" => $aggrgation_handle,
"count" => $count, "count" => $count,
"progress" => $progress, "progress" => $progress,
"fraction" => $fraction, "fraction" => $fraction,
@ -388,7 +394,7 @@ class badgeinfo {
* *
*/ */
protected function get_award_subcriteria(award_criteria $crit, $userid = null) : array { protected function get_award_subcriteria(award_criteria $crit, $userid = null) : array {
global $DB; global $DB, $CFG;
$list = []; $list = [];
if ($crit->criteriatype == BADGE_CRITERIA_TYPE_ACTIVITY) { if ($crit->criteriatype == BADGE_CRITERIA_TYPE_ACTIVITY) {
@ -444,7 +450,7 @@ class badgeinfo {
if (isset($p["bydate"])) { if (isset($p["bydate"])) {
$date = $data->timemodified; $date = $data->timemodified;
$check_date = ($date <= $p['bydate']); $check_date = ($date <= $p['bydate']);
$subcrit["requirements"]["completion"]["completed"] = $check_date; $subcrit["requirements"]["bydate"]["completed"] = $check_date;
} }
$subcrit["completed"] = $modcompleted && $check_date; $subcrit["completed"] = $modcompleted && $check_date;
@ -471,7 +477,7 @@ class badgeinfo {
if(isset($userid)) { if(isset($userid)) {
$crit = $DB->get_record('badge_manual_award', array('issuerrole' => $p['role'], 'recipientid' => $userid, 'badgeid' => $crit->badgeid)); $crit = $DB->get_record('badge_manual_award', array('issuerrole' => $p['role'], 'recipientid' => $userid, 'badgeid' => $crit->badgeid));
$subcrit["completed"] = $crit; $subcrit["completed"] = $crit !== false;
} }
$list[] = $subcrit; $list[] = $subcrit;
} }
@ -500,17 +506,18 @@ class badgeinfo {
$subcrit = [ $subcrit = [
"title" => $course->fullname, "title" => $course->fullname,
"link" => (new moodle_url($CFG->wwwroot."/course/view.php",["id" => $course->id]))->out(),
"description" => $description, "description" => $description,
"requirements" => [ "requirements" => [
'completion' => [ 'completion' => [
'title' => get_string('coursecompleted','core'), 'title' => get_string('coursecompleted','completion'),
] ]
] ]
]; ];
if (isset($p["grade"])) { if (isset($p["grade"])) {
$subcrit["requirements"]["grade"] = [ $subcrit["requirements"]["grade"] = [
'title' => get_string('criteria_descr_bydate','badges',$p["grade"]), 'title' => get_string('criteria_descr_grade','badges',$p["grade"]),
]; ];
} }
@ -521,21 +528,24 @@ class badgeinfo {
} }
if(isset($userid)) { if(isset($userid)) {
$info = new \completion_info($course); $coursecompletion = new \completion_completion(["userid" => $userid, "course" => $course->id]);
$coursecompleted = $info->is_course_complete($userid); $coursecompleted = $coursecompletion->is_complete();
$subcrit["requirements"]["completion"]["completed"] = $coursecompleted; $f = fopen("/tmp/debug","a+");
fputs($f,$course->fullname." ".($coursecompleted?"(COMPLETED)":"(NOT completed)")."\n");
fputs($f,print_r($coursecompletion,true));
fclose($f);
$subcrit["requirements"]["completion"]["completed"] = (bool) $coursecompleted;
$check_grade = true; $check_grade = true;
if (isset($p["grade"])) { if (isset($p["grade"])) {
$grade = \grade_get_course_grade($userid,$course->id); $grade = \grade_get_course_grade($userid,$course->id);
$check_grade = ($grade->grade >= $p['grade']); $check_grade = ($grade->grade >= $p['grade']);
$subcrit["requirements"]["completion"]["completed"] = $check_grade; $subcrit["requirements"]["grade"]["completed"] = (bool) $check_grade;
} }
$check_date = true; $check_date = true;
if (isset($p["bydate"])) { if (isset($p["bydate"])) {
$completion = new \completion_completion(["userid" => $userid, "course" => $course->id]); $check_date = ((bool) $coursecompletion->timecompleted) && ($coursecompletion->timecompleted <= $p["bydate"]);
$check_date = ($completion->timecompleted <= $p["bydate"]); $subcrit["requirements"]["bydate"]["completed"] = (bool) $check_date;
$subcrit["requirements"]["completion"]["completed"] = $check_date;
} }
$subcrit["completed"] = $coursecompleted && $check_grade && $check_date; $subcrit["completed"] = $coursecompleted && $check_grade && $check_date;
@ -590,7 +600,7 @@ class badgeinfo {
$sql = "SELECT 1 FROM {user} u " . $join . " WHERE u.id = :userid $where"; $sql = "SELECT 1 FROM {user} u " . $join . " WHERE u.id = :userid $where";
$completed = $DB->record_exists_sql($sql, $sqlparams); $completed = $DB->record_exists_sql($sql, $sqlparams);
$subcrit["completed"] = $completed; $subcrit["completed"] = (bool) $completed;
} }
$list[] = $subcrit; $list[] = $subcrit;
} }
@ -601,13 +611,14 @@ class badgeinfo {
$title = get_string('error:nosuchbadge', 'badges'); $title = get_string('error:nosuchbadge', 'badges');
$description = get_string('error:nosuchbadge', 'badges'); $description = get_string('error:nosuchbadge', 'badges');
} else { } else {
$title = \html_writer::tag('b', '"' . $badgename . '"');; $title = $badgename;
$description = \html_writer::tag('b', '"' . $badgename . '"');; $description = \html_writer::tag('b', '"' . $badgename . '"');;
} }
$subcrit = [ $subcrit = [
"title" => $title, "title" => $title,
"description" => $description, "description" => $description,
"link" => (new \moodle_url($CFG->wwwroot."/badges/overview.php",["id" => $p["badge"]]))->out(),
"requirements" => [] "requirements" => []
]; ];
@ -616,10 +627,11 @@ class badgeinfo {
// See if the user has earned this badge. // See if the user has earned this badge.
if($badge) { if($badge) {
$awarded = $DB->get_record('badge_issued', array('badgeid' => $p['badge'], 'userid' => $userid)); $awarded = $DB->get_record('badge_issued', array('badgeid' => $p['badge'], 'userid' => $userid));
$awarded = isset($awarded);
} else { } else {
$awarded = false; $awarded = false;
} }
$subcrit["completed"] = $awarded; $subcrit["completed"] = (bool)$awarded;
} }
$list[] = $subcrit; $list[] = $subcrit;
} }
@ -642,11 +654,7 @@ class badgeinfo {
if(isset($userid)) { if(isset($userid)) {
$cohort = $DB->get_record('cohort', array('id' => $p['cohort'])); $cohort = $DB->get_record('cohort', array('id' => $p['cohort']));
if(\cohort_is_member($cohort->id, $userid)) { $ismember = (bool) \cohort_is_member($cohort->id, $userid);
$ismember = true;
} else {
$ismember = false;
}
$subcrit["completed"] = $ismember; $subcrit["completed"] = $ismember;
} }
$list[] = $subcrit; $list[] = $subcrit;
@ -706,7 +714,7 @@ class badgeinfo {
$proficiency = $uc->get('proficiency'); $proficiency = $uc->get('proficiency');
} }
$subcrit["completed"] = $proficiency; $subcrit["completed"] = (bool) $proficiency;
} }
$list[] = $subcrit; $list[] = $subcrit;
} }

View File

@ -707,6 +707,10 @@
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
.path-local-treestudyplan .t-badge-criteria-requirement,
.features-treestudyplan .t-badge-criteria-requirement {
color: var(--gray);
}
.path-local-treestudyplan .r-report-tabs .list-group-item-action, .path-local-treestudyplan .r-report-tabs .list-group-item-action,
.features-treestudyplan .r-report-tabs .list-group-item-action { .features-treestudyplan .r-report-tabs .list-group-item-action {
width: inherit; width: inherit;

View File

@ -180,6 +180,8 @@ $string["completion_completed"] = "Completed";
$string["completion_good"] = "Good"; $string["completion_good"] = "Good";
$string["completion_excellent"] = "Excellent"; $string["completion_excellent"] = "Excellent";
$string["completion_passed"] = "Passed"; $string["completion_passed"] = "Passed";
$string["completion_incomplete_badge"] = "Not issued";
$string["completion_completed_badge"] = "Issued";
$string["incomplete"] = 'Not started'; $string["incomplete"] = 'Not started';
$string["completed"] = 'Completed'; $string["completed"] = 'Completed';

View File

@ -177,6 +177,8 @@ $string["completion_completed"] = "Voltooid";
$string["completion_good"] = "Goed"; $string["completion_good"] = "Goed";
$string["completion_excellent"] = "Uitstekend"; $string["completion_excellent"] = "Uitstekend";
$string["completion_passed"] = "Behaald"; $string["completion_passed"] = "Behaald";
$string["completion_incomplete_badge"] = "Niet uitgegeven";
$string["completion_completed_badge"] = "Uitgegeven";
$string["incomplete"] = 'Niet gestart'; $string["incomplete"] = 'Niet gestart';
$string["completed"] = 'Voltooid'; $string["completed"] = 'Voltooid';

View File

@ -603,6 +603,10 @@
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
.t-badge-criteria-requirement {
color: var(--gray);
}
.r-report-tabs .list-group-item-action { .r-report-tabs .list-group-item-action {
width: inherit; width: inherit;
} }

View File

@ -707,6 +707,10 @@
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
} }
.path-local-treestudyplan .t-badge-criteria-requirement,
.features-treestudyplan .t-badge-criteria-requirement {
color: var(--gray);
}
.path-local-treestudyplan .r-report-tabs .list-group-item-action, .path-local-treestudyplan .r-report-tabs .list-group-item-action,
.features-treestudyplan .r-report-tabs .list-group-item-action { .features-treestudyplan .r-report-tabs .list-group-item-action {
width: inherit; width: inherit;