Upgraded site-badges to display properly

This commit is contained in:
PMKuipers 2023-06-03 00:01:18 +02:00
parent b9243d9ddb
commit c12396f9c2
7 changed files with 193 additions and 27 deletions

View File

@ -30,7 +30,18 @@ export default {
unsubmitted: "unsubmitted",
nogrades: "nogrades",
unknown: "unknown",
},
completion: {
completion_completed: "completion_completed",
completion_incomplete: "completion_incomplete",
},
badge: {
share_badge: "share_badge",
dateissued: "dateissued",
dateexpire: "dateexpire",
badgeinfo: "badgeinfo",
}
});
/************************************
@ -1640,22 +1651,88 @@ export default {
},
data() {
return {
txt: strings
};
},
computed: {
completion() {
return this.value.badge.issued?"completed":"incomplete";
},
issued_icon(){
switch(this.value.badge.issued){
default: // "nogrades":
return "circle-o";
case true:
return "check";
}
},
},
methods: {
},
template: `
<div :class="'r-item-badge r-item-filter completion-'+completion" v-b-tooltip.hover :title="value.badge.name">
<svg class="r-badge-backdrop" width='50px' height='50px'>
<circle cx="25px" cy="25px" r="24px" />
</svg>
<img class="badge-image" :src="value.badge.imageurl">
<div :class="'r-item-badge r-item-filter r-completion-'+completion" v-b-tooltip.hover :title="value.badge.name">
<a v-b-modal="'r-item-badge-details-'+value.id"
><svg class="r-badge-backdrop " width='50px' height='50px' viewBox="0 0 100 100">
<title>{{value.badge.name}}</title>
<circle v-if="teachermode" cx="50" cy="50" r="46"
style="stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;"/>
<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;"/>
<circle v-else cx="50" cy="50" r="46"
stroke-dasharray="6 9"
style="stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;"/>
<image class="badge-image" clip-path="circle() fill-box"
:href="value.badge.imageurl" x="12" y="12" width="76" height="76"
:style="(value.badge.issued||teachermode)?'':'opacity: 0.4;'" />
</svg></a>
<b-modal
:id="'r-item-badge-details-'+value.id"
:title="value.badge.name"
size="lg"
ok-only
centered
scrollable
>
<template #modal-header>
<div>
<h1><i class="fa fa-certificate"></i>
<a :href="(!guestmode)?(value.badge.infolink):undefined" target="_blank"
>{{ value.badge.name }}</a
></h1>
</div>
<div class="r-course-detail-header-right">
<div class="r-completion-detail-header">
{{ txt.completion['completion_'+completion] }}
<i v-b-popover.hover :class="'fa fa-'+issued_icon+' r-completion-'+completion"
:title="txt.completion['completion_'+completion]"></i>
</div>
</div>
</template>
<b-container fluid>
<b-row><b-col cols="3">
<img :src="value.badge.imageurl"/>
</b-col><b-col cols="9">
<p>{{value.badge.description}}</p>
<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>
{{txt.badge.dateissued}}:</strong> {{ value.badge.dateissued }}</li>
<li v-if='value.badge.dateexpired'
><strong><i class="fa fa-calendar-times-o r-completion-complete"></i>
{{txt.badge.dateexpired}}:</strong> {{ value.badge.dateexpired }}</li>
<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>
</ul>
<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"
><span v-html='crit'></span></li></ul>
<p v-if="(!guestmode)"><strong><i class="fa fa-link"></i>
<a :href="value.badge.infolink">{{ txt.badge.badgeinfo }}</a></strong></p>
</b-col></b-row>
</b-container>
</b-modal>
</div>
`,
});
},

View File

@ -169,6 +169,16 @@ export default {
invalid: {
error: 'error',
},
completion: {
completion_completed: "completion_completed",
completion_incomplete: "completion_incomplete",
},
badge: {
share_badge: "share_badge",
dateissued: "dateissued",
dateexpire: "dateexpire",
badgeinfo: "badgeinfo",
}
});
@ -1934,7 +1944,7 @@ export default {
return !(["start",].includes(this.value.type));
},
hasContext() {
return ['start','junction','finish',].includes(this.value.type);
return ['junction','finish'].includes(this.value.type);
}
},
created(){
@ -2456,21 +2466,57 @@ export default {
props: {
value : {
type: Object,
default: function(){ return {};},
default: function(){ return { badge: {}};},
},
},
data() {
return {
txt: strings,
};
},
methods: {
},
template: `
<div class='t-item-badge t-item-filter' v-b-tooltip.hover :title="value.badge.name">
<svg class="t-badge-backdrop" width='50px' height='50px'>
<circle cx="25px" cy="25px" r="24px" />
<svg class="t-badge-backdrop " width='50px' height='50px' viewBox="0 0 100 100">
<title>{{value.badge.name}}</title>
<circle cx="50" cy="50" r="46"
style="stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;"/>
<image class="badge-image" clip-path="circle() fill-box"
:href="value.badge.imageurl" x="12" y="12" width="76" height="76"/>
</svg>
<img class="badge-image" :src="value.badge.imageurl">
<a class="t-item-config badge"
v-b-modal="'t-item-badge-details-'+value.id" href="#" @click.prevent=""><i class="fa fa-gear"></i></a>
<b-modal
:id="'t-item-badge-details-'+value.id"
:title="value.badge.name"
size="lg"
ok-only
centered
scrollable
>
<template #modal-header>
<div>
<h1><i class="fa fa-certificate"></i>
<a :href="value.badge.infolink" target="_blank"
>{{ value.badge.name }}</a
></h1>
</div>
</template>
<b-container fluid>
<b-row><b-col cols="3">
<img :src="value.badge.imageurl"/>
</b-col><b-col cols="9">
<p>{{value.badge.description}}</p>
<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"
><span v-html='crit'></span></li></ul>
<p><strong><i class="fa fa-link"></i>
<a :href="value.badge.infolink">{{ txt.badge.badgeinfo }}</a></strong></p>
</b-col></b-row>
</b-container>
</b-modal>
</div>
`,
});

View File

@ -43,9 +43,11 @@ class badgeinfo {
public static function editor_structure($value=VALUE_REQUIRED){
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of badge'),
"infolink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL),
"name" => new \external_value(PARAM_TEXT, 'badge name'),
"status" => new \external_value(PARAM_TEXT, 'badge status'),
"locked" => new \external_value(PARAM_TEXT, 'badge lock status'),
"criteria" => new \external_multiple_structure(new \external_value(PARAM_RAW, 'criteria text'),'badge criteria',VALUE_OPTIONAL),
"description"=> new \external_value(PARAM_TEXT, 'badge description'),
"imageurl" => new \external_value(PARAM_TEXT, 'url of badge image'),
],"Badge info",$value);
@ -55,11 +57,18 @@ class badgeinfo {
{
$context = ($this->badge->type == BADGE_TYPE_SITE) ? \context_system::instance() : \context_course::instance($this->badge->courseid);
// If the user is viewing another user's badge and doesn't have the right capability return only part of the data.
$criteria = [];
foreach($this->badge->get_criteria() as $bc){
$criteria[] = $bc->get_title()." ".$bc->get_details();
}
$model = [
'id' => $this->badge->id,
'infolink' => (new \moodle_url('/badges/overview.php', ['id' => $this->badge->id]))->out(false),
'name' => $this->badge->name,
'status' => self::STATUSINFO[$this->badge->status],
'locked' => self::LOCKEDINFO[$this->badge->status],
'criteria' => $criteria,
'description' => $this->badge->description,
'imageurl' => \moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $this->badge->id, '/','f1')->out(false),
];
@ -70,10 +79,14 @@ class badgeinfo {
{
return new \external_single_structure([
"id" => new \external_value(PARAM_INT, 'id of badge'),
"infolink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL),
"name" => new \external_value(PARAM_TEXT, 'badge name'),
"criteria" => new \external_multiple_structure(new \external_value(PARAM_RAW, 'criteria text'),'badge criteria',VALUE_OPTIONAL),
"description"=> new \external_value(PARAM_TEXT, 'badge description'),
"imageurl" => new \external_value(PARAM_TEXT, 'url of badge image'),
"issued" => new \external_value(PARAM_BOOL, 'badge is issued'),
"dateissued" => new \external_value(PARAM_TEXT, 'date the badge was issued',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),
"issuedlink" => new \external_value(PARAM_TEXT, 'badge issue information link', VALUE_OPTIONAL),
],"Badge info",$value);
@ -87,18 +100,28 @@ class badgeinfo {
$issued = $this->badge->is_issued($userid);
// If the user is viewing another user's badge and doesn't have the right capability return only part of the data.
$criteria = [];
foreach($this->badge->get_criteria() as $bc){
$criteria[] = $bc->get_title()."".$bc->get_details();
}
$badge = [
'id' => $this->badge->id,
'name' => $this->badge->name,
'description' => $this->badge->description,
'imageurl' => \moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $this->badge->id, '/','f1')->out(false),
'criteria' => $criteria,
'issued' => $issued,
'infolink' => (new \moodle_url('/badges/overview.php', ['id' => $this->badge->id]))->out(false),
];
if($issued) {
$issueinfo = $DB->get_record('badge_issued', array('badgeid' => $this->badge->id, 'userid' => $userid));
$badge['dateissued'] = userdate($issueinfo->dateissued,"%e %b %G");
if($issueinfo->expiredate){
$badge['dateexpire'] = userdate($issueinfo->dateexpire,"%e %b %G");
}
$badge['uniquehash'] = $issueinfo->uniquehash;
$badge['issuedlink'] = new \moodle_url('/badges/badge.php', array('hash' => $issueinfo->uniquehash));
$badge['issuedlink'] = (new \moodle_url('/badges/badge.php', ['hash' => $issueinfo->uniquehash]))->out(false);
}
return $badge;

View File

@ -616,13 +616,18 @@ class studyplanservice extends \external_api
public static function list_badges()
{
//TODO: Include course badges somehow... Just site badges is not enough
$systemcontext = webservicehelper::system_context();
$result = [];
$badges = badges_get_badges(BADGE_TYPE_SITE,"timemodified");
foreach ($badges as $badge) {
$result[] = (new badgeinfo($badge))->editor_model();
// TODO: Add config option to list only active badges
// if($badge->is_active()){
$result[] = (new badgeinfo($badge))->editor_model();
// }
//TODO: Include course badges somehow... Just site badges is not enough
}
return $result;

View File

@ -382,7 +382,7 @@ ul.t-toolbox li {
color: #009900;
}
.t-item-badge i {
.t-item-badge svg {
color: #ddaa00;
}
@ -412,6 +412,14 @@ a.t-item-config {
right: -5px;
}
a.t-item-config.badge {
top: -5px;
right: -5px;
font-size: 16px;
}
a.t-item-course-config {
font-size: 16pt;
vertical-align: middle;
@ -463,12 +471,6 @@ a.t-item-course-config {
transform: translate(-50%, -50%);
}
.t-item-badge svg.t-badge-backdrop circle {
stroke: black;
stroke-width: 2px;
fill: #ccc;
}
.l-leaderline-linewrapper {
width: 0;
@ -660,13 +662,12 @@ a.t-item-course-config {
stroke: black;
stroke-width: 2px;
fill: #ccc;
}
.r-studyplan-line-wrapper {
width: 0;
height: 0;
position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `abcomsolute`) */
}
.r-item-module-children {
@ -773,7 +774,7 @@ table.r-item-course-grade-details td {
.t-timing-past,
.r-timing-past {
color: darkgreen;
color: var(--purple);
}
.t-timing-present,
.r-timing-present {
@ -802,7 +803,7 @@ table.r-item-course-grade-details td {
.t-timing-indicator.timing-past,
.r-timing-indicator.timing-past {
background-color: #3a3;
background-color: var(--purple);
}
.t-timing-indicator.timing-present,
@ -952,3 +953,7 @@ table.r-item-course-grade-details td {
.s-edit-mod-form [data-fieldtype=submit] { display: none ! important; }
.s-edit-mod-form.genericonly form > fieldset:not(#id_general) { display: none ! important; }
.border-grey {
border-color: #aaa;
}

View File

@ -244,3 +244,8 @@ $string["aggregation_overall_all"] = "Complete all of the categories";
$string["aggregation_overall_any"] = "Complete one or more of the categories";
$string["aggregation_all"] = "Complete all";
$string["aggregation_any"] = "Complete one or more";
$string["share_badge"] = "Share badge";
$string["dateissued"] = "Issued on";
$string["dateexpire"] = "Expires on";
$string["badgeinfo"] = "Badge details";

View File

@ -247,3 +247,8 @@ $string["aggregation_overall_all"] = "Behaal alle categorieë";
$string["aggregation_overall_any"] = "Behaal één of meer categorieën";
$string["aggregation_all"] = "Alles behalen";
$string["aggregation_any"] = "Eén of meer behalen";
$string["share_badge"] = "Bewijs delen";
$string["dateissued"] = "Afgegeven op";
$string["dateexpire"] = "Veloopt op";
$string["badgeinfo"] = "Meer details";