Implemented student view. Added feedback view
This commit is contained in:
parent
82e92eed45
commit
456e9b503e
2
amd/build/report-viewer-components.min.js
vendored
2
amd/build/report-viewer-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
amd/build/util/string-helper.min.js
vendored
2
amd/build/util/string-helper.min.js
vendored
|
@ -1,3 +1,3 @@
|
||||||
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.load_stringkeys=function(string_keys){var _loop2=function(idx){var stringkeys=[];for(var i in string_keys[idx]){var parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}getstr_func(stringkeys).then((function(strings){for(var _i in strings){var s=strings[_i];string_keys[idx][_i].text=s}}))};for(var idx in string_keys)_loop2(idx);return string_keys},_exports.load_strings=function(strings){var _loop=function(idx){var stringkeys=[];for(var handle in strings[idx]){var parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}getstr_func(stringkeys).then((function(str){var i=0;for(var _key in strings[idx])strings[idx][_key]=str[i],i++}))};for(var idx in strings)_loop(idx);return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,(function(m,m1){return m1&&values.hasOwnProperty(m1)?values[m1]:m}))};var getstr_func=void 0!==_str.getStrings?_str.getStrings:_str.get_strings}));
|
define("local_treestudyplan/util/string-helper",["exports","core/str"],(function(_exports,_str){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.load_stringkeys=function(string_keys){for(let idx in string_keys){let stringkeys=[];for(const i in string_keys[idx]){let parts=string_keys[idx][i].textkey.split("$"),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}getstr_func(stringkeys).then((function(strings){for(const i in strings){const s=strings[i];string_keys[idx][i].text=s}}))}return string_keys},_exports.load_strings=function(strings){for(let idx in strings){let stringkeys=[];for(const handle in strings[idx]){let parts=strings[idx][handle].split(/[$@]/),identifier=parts[0],component=parts.length>1?parts[1]:"local_treestudyplan";stringkeys.push({key:identifier,component:component})}getstr_func(stringkeys).then((function(str){let i=0;for(const handle in strings[idx])strings[idx][handle]=str[i],i++}))}return strings},_exports.strformat=function(str,values){return str.replace(/\{(\w+)\}/g,((m,m1)=>m1&&values.hasOwnProperty(m1)?values[m1]:m))};const getstr_func=void 0!==_str.getStrings?_str.getStrings:_str.get_strings}));
|
||||||
|
|
||||||
//# sourceMappingURL=string-helper.min.js.map
|
//# sourceMappingURL=string-helper.min.js.map
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"string-helper.min.js","sources":["../../src/util/string-helper.js"],"sourcesContent":["import {get_strings} from 'core/str';\nimport {getStrings} from 'core/str';\n\n/* Determine the proper getstrings function to use (MDL4.3+ recommends use of getStrings, which is jquery independent) */\nconst getstr_func = (getStrings !== undefined)?getStrings:get_strings;\n\n/**\n * Load the translation of strings from a strings object\n * @param {Object} strings The map of strings\n * @returns {Object} The map with strings loaded in\n */\nexport function load_strings(strings){\n for(let idx in strings){\n let stringkeys = [];\n for(const handle in strings[idx]){\n const key = strings[idx][handle];\n let parts = key.split(/[$@]/);\n let identifier = parts[0];\n let component = (parts.length > 1)?parts[1]:'local_treestudyplan';\n stringkeys.push({ key: identifier, component: component});\n }\n getstr_func(stringkeys).then(function(str){\n let i = 0;\n for(const key in strings[idx]){\n strings[idx][key] = str[i];\n i++;\n }\n });\n }\n\n return strings;\n}\n\n/**\n * Load the translation of strings from a strings object based on keys\n * Used for loading values for a drop down menu or the like\n * @param {Object} string_keys The map of stringkeys\n * @returns {Object} The map with strings loaded in\n */\nexport function load_stringkeys(string_keys){\n for(let idx in string_keys){\n // Get text strings for condition settings\n let stringkeys = [];\n for(const i in string_keys[idx]){\n const key = string_keys[idx][i].textkey;\n let parts = key.split(\"$\");\n let identifier = parts[0];\n let component = (parts.length > 1)?parts[1]:'local_treestudyplan';\n stringkeys.push({ key: identifier, component: component});\n }\n getstr_func(stringkeys).then(function(strings){\n for(const i in strings) {\n const s = strings[i];\n const l = string_keys[idx][i];\n l.text = s;\n }\n });\n }\n return string_keys;\n}\n\n/**\n * String formatting function - replaces {name} in string by value of same key in values parameter\n * @param {string} str String t\n * @param {object} values Object containing keys to replace {key} strings with\n * @returns Formatted string\n */\nexport function strformat(str,values) {\n return str.replace(/\\{(\\w+)\\}/g, (m, m1) => {\n if (m1 && values.hasOwnProperty(m1)) {\n return values[m1];\n } else {\n return m;\n }\n });\n}"],"names":["string_keys","idx","stringkeys","i","parts","textkey","split","identifier","component","length","push","key","getstr_func","then","strings","s","text","handle","str","values","replace","m","m1","hasOwnProperty","undefined","getStrings","get_strings"],"mappings":"0LAuCgCA,iCACpBC,SAEAC,WAAa,OACb,IAAMC,KAAMH,YAAYC,KAAK,KAEzBG,MADQJ,YAAYC,KAAKE,GAAGE,QAChBC,MAAM,KAClBC,WAAaH,MAAM,GACnBI,UAAaJ,MAAMK,OAAS,EAAGL,MAAM,GAAG,sBAC5CF,WAAWQ,KAAK,CAAEC,IAAKJ,WAAYC,UAAWA,YAElDI,YAAYV,YAAYW,MAAK,SAASC,aAC9B,IAAMX,MAAKW,QAAS,KACdC,EAAID,QAAQX,IACRH,YAAYC,KAAKE,IACzBa,KAAOD,WAdjB,IAAId,OAAOD,mBAAPC,YAkBDD,4CA/CkBc,4BACjBb,SACAC,WAAa,OACb,IAAMe,UAAWH,QAAQb,KAAK,KAE1BG,MADQU,QAAQb,KAAKgB,QACTX,MAAM,QAClBC,WAAaH,MAAM,GACnBI,UAAaJ,MAAMK,OAAS,EAAGL,MAAM,GAAG,sBAC5CF,WAAWQ,KAAK,CAAEC,IAAKJ,WAAYC,UAAWA,YAElDI,YAAYV,YAAYW,MAAK,SAASK,SAC9Bf,EAAI,MACJ,IAAMQ,QAAOG,QAAQb,KACrBa,QAAQb,KAAKU,MAAOO,IAAIf,GACxBA,YAbR,IAAIF,OAAOa,cAAPb,YAkBDa,qCAqCeI,IAAIC,eACnBD,IAAIE,QAAQ,cAAc,SAACC,EAAGC,WAC7BA,IAAMH,OAAOI,eAAeD,IACrBH,OAAOG,IAEPD,UApEbT,iBAA8BY,IAAfC,gBAA0BA,gBAAWC"}
|
{"version":3,"file":"string-helper.min.js","sources":["../../src/util/string-helper.js"],"sourcesContent":["import {get_strings} from 'core/str';\nimport {getStrings} from 'core/str';\n\n/* Determine the proper getstrings function to use (MDL4.3+ recommends use of getStrings, which is jquery independent) */\nconst getstr_func = (getStrings !== undefined)?getStrings:get_strings;\n\n/**\n * Load the translation of strings from a strings object\n * @param {Object} strings The map of strings\n * @returns {Object} The map with strings loaded in\n */\nexport function load_strings(strings){\n for(let idx in strings){\n let stringkeys = [];\n for(const handle in strings[idx]){\n const key = strings[idx][handle];\n let parts = key.split(/[$@]/);\n let identifier = parts[0];\n let component = (parts.length > 1)?parts[1]:'local_treestudyplan';\n stringkeys.push({ key: identifier, component: component});\n }\n getstr_func(stringkeys).then(function(str){\n let i = 0;\n for(const handle in strings[idx]){\n strings[idx][handle] = str[i];\n i++;\n }\n });\n }\n\n return strings;\n}\n\n/**\n * Load the translation of strings from a strings object based on keys\n * Used for loading values for a drop down menu or the like\n * @param {Object} string_keys The map of stringkeys\n * @returns {Object} The map with strings loaded in\n */\nexport function load_stringkeys(string_keys){\n for(let idx in string_keys){\n // Get text strings for condition settings\n let stringkeys = [];\n for(const i in string_keys[idx]){\n const key = string_keys[idx][i].textkey;\n let parts = key.split(\"$\");\n let identifier = parts[0];\n let component = (parts.length > 1)?parts[1]:'local_treestudyplan';\n stringkeys.push({ key: identifier, component: component});\n }\n getstr_func(stringkeys).then(function(strings){\n for(const i in strings) {\n const s = strings[i];\n const l = string_keys[idx][i];\n l.text = s;\n }\n });\n }\n return string_keys;\n}\n\n/**\n * String formatting function - replaces {name} in string by value of same key in values parameter\n * @param {string} str String t\n * @param {object} values Object containing keys to replace {key} strings with\n * @returns Formatted string\n */\nexport function strformat(str,values) {\n return str.replace(/\\{(\\w+)\\}/g, (m, m1) => {\n if (m1 && values.hasOwnProperty(m1)) {\n return values[m1];\n } else {\n return m;\n }\n });\n}"],"names":["string_keys","idx","stringkeys","i","parts","textkey","split","identifier","component","length","push","key","getstr_func","then","strings","s","text","handle","str","values","replace","m","m1","hasOwnProperty","undefined","getStrings","get_strings"],"mappings":"0LAuCgCA,iBACxB,IAAIC,OAAOD,YAAY,KAEnBE,WAAa,OACb,MAAMC,KAAMH,YAAYC,KAAK,KAEzBG,MADQJ,YAAYC,KAAKE,GAAGE,QAChBC,MAAM,KAClBC,WAAaH,MAAM,GACnBI,UAAaJ,MAAMK,OAAS,EAAGL,MAAM,GAAG,sBAC5CF,WAAWQ,KAAK,CAAEC,IAAKJ,WAAYC,UAAWA,YAElDI,YAAYV,YAAYW,MAAK,SAASC,aAC9B,MAAMX,KAAKW,QAAS,OACdC,EAAID,QAAQX,GACRH,YAAYC,KAAKE,GACzBa,KAAOD,aAIdf,4CA/CkBc,aACrB,IAAIb,OAAOa,QAAQ,KACfZ,WAAa,OACb,MAAMe,UAAWH,QAAQb,KAAK,KAE1BG,MADQU,QAAQb,KAAKgB,QACTX,MAAM,QAClBC,WAAaH,MAAM,GACnBI,UAAaJ,MAAMK,OAAS,EAAGL,MAAM,GAAG,sBAC5CF,WAAWQ,KAAK,CAAEC,IAAKJ,WAAYC,UAAWA,YAElDI,YAAYV,YAAYW,MAAK,SAASK,SAC9Bf,EAAI,MACJ,MAAMc,UAAUH,QAAQb,KACxBa,QAAQb,KAAKgB,QAAUC,IAAIf,GAC3BA,cAKLW,qCAqCeI,IAAIC,eACnBD,IAAIE,QAAQ,cAAc,CAACC,EAAGC,KAC7BA,IAAMH,OAAOI,eAAeD,IACrBH,OAAOG,IAEPD,WApEbT,iBAA8BY,IAAfC,gBAA0BA,gBAAWC"}
|
|
@ -136,6 +136,19 @@ export default {
|
||||||
student_from_plan_enrolled: "student_from_plan_enrolled",
|
student_from_plan_enrolled: "student_from_plan_enrolled",
|
||||||
students_from_plan_enrolled: "students_from_plan_enrolled",
|
students_from_plan_enrolled: "students_from_plan_enrolled",
|
||||||
},
|
},
|
||||||
|
competency: {
|
||||||
|
competency_not_configured: "competency_not_configured",
|
||||||
|
configure_competency: "configure_competency",
|
||||||
|
when: "when",
|
||||||
|
required: "required",
|
||||||
|
points: "points@core_grades",
|
||||||
|
heading: "competency_heading",
|
||||||
|
details: "competency_details",
|
||||||
|
results: "results",
|
||||||
|
unrated: "unrated",
|
||||||
|
progress: "completion_progress",
|
||||||
|
view_feedback: "view_feedback",
|
||||||
|
},
|
||||||
pageinfo: {
|
pageinfo: {
|
||||||
edit: 'period_edit',
|
edit: 'period_edit',
|
||||||
fullname: 'studyplan_name',
|
fullname: 'studyplan_name',
|
||||||
|
@ -1150,6 +1163,20 @@ export default {
|
||||||
' r-completion-'+value.completion"
|
' r-completion-'+value.completion"
|
||||||
:title="text['completion_'+value.completion]"></i>
|
:title="text['completion_'+value.completion]"></i>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if='value.course.competency'>
|
||||||
|
<r-progress-circle v-if='["failed", "progress","incomplete"].includes(value.completion)'
|
||||||
|
:value='value.course.competency.progress'
|
||||||
|
:max='value.course.competency.count'
|
||||||
|
:min='0'
|
||||||
|
:class="'r-course-result r-completion-'+value.completion"
|
||||||
|
:icon='circle_icon(value.completion)'
|
||||||
|
:title="text['completion_'+value.completion]"
|
||||||
|
></r-progress-circle>
|
||||||
|
<i v-else 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>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<i v-b-popover.top
|
<i v-b-popover.top
|
||||||
:class="'r-course-result fa fa-'+completion_icon(value.completion)+
|
:class="'r-course-result fa fa-'+completion_icon(value.completion)+
|
||||||
|
@ -1222,12 +1249,17 @@ export default {
|
||||||
v-model='value.course.completion'
|
v-model='value.course.completion'
|
||||||
:course='value.course'
|
:course='value.course'
|
||||||
:guestmode='guestmode'></r-item-studentcompletion>
|
:guestmode='guestmode'></r-item-studentcompletion>
|
||||||
|
<r-item-student-course-competency
|
||||||
|
v-if='!!value.course.competency'
|
||||||
|
v-model='value.course.competency'
|
||||||
|
:item='value'
|
||||||
|
></r-item-student-course-competency>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
</b-card></div>
|
</b-card></div>
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
//TAG: Selected activities dispaly
|
//Selected activities dispaly
|
||||||
Vue.component('r-item-studentgrades',{
|
Vue.component('r-item-studentgrades',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -1324,7 +1356,7 @@ export default {
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
//TAG: Core completion version of student course info
|
// Core completion version of student course info
|
||||||
Vue.component('r-item-studentcompletion',{
|
Vue.component('r-item-studentcompletion',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -1479,6 +1511,208 @@ export default {
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//TAG: STUDENT Course competency
|
||||||
|
Vue.component('r-item-student-course-competency',{
|
||||||
|
props: {
|
||||||
|
value : {
|
||||||
|
type: Object,
|
||||||
|
default: function(){ return {};},
|
||||||
|
},
|
||||||
|
guestmode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: function(){ return { id: null};},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
text: strings.competency,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasCompletions() {
|
||||||
|
if(this.value.conditions) {
|
||||||
|
for(const cgroup of this.value.conditions){
|
||||||
|
if(cgroup.items && cgroup.items.length > 0){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
completion_icon(competency) {
|
||||||
|
if (competency.proficient && competency.courseproficient) {
|
||||||
|
return "check-circle";
|
||||||
|
} else if (competency.proficient) {
|
||||||
|
return "check";
|
||||||
|
} else if (competency.proficient === false) {
|
||||||
|
return "times-circle";
|
||||||
|
} else {
|
||||||
|
return "circle-o";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
completion_tag(competency){
|
||||||
|
if (competency.proficient && competency.courseproficient) {
|
||||||
|
return "completed";
|
||||||
|
} else if (competency.proficient) {
|
||||||
|
return "completed";
|
||||||
|
} else if (competency.proficient === false) {
|
||||||
|
return "failed";
|
||||||
|
} else if (competency.progress) {
|
||||||
|
return "progress";
|
||||||
|
} else {
|
||||||
|
return "incomplete";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
pathtags(competency) {
|
||||||
|
const path = competency.path;
|
||||||
|
let s = "";
|
||||||
|
for (const ix in path) {
|
||||||
|
const p = path[ix];
|
||||||
|
if ( ix > 0) {
|
||||||
|
s += " / ";
|
||||||
|
}
|
||||||
|
let url;
|
||||||
|
if (p.type =='competency') {
|
||||||
|
url = `/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${p.id}`;
|
||||||
|
} else {
|
||||||
|
url = this.competencyurl(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
s += `<a href="${url}" target="_blank">${p.title}</a>`;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
},
|
||||||
|
competencyurl(c) {
|
||||||
|
return `/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${c.id}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<table class="r-item-course-competency-list">
|
||||||
|
<tr v-if="value.competencies.length == 0">
|
||||||
|
<td colspan='2'>{{text.competencies_not_configured}}!
|
||||||
|
<br><a :href="'/admin/tool/lp/coursecompetencies.php?courseid='+item.course.id" target='_blank'>{{text.configure_competencies}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<template v-else>
|
||||||
|
<tr v-for='c in value.competencies'>
|
||||||
|
<td :colspan="(c.details)?1:2">
|
||||||
|
<a href="#" v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.title'></span></a>
|
||||||
|
</td>
|
||||||
|
<td class='details' v-if="c.details">
|
||||||
|
<a href="#" v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.details'></span></a>
|
||||||
|
</td>
|
||||||
|
<td :colspan="(c.required)?1:2">
|
||||||
|
<span :class="'r-completion-'+completion_tag(c)">
|
||||||
|
<template v-if="!c.progress && !c.count">
|
||||||
|
<i :class="'fa fa-'+completion_icon(c)" :title="text['completion_'+completion_tag(c)]"></i>
|
||||||
|
{{ (c.proficient === null)?text.unrated:c.grade }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<r-progress-circle
|
||||||
|
:value='c.progress'
|
||||||
|
:max='c.count'
|
||||||
|
:min='0'
|
||||||
|
:class="'r-completion-'+completion_tag(c)"
|
||||||
|
:title="text['completion_'+completion_tag(c)]"
|
||||||
|
></r-progress-circle>
|
||||||
|
{{ (c.proficient === null)?((c.progress)?text.progress:text.unrated):c.grade }}
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td v-if="c.required">
|
||||||
|
<span class="text-danger" v-if="c.required">{{ text.required }}</span>
|
||||||
|
</td>
|
||||||
|
<td v-if="c.feedback">
|
||||||
|
<a v-b-modal="'r-competency-feedback-'+c.id"
|
||||||
|
href="#"
|
||||||
|
>{{ text["view_feedback"]}}</a>
|
||||||
|
<b-modal
|
||||||
|
:id="'r-competency-feedback-'+c.id"
|
||||||
|
size="sm"
|
||||||
|
ok-only
|
||||||
|
centered
|
||||||
|
scrollable
|
||||||
|
>
|
||||||
|
<template #modal-header>
|
||||||
|
<h2><i class="fa fa-puzzle-piece"></i>{{ c.title }}</h2><br>
|
||||||
|
</template>
|
||||||
|
<span v-html="c.feedback"></span>
|
||||||
|
</b-modal>
|
||||||
|
</td>
|
||||||
|
<b-modal :id="'modal-competency-id-'+c.id"
|
||||||
|
size="lg"
|
||||||
|
ok-only
|
||||||
|
centered
|
||||||
|
scrollable
|
||||||
|
>
|
||||||
|
<template #modal-header>
|
||||||
|
<div>
|
||||||
|
<h1><i class="fa fa-puzzle-piece"></i>
|
||||||
|
<a :href="'/admin/tool/lp/competencies.php?competencyid='+c.id" target="_blank"
|
||||||
|
>{{c.title}} {{c.details}} </a
|
||||||
|
></h1>
|
||||||
|
<div><span v-html="pathtags(c)"></span></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="mb-2" v-if="c.description"><span v-html='c.description'></span></div>
|
||||||
|
|
||||||
|
<template v-if="c.rule && c.children">
|
||||||
|
<div>{{ c.ruleoutcome }} {{ text.when}} <span v-html="c.rule.toLocaleLowerCase()"></span></div>
|
||||||
|
<table v-if="c.children" class='r-item-course-competency-list'>
|
||||||
|
<tr class='t-item-course-competency-headers'>
|
||||||
|
<th colspan="2">{{text.heading}}</th>
|
||||||
|
<th colspan="3">{{text.results}}</th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cc in c.children">
|
||||||
|
<td :colspan="(c.details)?1:2" >
|
||||||
|
<a :href='competencyurl(c)' target="_blank"><span v-html='cc.title'></span></a>
|
||||||
|
</td>
|
||||||
|
<td class='details' v-if="cc.details">
|
||||||
|
<a :href='competencyurl(c)' target="_blank"><span v-html='cc.details'></span></a>
|
||||||
|
</td>
|
||||||
|
<td><span :class="'r-completion-'+completion_tag(cc)"
|
||||||
|
><i :class="'fa fa-'+completion_icon(cc)" :title="text['completion_'+completion_tag(cc)]"></i>
|
||||||
|
{{ (cc.proficient === null)?text.unrated:cc.grade }}</span></td>
|
||||||
|
<td><span class="text-info">{{ cc.points }} {{ text.points }}</span></td>
|
||||||
|
<td><span class="text-danger" v-if='cc.required'>{{ text.required }}</span></td>
|
||||||
|
<td v-if="cc.feedback">
|
||||||
|
<a v-b-modal="'r-competency-feedback-'+cc.id"
|
||||||
|
href="#"
|
||||||
|
>{{ text["view_feedback"]}}</a>
|
||||||
|
<b-modal
|
||||||
|
:id="'r-competency-feedback-'+cc.id"
|
||||||
|
size="sm"
|
||||||
|
ok-only
|
||||||
|
centered
|
||||||
|
scrollable
|
||||||
|
>
|
||||||
|
<template #modal-header>
|
||||||
|
<h2><i class="fa fa-puzzle-piece"></i>{{ cc.title }}</h2><br>
|
||||||
|
</template>
|
||||||
|
<span v-html="cc.feedback"></span>
|
||||||
|
</b-modal>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
</b-modal>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|
||||||
//TAG: Teacher course
|
//TAG: Teacher course
|
||||||
Vue.component('r-item-teachercourse', {
|
Vue.component('r-item-teachercourse', {
|
||||||
props: {
|
props: {
|
||||||
|
@ -1539,7 +1773,7 @@ export default {
|
||||||
|
|
||||||
return completable;
|
return completable;
|
||||||
},
|
},
|
||||||
progress_circle() { //INFO:
|
progress_circle() {
|
||||||
const status = {
|
const status = {
|
||||||
students: 0,
|
students: 0,
|
||||||
completed: 0,
|
completed: 0,
|
||||||
|
@ -1719,6 +1953,11 @@ export default {
|
||||||
v-model='value.course.completion'
|
v-model='value.course.completion'
|
||||||
:course='value.course'
|
:course='value.course'
|
||||||
></r-item-teachercompletion>
|
></r-item-teachercompletion>
|
||||||
|
<r-item-teacher-course-competency
|
||||||
|
v-if='!!value.course.competency'
|
||||||
|
v-model='value.course.competency'
|
||||||
|
:item='value'
|
||||||
|
></r-item-teacher-course-competency>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
|
|
||||||
</b-card>
|
</b-card>
|
||||||
|
@ -1727,7 +1966,7 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//TAG: Select activities to use in grade overview
|
//Select activities to use in grade overview
|
||||||
Vue.component('r-item-teacher-gradepicker', {
|
Vue.component('r-item-teacher-gradepicker', {
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -1825,7 +2064,7 @@ export default {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TAG: Selected activities dispaly
|
//Selected activities dispaly
|
||||||
Vue.component('r-item-teachergrades',{
|
Vue.component('r-item-teachergrades',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -1938,7 +2177,7 @@ export default {
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
|
||||||
//TAG: Core completion version of student course info
|
// Core completion version of student course info
|
||||||
Vue.component('r-item-teachercompletion',{
|
Vue.component('r-item-teachercompletion',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -2037,6 +2276,157 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//TAG: Course competency
|
||||||
|
Vue.component('r-item-teacher-course-competency',{
|
||||||
|
props: {
|
||||||
|
value : {
|
||||||
|
type: Object,
|
||||||
|
default: function(){ return {};},
|
||||||
|
},
|
||||||
|
guestmode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: function(){ return { id: null};},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
text: strings.competency,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created(){
|
||||||
|
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasCompletions() {
|
||||||
|
if(this.value.conditions) {
|
||||||
|
for(const cgroup of this.value.conditions){
|
||||||
|
if(cgroup.items && cgroup.items.length > 0){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
completion_icon(completion) {
|
||||||
|
switch(completion){
|
||||||
|
case "progress":
|
||||||
|
return "exclamation-circle";
|
||||||
|
case "complete":
|
||||||
|
return "check-circle";
|
||||||
|
case "complete-pass":
|
||||||
|
return "check-circle";
|
||||||
|
case "complete-fail":
|
||||||
|
return "times-circle";
|
||||||
|
default: // case "incomplete"
|
||||||
|
return "circle-o";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
completion_tag(cgroup){
|
||||||
|
return cgroup.completion?'completed':'incomplete';
|
||||||
|
},
|
||||||
|
|
||||||
|
pathtags(competency) {
|
||||||
|
const path = competency.path;
|
||||||
|
let s = "";
|
||||||
|
for (const ix in path) {
|
||||||
|
const p = path[ix];
|
||||||
|
if ( ix > 0) {
|
||||||
|
s += " / ";
|
||||||
|
}
|
||||||
|
let url;
|
||||||
|
if (p.type =='competency') {
|
||||||
|
url = `/admin/tool/lp/competencies.php?competencyid=${p.id}`;
|
||||||
|
} else {
|
||||||
|
url = `/admin/tool/lp/competencies.php?competencyframeworkid=${p.id}&pagecontextid=${p.contextid}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += `<a href="${url}">${p.title}</a>`;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
},
|
||||||
|
requiredChanged(newValue,c){
|
||||||
|
call([{
|
||||||
|
methodname: 'local_treestudyplan_require_competency',
|
||||||
|
args: { 'competency_id': c.id,
|
||||||
|
'item_id': this.item.id,
|
||||||
|
'required': newValue,
|
||||||
|
}
|
||||||
|
}])[0].fail(notification.exception);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<table class="t-item-course-competency-list">
|
||||||
|
<tr v-if="value.competencies.length == 0">
|
||||||
|
<td colspan='2'>{{text.competencies_not_configured}}!
|
||||||
|
<br><a :href="'/admin/tool/lp/coursecompetencies.php?courseid='+item.course.id" target='_blank'>{{text.configure_competencies}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<template v-else>
|
||||||
|
<tr class='t-item-course-competency-headers'>
|
||||||
|
<th>{{text.heading}}</th>
|
||||||
|
<th></th>
|
||||||
|
<th>{{text.required}}</th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for='c in value.competencies'>
|
||||||
|
<td :colspan="(c.details)?1:2"><a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.title'></span></a></td>
|
||||||
|
<td class='details' v-if="c.details">
|
||||||
|
<a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.details'></span></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b-form-checkbox inline
|
||||||
|
@change="requiredChanged($event,c)"
|
||||||
|
v-model="c.required"
|
||||||
|
>{{ text.required }}</b-form-checkbox>
|
||||||
|
</td>
|
||||||
|
<b-modal :id="'modal-competency-id-'+c.id"
|
||||||
|
size="lg"
|
||||||
|
ok-only
|
||||||
|
centered
|
||||||
|
scrollable
|
||||||
|
>
|
||||||
|
<template #modal-header>
|
||||||
|
<div>
|
||||||
|
<h1><i class="fa fa-puzzle-piece"></i>
|
||||||
|
<a :href="'/admin/tool/lp/competencies.php?competencyid='+c.id" target="_blank"
|
||||||
|
>{{c.title}} {{c.details}} </a
|
||||||
|
></h1>
|
||||||
|
<div><span v-html="pathtags(c)"></span></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="mb-2" v-if="c.description"><span v-html='c.description'></span></div>
|
||||||
|
|
||||||
|
<template v-if="c.rule && c.children">
|
||||||
|
<div>{{ c.ruleoutcome }} {{ text.when}} <span v-html="c.rule.toLocaleLowerCase()"></span></div>
|
||||||
|
<table v-if="c.children" class='t-item-course-competency-list'>
|
||||||
|
<tr class='t-item-course-competency-headers'>
|
||||||
|
<th>{{text.heading}}</th>
|
||||||
|
<th></th>
|
||||||
|
<th>{{text.required}}</th>
|
||||||
|
</tr>
|
||||||
|
<tr v-for="cc in c.children">
|
||||||
|
<td :colspan="(c.details)?1:2" ><span v-html='cc.title'></span></td>
|
||||||
|
<td class='details' v-if="cc.details"><span v-html='cc.details'></span></td>
|
||||||
|
<td><span class="text-info">{{ cc.points }} {{ text.points }}</span></td>
|
||||||
|
<td><span class="text-danger" v-if='cc.required'>{{ text.required }}</span></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
</b-modal>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vue.component('r-grading-bar',{
|
Vue.component('r-grading-bar',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
|
|
@ -237,6 +237,11 @@ export default {
|
||||||
competency: {
|
competency: {
|
||||||
competency_not_configured: "competency_not_configured",
|
competency_not_configured: "competency_not_configured",
|
||||||
configure_competency: "configure_competency",
|
configure_competency: "configure_competency",
|
||||||
|
when: "when",
|
||||||
|
required: "required",
|
||||||
|
points: "points@core_grades",
|
||||||
|
heading: "competency_heading",
|
||||||
|
details: "competency_details",
|
||||||
},
|
},
|
||||||
badge: {
|
badge: {
|
||||||
share_badge: "share_badge",
|
share_badge: "share_badge",
|
||||||
|
@ -3191,7 +3196,7 @@ export default {
|
||||||
<t-item-course-competency
|
<t-item-course-competency
|
||||||
v-if='!!value.course.competency'
|
v-if='!!value.course.competency'
|
||||||
v-model='value.course.competency'
|
v-model='value.course.competency'
|
||||||
:course='value.course'
|
:item='value'
|
||||||
></t-item-course-competency>
|
></t-item-course-competency>
|
||||||
|
|
||||||
<template #modal-footer="{ ok, cancel, hide }" >
|
<template #modal-footer="{ ok, cancel, hide }" >
|
||||||
|
@ -3410,10 +3415,10 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
course: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: function(){ return {};},
|
default: function(){ return { id: null};},
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -3421,19 +3426,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created(){
|
created(){
|
||||||
const self = this;
|
|
||||||
// Get text strings for condition settings
|
|
||||||
let stringkeys = [];
|
|
||||||
for(const key in this.text){
|
|
||||||
stringkeys.push({ key: key, component: 'local_treestudyplan'});
|
|
||||||
}
|
|
||||||
get_strings(stringkeys).then(function(strings){
|
|
||||||
let i = 0;
|
|
||||||
for(const key in self.text){
|
|
||||||
self.text[key] = strings[i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
hasCompletions() {
|
hasCompletions() {
|
||||||
|
@ -3448,25 +3441,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
completion_icon(completion) {
|
|
||||||
switch(completion){
|
|
||||||
case "progress":
|
|
||||||
return "exclamation-circle";
|
|
||||||
case "complete":
|
|
||||||
return "check-circle";
|
|
||||||
case "complete-pass":
|
|
||||||
return "check-circle";
|
|
||||||
case "complete-fail":
|
|
||||||
return "times-circle";
|
|
||||||
default: // case "incomplete"
|
|
||||||
return "circle-o";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
completion_tag(cgroup){
|
|
||||||
return cgroup.completion?'completed':'incomplete';
|
|
||||||
},
|
|
||||||
|
|
||||||
pathtags(competency) {
|
pathtags(competency) {
|
||||||
const path = competency.path;
|
const path = competency.path;
|
||||||
let s = "";
|
let s = "";
|
||||||
|
@ -3486,20 +3460,39 @@ export default {
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
},
|
},
|
||||||
|
requiredChanged(newValue,c){
|
||||||
|
call([{
|
||||||
|
methodname: 'local_treestudyplan_require_competency',
|
||||||
|
args: { 'competency_id': c.id,
|
||||||
|
'item_id': this.item.id,
|
||||||
|
'required': newValue,
|
||||||
|
}
|
||||||
|
}])[0].fail(notification.exception);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<table class="r-item-course-grade-details">
|
<table class="t-item-course-competency-list">
|
||||||
<tr v-if="value.competencies.length == 0">
|
<tr v-if="value.competencies.length == 0">
|
||||||
<td colspan='2'>{{text.competencies_not_configured}}!
|
<td colspan='2'>{{text.competencies_not_configured}}!
|
||||||
<br><a :href="'/admin/tool/lp/coursecompetencies.php?courseid='+course.id" target='_blank'>{{text.configure_competencies}}</a>
|
<br><a :href="'/admin/tool/lp/coursecompetencies.php?courseid='+item.course.id" target='_blank'>{{text.configure_competencies}}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<tr class='t-item-course-competency-headers'>
|
||||||
|
<th>{{text.heading}}</th>
|
||||||
|
<th></th>
|
||||||
|
<th>{{text.required}}</th>
|
||||||
|
</tr>
|
||||||
<tr v-for='c in value.competencies'>
|
<tr v-for='c in value.competencies'>
|
||||||
<td><a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.title'></span></a></td>
|
<td :colspan="(c.details)?1:2"><a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.title'></span></a></td>
|
||||||
<td v-if="c.details">
|
<td class='details' v-if="c.details">
|
||||||
<span v-html='c.details'></span>
|
<a href='#' v-b-modal="'modal-competency-id-'+c.id"><span v-html='c.details'></span></a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<b-form-checkbox inline
|
||||||
|
@change="requiredChanged($event,c)"
|
||||||
|
v-model="c.required"
|
||||||
|
>{{ text.required }}</b-form-checkbox>
|
||||||
</td>
|
</td>
|
||||||
<b-modal :id="'modal-competency-id-'+c.id"
|
<b-modal :id="'modal-competency-id-'+c.id"
|
||||||
size="lg"
|
size="lg"
|
||||||
|
@ -3516,14 +3509,24 @@ export default {
|
||||||
<div><span v-html="pathtags(c)"></span></div>
|
<div><span v-html="pathtags(c)"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-html='c.description'></span>
|
<div class="mb-2" v-if="c.description"><span v-html='c.description'></span></div>
|
||||||
<table v-if="c.children">
|
|
||||||
|
<template v-if="c.rule && c.children">
|
||||||
|
<div>{{ c.ruleoutcome }} {{ text.when}} <span v-html="c.rule.toLocaleLowerCase()"></span></div>
|
||||||
|
<table v-if="c.children" class='t-item-course-competency-list'>
|
||||||
|
<tr class='t-item-course-competency-headers'>
|
||||||
|
<th>{{text.heading}}</th>
|
||||||
|
<th></th>
|
||||||
|
<th>{{text.required}}</th>
|
||||||
|
</tr>
|
||||||
<tr v-for="cc in c.children">
|
<tr v-for="cc in c.children">
|
||||||
<td><span v-html='cc.displayfield'></span>
|
<td :colspan="(c.details)?1:2" ><span v-html='cc.title'></span></td>
|
||||||
</td><td><span v-html='cc.description'></span>
|
<td class='details' v-if="cc.details"><span v-html='cc.details'></span></td>
|
||||||
</td>
|
<td><span class="text-info">{{ cc.points }} {{ text.points }}</span></td>
|
||||||
|
<td><span class="text-danger" v-if='cc.required'>{{ text.required }}</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
</template>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -21,8 +21,8 @@ export function load_strings(strings){
|
||||||
}
|
}
|
||||||
getstr_func(stringkeys).then(function(str){
|
getstr_func(stringkeys).then(function(str){
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for(const key in strings[idx]){
|
for(const handle in strings[idx]){
|
||||||
strings[idx][key] = str[i];
|
strings[idx][handle] = str[i];
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,6 +31,7 @@ use core_competency\course_competency;
|
||||||
use core_competency\competency;
|
use core_competency\competency;
|
||||||
use core_competency\api as c_api;
|
use core_competency\api as c_api;
|
||||||
use core_competency\competency_rule_points;
|
use core_competency\competency_rule_points;
|
||||||
|
use core_competency\evidence;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,6 +90,9 @@ class coursecompetencyinfo {
|
||||||
"count" => new \external_value(PARAM_INT, 'number of students in stats',VALUE_OPTIONAL),
|
"count" => new \external_value(PARAM_INT, 'number of students in stats',VALUE_OPTIONAL),
|
||||||
"required" => new \external_value(PARAM_BOOL, 'if required in parent competency rule',VALUE_OPTIONAL),
|
"required" => new \external_value(PARAM_BOOL, 'if required in parent competency rule',VALUE_OPTIONAL),
|
||||||
"points" => new \external_value(PARAM_INT, 'number of points in parent competency rule',VALUE_OPTIONAL),
|
"points" => new \external_value(PARAM_INT, 'number of points in parent competency rule',VALUE_OPTIONAL),
|
||||||
|
"progress" => new \external_value(PARAM_INT, 'number completed child competencies/points',VALUE_OPTIONAL),
|
||||||
|
"count" => new \external_value(PARAM_INT, 'number of child competencies/points required',VALUE_OPTIONAL),
|
||||||
|
"feedback" => new \external_value(PARAM_RAW, 'feedback provided with this competency',VALUE_OPTIONAL),
|
||||||
];
|
];
|
||||||
if($recurse) {
|
if($recurse) {
|
||||||
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false),'child competencies',VALUE_OPTIONAL);
|
$struct["children"] = new \external_multiple_structure(self::competencyinfo_structure(false),'child competencies',VALUE_OPTIONAL);
|
||||||
|
@ -114,8 +118,8 @@ class coursecompetencyinfo {
|
||||||
*/
|
*/
|
||||||
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
|
public static function user_structure($value = VALUE_REQUIRED) : \external_description {
|
||||||
return new \external_single_structure([
|
return new \external_single_structure([
|
||||||
"progress" => new \external_value(PARAM_INT, 'number completed competencies'),
|
|
||||||
"competencies" => new \external_multiple_structure(self::competencyinfo_structure(), 'competencies'),
|
"competencies" => new \external_multiple_structure(self::competencyinfo_structure(), 'competencies'),
|
||||||
|
"progress" => new \external_value(PARAM_INT, 'number completed competencies'),
|
||||||
"count" => new \external_value(PARAM_INT, 'number of competencies',VALUE_OPTIONAL),
|
"count" => new \external_value(PARAM_INT, 'number of competencies',VALUE_OPTIONAL),
|
||||||
], 'course completion info', $value);
|
], 'course completion info', $value);
|
||||||
}
|
}
|
||||||
|
@ -194,20 +198,19 @@ class coursecompetencyinfo {
|
||||||
$ncourseproficient = 0;
|
$ncourseproficient = 0;
|
||||||
|
|
||||||
foreach($coursecompetencies as $c) {
|
foreach($coursecompetencies as $c) {
|
||||||
|
$ci = $this->competencyinfo_model($c);
|
||||||
if(!empty($studentslist)){
|
if(!empty($studentslist)){
|
||||||
$stats = $this->proficiency_stats($c,$studentlist);
|
$stats = $this->proficiency_stats($c,$studentlist);
|
||||||
$count += $stats->count;
|
$count += $stats->count;
|
||||||
$nproficient += $stats->nproficient;
|
$nproficient += $stats->nproficient;
|
||||||
$ncourseproficient += $stats->ncourseproficient;
|
$ncourseproficient += $stats->ncourseproficient;
|
||||||
}
|
|
||||||
$ci = $this->competencyinfo_model($c);
|
|
||||||
// Copy proficiency stats to model.
|
// Copy proficiency stats to model.
|
||||||
foreach ((array)$stats as $key => $value) {
|
foreach ((array)$stats as $key => $value) {
|
||||||
$ci[$key] = $value;
|
$ci[$key] = $value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
$ci['required'] = $this->is_required($c);
|
$ci['required'] = $this->is_required($c);
|
||||||
|
|
||||||
|
|
||||||
$rule = $c->get_rule_object();
|
$rule = $c->get_rule_object();
|
||||||
$ruleoutcome = $c->get('ruleoutcome');
|
$ruleoutcome = $c->get('ruleoutcome');
|
||||||
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
||||||
|
@ -223,7 +226,7 @@ class coursecompetencyinfo {
|
||||||
} else {
|
} else {
|
||||||
$outcometag = "none";
|
$outcometag = "none";
|
||||||
}
|
}
|
||||||
$model["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
||||||
|
|
||||||
if ($rule instanceof competency_rule_points) {
|
if ($rule instanceof competency_rule_points) {
|
||||||
$ruleconfig = json_decode($ruleconfig);
|
$ruleconfig = json_decode($ruleconfig);
|
||||||
|
@ -234,9 +237,9 @@ class coursecompetencyinfo {
|
||||||
foreach($ruleconfig->competencies as $cr){
|
foreach($ruleconfig->competencies as $cr){
|
||||||
$crlist[$cr->id] = $cr;
|
$crlist[$cr->id] = $cr;
|
||||||
}
|
}
|
||||||
$model["rule"] = $ruletext . " ({$points} ".get_string("points","core_grades").")";
|
$ci["rule"] = $ruletext . " ({$points} ".get_string("points","core_grades").")";
|
||||||
} else {
|
} else {
|
||||||
$model["rule"] = $ruletext;
|
$ci["rule"] = $ruletext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get one level of children
|
// get one level of children
|
||||||
|
@ -289,10 +292,15 @@ class coursecompetencyinfo {
|
||||||
foreach ((array)$p as $key => $value) {
|
foreach ((array)$p as $key => $value) {
|
||||||
$ci[$key] = $value;
|
$ci[$key] = $value;
|
||||||
}
|
}
|
||||||
|
$ci['required'] = $this->is_required($c);
|
||||||
if ($p->proficient || $p->courseproficient) {
|
if ($p->proficient || $p->courseproficient) {
|
||||||
$progress += 1;
|
$progress += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve feedback.
|
||||||
|
$ci["feedback"] = $this->retrievefeedback($c,$userid);
|
||||||
|
|
||||||
|
|
||||||
$rule = $c->get_rule_object();
|
$rule = $c->get_rule_object();
|
||||||
$ruleoutcome = $c->get('ruleoutcome');
|
$ruleoutcome = $c->get('ruleoutcome');
|
||||||
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
if($rule && $ruleoutcome != competency::OUTCOME_NONE) {
|
||||||
|
@ -308,7 +316,7 @@ class coursecompetencyinfo {
|
||||||
} else {
|
} else {
|
||||||
$outcometag = "none";
|
$outcometag = "none";
|
||||||
}
|
}
|
||||||
$model["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
$ci["ruleoutcome"] = get_string("coursemodulecompetencyoutcome_{$outcometag}","core_competency");
|
||||||
|
|
||||||
if ($rule instanceof competency_rule_points) {
|
if ($rule instanceof competency_rule_points) {
|
||||||
$ruleconfig = json_decode($ruleconfig);
|
$ruleconfig = json_decode($ruleconfig);
|
||||||
|
@ -325,16 +333,21 @@ class coursecompetencyinfo {
|
||||||
// get one level of children
|
// get one level of children
|
||||||
$dids = competency::get_descendants_ids($c);
|
$dids = competency::get_descendants_ids($c);
|
||||||
if(count($dids) > 0) {
|
if(count($dids) > 0) {
|
||||||
|
$dcount = 0;
|
||||||
|
$dprogress = 0;
|
||||||
$children = [];
|
$children = [];
|
||||||
foreach($dids as $did) {
|
foreach($dids as $did) {
|
||||||
$cc = new competency($did);
|
$cc = new competency($did);
|
||||||
$cci = $this->competencyinfo_model($cc);
|
$cci = $this->competencyinfo_model($cc);
|
||||||
if($rule instanceof competency_rule_points) {
|
|
||||||
$cp = $p = $this->proficiency($cc,$userid);
|
$cp = $p = $this->proficiency($cc,$userid);
|
||||||
// Copy proficiency info to model.
|
// Copy proficiency info to model.
|
||||||
foreach ((array)$cp as $key => $value) {
|
foreach ((array)$cp as $key => $value) {
|
||||||
$cci[$key] = $value;
|
$cci[$key] = $value;
|
||||||
}
|
}
|
||||||
|
// Retrieve feedback.
|
||||||
|
$cci["feedback"] = $this->retrievefeedback($cc,$userid);
|
||||||
|
|
||||||
|
if($rule instanceof competency_rule_points) {
|
||||||
if(array_key_exists($did,$crlist)) {
|
if(array_key_exists($did,$crlist)) {
|
||||||
$cr = $crlist[$did];
|
$cr = $crlist[$did];
|
||||||
$cci["points"] = (int) $cr->points;
|
$cci["points"] = (int) $cr->points;
|
||||||
|
@ -343,17 +356,27 @@ class coursecompetencyinfo {
|
||||||
$points += (int) $cr->points;
|
$points += (int) $cr->points;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$dcount += 1;
|
||||||
|
if ($cp->proficient) {
|
||||||
|
$dprogress += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$children[] = $cci;
|
$children[] = $cci;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ci["children"] = $children;
|
$ci["children"] = $children;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($rule instanceof competency_rule_points) {
|
if ($rule instanceof competency_rule_points) {
|
||||||
$model["rule"] = $ruletext . " ({$points} / {$pointsreq} ".get_string("points","core_grades").")";
|
$ci["rule"] = $ruletext . " ({$points} / {$pointsreq} ".get_string("points","core_grades").")";
|
||||||
|
$ci["count"] = $pointsreq;
|
||||||
|
$ci["progress"] = $points;
|
||||||
} else {
|
} else {
|
||||||
$model["rule"] = $ruletext;
|
$ci["rule"] = $ruletext;
|
||||||
|
$ci["count"] = $dcount;
|
||||||
|
$ci["progress"] = $dprogress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -412,16 +435,47 @@ class coursecompetencyinfo {
|
||||||
public function proficiency($competency, $userid) {
|
public function proficiency($competency, $userid) {
|
||||||
$scale = $competency->get_scale();
|
$scale = $competency->get_scale();
|
||||||
$competencyid = $competency->get('id');
|
$competencyid = $competency->get('id');
|
||||||
$uc = c_api::get_user_competency($userid, $competencyid);
|
|
||||||
$ucc = c_api::get_user_competency_in_course($this->course->id,$userid,$competencyid);
|
|
||||||
$r = new \stdClass();
|
$r = new \stdClass();
|
||||||
|
|
||||||
|
$uc = c_api::get_user_competency($userid, $competencyid);
|
||||||
$r->proficient = $uc->get('proficiency');
|
$r->proficient = $uc->get('proficiency');
|
||||||
$r->courseproficient = $ucc->get('proficiency');
|
|
||||||
$r->grade = $scale->get_nearest_item($uc->get('grade'));
|
$r->grade = $scale->get_nearest_item($uc->get('grade'));
|
||||||
|
try {
|
||||||
|
// Only add course grade and proficiency if the competency is included in the course.
|
||||||
|
$ucc = c_api::get_user_competency_in_course($this->course->id,$userid,$competencyid);
|
||||||
|
$r->courseproficient = $ucc->get('proficiency');
|
||||||
$r->coursegrade = $scale->get_nearest_item($ucc->get('grade'));
|
$r->coursegrade = $scale->get_nearest_item($ucc->get('grade'));
|
||||||
|
} catch (\Exception $x) {}
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve course proficiency and overall proficiency for a competency and user
|
||||||
|
*
|
||||||
|
* @param \core_competency\competency $competency
|
||||||
|
* @param int $userid
|
||||||
|
*
|
||||||
|
* @return stdClass
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function retrievefeedback($competency, $userid) {
|
||||||
|
$competencyid = $competency->get('id');
|
||||||
|
$uc = c_api::get_user_competency($userid, $competencyid);
|
||||||
|
|
||||||
|
// Get evidences and sort by creation date (newest first)
|
||||||
|
$evidence = evidence::get_records_for_usercompetency($uc->get('id'),\context_system::instance(),'timecreated', "DESC");
|
||||||
|
|
||||||
|
// Get the first valid note and return it;
|
||||||
|
foreach($evidence as $e) {
|
||||||
|
if ( in_array($e->get('action'),[evidence::ACTION_OVERRIDE,evidence::ACTION_COMPLETE] )) {
|
||||||
|
return $e->get('note');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Webservice executor to mark competency as required
|
* Webservice executor to mark competency as required
|
||||||
* @param int $competencyid ID of the competency
|
* @param int $competencyid ID of the competency
|
||||||
|
|
|
@ -197,15 +197,15 @@ class competency_aggregator extends \local_treestudyplan\aggregator {
|
||||||
$limit = $this->cfg()->thresh_completed * $count;
|
$limit = $this->cfg()->thresh_completed * $count;
|
||||||
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
|
$coursefinished = ($course->enddate) ? ($course->enddate < time()) : false;
|
||||||
|
|
||||||
if ($courseproficient >= $count && $requiredmet >= $requiredcount) {
|
if ($proficient >= $count && $requiredmet >= $requiredcount) {
|
||||||
if ($limit < $count) {
|
if ($limit < $count) {
|
||||||
return completion::EXCELLENT;
|
return completion::EXCELLENT;
|
||||||
} else {
|
} else {
|
||||||
return completion::COMPLETED;
|
return completion::COMPLETED;
|
||||||
}
|
}
|
||||||
} else if ($courseproficient > $limit && $requiredmet >= $requiredcount) {
|
} else if ($proficient > $limit && $requiredmet >= $requiredcount) {
|
||||||
return completion::COMPLETED;
|
return completion::COMPLETED;
|
||||||
} else if ($courseproficient > 0) {
|
} else if ($proficient > 0) {
|
||||||
if ( $this->cfg()->use_failed && $coursefinished) {
|
if ( $this->cfg()->use_failed && $coursefinished) {
|
||||||
return completion::FAILED;
|
return completion::FAILED;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -901,7 +901,7 @@ class studyplanservice extends \external_api {
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter description for webservice function include_grade
|
* Parameter description for webservice function require_competency
|
||||||
*/
|
*/
|
||||||
public static function require_competency_parameters() : \external_function_parameters {
|
public static function require_competency_parameters() : \external_function_parameters {
|
||||||
return new \external_function_parameters( [
|
return new \external_function_parameters( [
|
||||||
|
@ -912,7 +912,7 @@ class studyplanservice extends \external_api {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value description for webservice function include_grade
|
* Return value description for webservice function require_competency
|
||||||
*/
|
*/
|
||||||
public static function require_competency_returns() : \external_description {
|
public static function require_competency_returns() : \external_description {
|
||||||
return success::structure();
|
return success::structure();
|
||||||
|
@ -920,15 +920,14 @@ class studyplanservice extends \external_api {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a gradable item for inclusion in the studyplan
|
* Mark a competency as required for course completion
|
||||||
* @param mixed $gradeid Id of gradable
|
* @param mixed $gradeid Id of gradable
|
||||||
* @param mixed $itemid Id of study item
|
* @param mixed $itemid Id of study item
|
||||||
* @param bool $include Include grade or not
|
|
||||||
* @param bool $required Mark grade as required or not
|
* @param bool $required Mark grade as required or not
|
||||||
* @return array Success/Fail model
|
* @return array Success/Fail model
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static function require_competency($competencyid, $itemid, $include, $required = false) {
|
public static function require_competency($competencyid, $itemid, $required) {
|
||||||
global $USER;
|
global $USER;
|
||||||
$item = studyitem::find_by_id($itemid);
|
$item = studyitem::find_by_id($itemid);
|
||||||
// Find related course and course context.
|
// Find related course and course context.
|
||||||
|
@ -944,7 +943,7 @@ class studyplanservice extends \external_api {
|
||||||
// Check correct capabilities.
|
// Check correct capabilities.
|
||||||
if (has_capability('local/treestudyplan:editstudyplan', $item->context()) ||
|
if (has_capability('local/treestudyplan:editstudyplan', $item->context()) ||
|
||||||
($coursecontext && is_enrolled($coursecontext, $USER, 'local/treestudyplan:selectowngradables'))) {
|
($coursecontext && is_enrolled($coursecontext, $USER, 'local/treestudyplan:selectowngradables'))) {
|
||||||
return coursecompetencyinfo::require_competency($competencyid, $itemid, $include, $required)->model();
|
return coursecompetencyinfo::require_competency($competencyid, $itemid, $required)->model();
|
||||||
} else {
|
} else {
|
||||||
return success::fail("Access denied")->model();
|
return success::fail("Access denied")->model();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1306,6 +1306,22 @@
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list td,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list td.details,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list td.details {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.r-item-course-competency-list td,
|
||||||
|
.features-treestudyplan table.r-item-course-competency-list td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.path-local-treestudyplan .card.s-studyplan-card,
|
.path-local-treestudyplan .card.s-studyplan-card,
|
||||||
.features-treestudyplan .card.s-studyplan-card {
|
.features-treestudyplan .card.s-studyplan-card {
|
||||||
|
|
|
@ -177,6 +177,9 @@ $string["condition_any"] = 'One or more entries need to be completed';
|
||||||
$string["courses"] = 'Courses';
|
$string["courses"] = 'Courses';
|
||||||
$string["select_grades"] = 'Grades included in report';
|
$string["select_grades"] = 'Grades included in report';
|
||||||
|
|
||||||
|
$string["configure_competency"] = "Configure course competencies";
|
||||||
|
$string["competency_not_configured"] = "Course competencies have not yet been configured.";
|
||||||
|
|
||||||
$string["configure_completion"] = "Configure course completion";
|
$string["configure_completion"] = "Configure course completion";
|
||||||
$string["completion_not_configured"] = "Course completion has not yet been configured.";
|
$string["completion_not_configured"] = "Course completion has not yet been configured.";
|
||||||
$string["completion_failed"] = "Failed";
|
$string["completion_failed"] = "Failed";
|
||||||
|
@ -242,6 +245,7 @@ $string["allgraded"] = 'All graded';
|
||||||
$string["unsubmitted"] = 'No submission';
|
$string["unsubmitted"] = 'No submission';
|
||||||
$string["nogrades"] = 'No grades';
|
$string["nogrades"] = 'No grades';
|
||||||
$string["unknown"] = 'Grading status unknown';
|
$string["unknown"] = 'Grading status unknown';
|
||||||
|
$string["when"] = "when";
|
||||||
|
|
||||||
$string["selectstudent_btn"] = "View student plans";
|
$string["selectstudent_btn"] = "View student plans";
|
||||||
$string["selectstudent"] = "Choose student";
|
$string["selectstudent"] = "Choose student";
|
||||||
|
@ -299,9 +303,14 @@ $string["settingdesc_competency_thresh_completed"] = 'Minimum percentage of prof
|
||||||
$string["setting_competency_support_failed"] = 'Support "Failed" result';
|
$string["setting_competency_support_failed"] = 'Support "Failed" result';
|
||||||
$string["settingdesc_competency_support_failed"] = 'When the course end date has passed, mark course as "Failed" instead of "Progress"';
|
$string["settingdesc_competency_support_failed"] = 'When the course end date has passed, mark course as "Failed" instead of "Progress"';
|
||||||
|
|
||||||
$string["grade_include"] = "Include";
|
$string["grade_include"] = 'Include';
|
||||||
$string["grade_require"] = "Require";
|
$string["grade_require"] = 'Require';
|
||||||
$string["required_goal"] = "Required outcome";
|
$string["required_goal"] = 'Required outcome';
|
||||||
|
$string["required"] = 'Required';
|
||||||
|
$string["competency_heading"] = 'Competency';
|
||||||
|
$string["competency_details"] = 'Details';
|
||||||
|
$string["results"] = 'Results';
|
||||||
|
$string["unrated"] = 'Unrated';
|
||||||
|
|
||||||
$string["advanced_tools"] = 'Advanced';
|
$string["advanced_tools"] = 'Advanced';
|
||||||
$string["confirm_cancel"] = 'Cancel';
|
$string["confirm_cancel"] = 'Cancel';
|
||||||
|
|
|
@ -174,6 +174,9 @@ $string["condition_any"] = 'Minimaal één onderdeel moet afgerond zijn';
|
||||||
$string["courses"] = 'Cursussen';
|
$string["courses"] = 'Cursussen';
|
||||||
$string["select_grades"] = 'Resultaten die meetellen';
|
$string["select_grades"] = 'Resultaten die meetellen';
|
||||||
|
|
||||||
|
$string["configure_competency"] = "Cursuscompetenties instellen";
|
||||||
|
$string["competency_not_configured"] = "De cursuscompetenties zijn nog niet ingesteld.";
|
||||||
|
|
||||||
$string["configure_completion"] = "Voltooiing instellen";
|
$string["configure_completion"] = "Voltooiing instellen";
|
||||||
$string["completion_not_configured"] = "De cursusvoltooiing is nog niet ingesteld.";
|
$string["completion_not_configured"] = "De cursusvoltooiing is nog niet ingesteld.";
|
||||||
$string["completion_failed"] = "Onvoldoende";
|
$string["completion_failed"] = "Onvoldoende";
|
||||||
|
@ -239,6 +242,7 @@ $string["allgraded"] = 'Alles beoordeeld';
|
||||||
$string["unsubmitted"] = 'Geen inzendingen';
|
$string["unsubmitted"] = 'Geen inzendingen';
|
||||||
$string["nogrades"] = 'Geen items';
|
$string["nogrades"] = 'Geen items';
|
||||||
$string["unknown"] = 'Beoordelingen onbekend';
|
$string["unknown"] = 'Beoordelingen onbekend';
|
||||||
|
$string["when"] = "zodra";
|
||||||
|
|
||||||
$string["selectstudent_btn"] = "Bekijk studentenvoortgang";
|
$string["selectstudent_btn"] = "Bekijk studentenvoortgang";
|
||||||
$string["selectstudent"] = "Kies een student";
|
$string["selectstudent"] = "Kies een student";
|
||||||
|
@ -298,9 +302,14 @@ $string["settingdesc_competency_thresh_completed"] = 'Minimumpercentage behaalde
|
||||||
$string["setting_competency_support_failed"] = 'Onvoldoende ingeschakeld';
|
$string["setting_competency_support_failed"] = 'Onvoldoende ingeschakeld';
|
||||||
$string["settingdesc_competency_support_failed"] = 'Vink aan om "Onvoldoende" weer te kunnen geven als eind resultaat voor een cursus';
|
$string["settingdesc_competency_support_failed"] = 'Vink aan om "Onvoldoende" weer te kunnen geven als eind resultaat voor een cursus';
|
||||||
|
|
||||||
$string["grade_include"] = "Doel";
|
$string["grade_include"] = 'Doel';
|
||||||
$string["grade_require"] = "Verplicht";
|
$string["grade_require"] = 'Verplicht';
|
||||||
$string["required_goal"] = "Verplicht leerdoel";
|
$string["required_goal"] = 'Verplicht leerdoel';
|
||||||
|
$string["required"] = 'Verplicht';
|
||||||
|
$string["competency_heading"] = 'Competentie';
|
||||||
|
$string["competency_details"] = 'Details';
|
||||||
|
$string["results"] = 'Resultaten';
|
||||||
|
$string["unrated"] = 'Niet beoordeeld';
|
||||||
|
|
||||||
$string["advanced_tools"] = 'Geavanceerd';
|
$string["advanced_tools"] = 'Geavanceerd';
|
||||||
$string["confirm_cancel"] = 'Annuleren';
|
$string["confirm_cancel"] = 'Annuleren';
|
||||||
|
|
|
@ -1118,4 +1118,23 @@
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.t-item-course-competency-list {
|
||||||
|
width: 100%;
|
||||||
|
td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
td.details {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table.r-item-course-competency-list {
|
||||||
|
td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
16
styles.css
16
styles.css
|
@ -1306,6 +1306,22 @@
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
}
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list td,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.t-item-course-competency-list td.details,
|
||||||
|
.features-treestudyplan table.t-item-course-competency-list td.details {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.path-local-treestudyplan table.r-item-course-competency-list td,
|
||||||
|
.features-treestudyplan table.r-item-course-competency-list td {
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.path-local-treestudyplan .card.s-studyplan-card,
|
.path-local-treestudyplan .card.s-studyplan-card,
|
||||||
.features-treestudyplan .card.s-studyplan-card {
|
.features-treestudyplan .card.s-studyplan-card {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user