3 lines
24 KiB
JavaScript
3 lines
24 KiB
JavaScript
define("local_treestudyplan/studyplan-report-components",["exports","./util/string-helper","core/ajax","core/notification","./util/debugger","core/config","./treestudyplan-components","./util/fittext-vue","./util/date-helper"],(function(_exports,_stringHelper,_ajax,_notification,_debugger,_config,_treestudyplanComponents,_fittextVue,_dateHelper){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_notification=_interopRequireDefault(_notification),_debugger=_interopRequireDefault(_debugger),_config=_interopRequireDefault(_config),_treestudyplanComponents=_interopRequireDefault(_treestudyplanComponents),_fittextVue=_interopRequireDefault(_fittextVue);new _debugger.default("treestudyplan-viewer"),Math.PI;function striptags(html){const tmp=document.createElement("DIV");tmp.innerHTML=html;const text=tmp.textContent||tmp.innerText;return tmp.remove(),text}function conditions(item){const course=item.course,list=[];if(course.competency)for(const cmp of course.competency.competencies)list.push(cmp);else if(course.completion)for(const cnd of course.completion.conditions)for(const itm of cnd.items)list.push(itm);else if(course.grades)for(const g of course.grades)g.selected&&list.push(g);return list}var _default={install(Vue){Vue.use(_treestudyplanComponents.default),Vue.use(_fittextVue.default);let strings=(0,_stringHelper.load_strings)({report:{loading:"loadinghelp@core",studyplan_past:"studyplan_past",studyplan_present:"studyplan_present",studyplan_future:"studyplan_future",back:"back"},invalid:{error:"error"},header:{overall:"overall",students:"students@core",firstname:"firstname@core",lastname:"lastname@core",email:"email@core",lastaccess:"lastaccess@core"},studentresults:{completion_incomplete:"completion_incomplete",completion_failed:"completion_failed",completion_pending:"completion_pending",completion_progress:"completion_progress",completion_completed:"completion_completed",completion_good:"completion_good",completion_excellent:"completion_excellent",student_not_tracked:"student_not_tracked",never:"never@core"}});Vue.component("q-studyplanreport",{props:{structure:{type:Object}},data:()=>({students:[],studentresults:{},studentsloading:!0,expansioninfo:{periods:{},lines:{},items:{}},groupinfo:{},sorting:{header:"lastname",asc:!0}}),created(){},watch:{structure:{immediate:!0,handler(structure){this.loadStudents();let firstperiod=!0;for(const period of structure.periods){const pid=period.period.id;this.expansioninfo.periods[pid]||(this.$set(this.expansioninfo.periods,pid,{expanded:!!(firstperiod&&period.lines.length>0)}),this.$set(this.expansioninfo.lines,period.period.id,{}));for(const line of period.lines){const lid=line.line.id;this.expansioninfo.lines[lid]||this.$set(this.expansioninfo.lines[pid],lid,{expanded:!0});for(const item of line.items)this.expansioninfo.items[item.id]||this.$set(this.expansioninfo.items,item.id,{expanded:!1})}firstperiod=!1}}}},computed:{sortedstudents(){const students=this.students;for(const group of this.students)group.users.sort(((a,b)=>{let d=a,e=b;if(this.sorting.asc||(d=b,e=a),"lastaccess"==this.sorting.header){return(d[this.sorting.header]?d[this.sorting.header]:0)-(e[this.sorting.header]?e[this.sorting.header]:0)}return String(d[this.sorting.header]).localeCompare(String(e[this.sorting.header]))}));return students},resultColCount(){let count=0;for(const period of this.structure.periods){const pid=period.period.id;if(this.expansioninfo.periods[pid].expanded)for(const line of period.lines){const lid=line.line.id;if(this.expansioninfo.lines[pid][lid].expanded)for(const item of line.items)this.expansioninfo.items[item.id].expanded?count+=1+conditions(item).length:count+=1;else count+=1}else count+=2}return count}},methods:{loadStudents(){const self=this;self.studentsloading=!0,(0,_ajax.call)([{methodname:"local_treestudyplan_all_associated_grouped",args:{studyplan_id:this.structure.studyplan.id}}])[0].then((function(response){self.students=response;for(const group of self.students){self.$set(self.groupinfo,group.id,{expanded:!0});for(const student of group.users)self.$set(self.studentresults,student.id,{loading:!0,results:[]}),(0,_ajax.call)([{methodname:"local_treestudyplan_get_report_data",args:{pageid:self.structure.page.id,userid:student.id,firstperiod:self.structure.firstperiod,lastperiod:self.structure.lastperiod}}])[0].then((function(response){self.studentresults[student.id].loading=!1,self.studentresults[student.id].results=response})).catch(_notification.default.exception)}self.studentsloading=!1})).catch(_notification.default.exception)},expansionChanged(parm,id,val){"lines"==(parm="p"==parm[0]?"periods":"l"==parm[0]?"lines":"items")?this.expansioninfo[parm][id[0]][id[1]].expanded=val:this.expansioninfo[parm][id].expanded=val},groupExpansionChanged(group){this.groupinfo[group.id].expanded=!this.groupinfo[group.id].expanded},toggleSort(header){this.sorting.header==header?this.sorting.asc=!this.sorting.asc:(this.sorting.header=header,this.sorting.asc=!0)}},template:'\n <table class=\'q-studyplanreport\'\n :style="\'--resultColCount: \'+resultColCount+\';\'">\n <colgroup class="q-col-studentinfo">\n <col class="q-name"></col>\n <col class="q-lastaccess"></col>\n </colgroup>\n <colgroup class="q-col-resultinfo">\n <col v-for="n in resultColCount"></col>\n </colgroup>\n <q-header \n :sorting=\'sorting\' \n :structure=\'structure\'\n :expansion=\'expansioninfo\'\n @expansion=\'expansionChanged\'\n @togglesort="toggleSort"\n ></q-header>\n <template v-if="!studentsloading">\n <template v-for="group in sortedstudents">\n <q-groupheading \n v-if="group.users && group.users.length > 0" \n :group="group"\n :expanded="groupinfo[group.id].expanded"\n @togglegroup="groupExpansionChanged"\n :resultcolumns="resultColCount"\n :studentinfocolumns="2"\n ></q-groupheading>\n <template v-if=\'groupinfo[group.id].expanded\'>\n <q-studentresults v-for="(student,idx) in group.users"\n :key="student.id"\n :student=\'student\'\n :even="(idx%2==1)"\n :structure=\'structure\'\n :results=\'studentresults[student.id].results\'\n :loading=\'studentresults[student.id].loading\'\n :expansion=\'expansioninfo\'\n ></q-studentresults>\n </template>\n </template>\n </template>\n <q-inforow v-else \n :resultcolumns="resultColCount"\n :studentinfocolumns="2"><div class="spinner-border spinner-border-sm text-info" role="status"></div></q-inforow>\n </table>\n '}),Vue.component("q-header",{props:{structure:{type:Object},sorting:{type:Object},expansion:{type:Object}},data:()=>({text:strings.header}),computed:{},methods:{conditions:item=>function(item){const course=item.course,list=[];if(course.competency)for(const cmp of course.competency.competencies)list.push({name:cmp.details?`${cmp.title} - ${cmp.details}`:cmp.title,tooltip:cmp.description});else if(course.completion)for(const cnd of course.completion.conditions)for(const itm of cnd.items)list.push({name:itm.title,tooltip:`${itm.details.type}: ${itm.details.requirement}`});else if(course.grades)for(const g of course.grades)g.selected&&list.push({name:g.name,tooltip:`${g.typename}: ${striptags(g.name)}`});return list}(item),colspanPeriod(period){const pid=period.period.id;if(this.expansion.periods[pid].expanded){let sum=0;for(const l of period.lines)sum+=this.colspanLine(period,l);return sum}return 2},colspanLine(period,line){const pid=period.period.id,lid=line.line.id;if(this.expansion.lines[pid][lid].expanded){let sum=0;for(const i of line.items)sum+=this.colspanItem(i);return sum}return 1},colspanItem(item){if(this.expansion.items[item.id].expanded){return 1+this.conditions(item).length}return 1},togglePeriod(period,val){void 0===val&&(val=!this.expansion.periods[period.id].expanded),this.$emit("expansion","periods",period.id,val)},toggleLine(period,line,val){void 0===val&&(val=!this.expansion.lines[period.id][line.id].expanded),this.$emit("expansion","lines",[period.id,line.id],val)},toggleItem(item,val){void 0===val&&(val=!this.expansion.items[item.id].expanded),this.$emit("expansion","items",item.id,val)},toggleSort(heading){this.$emit("togglesort",heading)}},mounted(){},updated(){},template:'\n <thead class=\'q-header\'>\n <tr> \x3c!-- period heading --\x3e\n <th rowspan=\'4\' colspan=\'2\' class=\'q-studentinfo q-generic\'><span>{{text.students}}</span></th>\n <th v-for="p in structure.periods" \n :class="\'q-period-heading \'+ ((expansion.periods[p.period.id].expanded)?\'expanded\':\'collapsed\')"\n :colspan=\'colspanPeriod(p)\'\n :rowspan=\'(expansion.periods[p.period.id].expanded && p.lines.length > 0)?1:5\'\n ><span class="q-wrap"><a v-if=\'(p.lines.length > 0)\' href=\'#\' @click.prevent="togglePeriod(p.period)"\n ><i v-if="expansion.periods[p.period.id].expanded" \n class=\'q-chevron fa fa-minus\'></i\n ><i v-else class=\'q-chevron fa fa-plus\'></i\n > {{ p.period.fullname}}</a\n ><span v-else>{{ p.period.fullname}}</span></span\n ></th>\n </tr>\n <tr> \x3c!-- line heading --\x3e\n <template v-for="p in structure.periods">\n <template v-if="expansion.periods[p.period.id].expanded">\n <th v-for="l in p.lines"\n :class="\'q-line-heading \' + ((expansion.lines[p.period.id][l.line.id].expanded)?\'expanded\':\'collapsed\')"\n :colspan="colspanLine(p,l)"\n :rowspan=\'(expansion.lines[p.period.id][l.line.id].expanded)?1:4\'\n ><span class="q-wrap"><fittext vertical maxsize="18pt"\n ><span class=\'q-label\'\n :title="l.line.shortname"\n v-html="l.line.shortname"\n ></span\n ></fittext></span\n ></th>\n </template>\n </template>\n </tr>\n <tr> \x3c!-- item heading --\x3e\n <template v-for="p in structure.periods"> \n <template v-if="expansion.periods[p.period.id].expanded"> \n <template v-for="l in p.lines">\n <template v-if="expansion.lines[p.period.id][l.line.id].expanded">\n <th v-for="item in l.items"\n :class="\'q-item-heading \' + ((expansion.items[item.id].expanded)?\'expanded\':\'collapsed\')"\n :colspan="colspanItem(item)"\n :rowspan=\'(expansion.items[item.id].expanded)?1:3\'\n ><div class="q-wrap"\n ><div class="q-toggle" ><a href=\'#\' \n @click.prevent="toggleItem(item)"\n ><i v-if="expansion.items[item.id].expanded" \n class=\'q-chevron fa fa-minus\'></i\n ><i v-else \n class=\'q-chevron fa fa-plus\'></i\n ></a\n ></div><div class="q-title">\n <fittext vertical maxsize="12pt" minsize="9pt"\n ><a style="display: inline-block;" href=\'#\' \n @click.prevent="toggleItem(item)"\n ><span class=\'q-label\'\n :title="item.course.displayname" \n v-html="item.course.displayname"\n ></span\n ></a\n ></fittext\n ></div\n ></div\n ></th>\n </template>\n </template>\n </template>\n </template>\n </tr>\n <tr> \x3c!-- condition heading --\x3e\n <template v-for="p in structure.periods">\n <template v-if="expansion.periods[p.period.id].expanded"> \n <template v-for="l in p.lines">\n <template v-if="expansion.lines[p.period.id][l.line.id].expanded">\n <template v-for="item in l.items">\n <template v-if="expansion.items[item.id].expanded">\n <th class=\'q-condition-heading overall\' rowspan="2"\n ><span class=\'q-wrap\'>{{ text.overall }}</span></th>\n <th v-for="c in conditions(item)" \n rowspan="2"\n class=\'q-condition-heading\'\n ><span class="q-wrap"><fittext vertical maxsize="14pt"><a class=\'q-label q-condition-label\'\n :title="c.tooltip" href="#" @click.prevent\n v-b-tooltip.focus\n v-html="c.name"></a\n ></fittext></span\n ></th>\n </template>\n </template>\n </template>\n </template>\n </template>\n </template>\n </tr>\n <tr> \x3c!-- student info heading --\x3e\n <th class="q-studentinfo q-name">\n <fittext maxsize="12pt"\n ><a href="#" @click.prevent="toggleSort(\'firstname\')">{{text.firstname}}</a\n ><i v-if="sorting.header==\'firstname\' && sorting.asc" class=\'fa fa-sort-asc fa-fw\'></i\n ><i v-else-if="sorting.header==\'firstname\' && !sorting.asc" class=\'fa fa-sort-desc fa-fw\'></i>\n / <a href="#" @click.prevent="toggleSort(\'lastname\')">{{text.lastname}}</a\n ><i v-if="sorting.header==\'lastname\' && sorting.asc" class=\'fa fa-sort-asc fa-fw\'></i\n ><i v-else-if="sorting.header==\'lastname\' && !sorting.asc" class=\'fa fa-sort-desc fa-fw\'></i\n ></fittext>\n </th>\n <th class="q-studentinfo q-email">\n <fittext maxsize="12pt"\n ><a href="#" @click.prevent="toggleSort(\'lastaccess\')">{{text.lastaccess}}</a\n ><i v-if="sorting.header==\'lastaccess\' && sorting.asc" class=\'fa fa-sort-asc fa-fw\'></i\n ><i v-else-if="sorting.header==\'lastaccess\' && !sorting.asc" class=\'fa fa-sort-desc fa-fw\'></i\n ></fittext>\n </th>\n </tr>\n </thead>\n '}),Vue.component("q-groupheading",{props:{group:{type:Object},resultcolumns:{type:Number,default:1},studentinfocolumns:{type:Number,default:1},expanded:{type:Boolean}},data:()=>({}),computed:{},methods:{toggleGroup(){this.$emit("togglegroup",this.group)}},template:'\n <tr class=\'q-groupheading\'>\n <th :colspan="studentinfocolumns"><a href="#" @click.prevent="toggleGroup"\n ><i v-if="expanded" class="fa fa-minus"></i\n ><i v-else class="fa fa-plus"></i\n > {{group.label}}</a></th>\n <td :colspan="resultcolumns"></td>\n </tr>\n '}),Vue.component("q-inforow",{props:{resultcolumns:{type:Number,default:1},studentinfocolumns:{type:Number,default:1}},data:()=>({}),computed:{},methods:{},template:'\n <tr class=\'q-inforow\'>\n <td :colspan="studentinfocolumns"><slot></slot></td>\n <td :colspan="resultcolumns"></td>\n </tr>\n '}),Vue.component("q-studentresults",{props:{student:{type:Object},structure:{type:Object},results:{type:Array},loading:{type:Boolean,default:!1},expansion:{type:Object},even:{type:Boolean,default:!1}},data:()=>({text:strings.studentresults}),computed:{lastaccess(){return this.student.lastaccess?(0,_dateHelper.format_datetime)(this.student.lastaccess):this.text.never}},methods:{useritems(line){const list=[];for(const item of line.items){let newitm=item;for(const itm of this.results)if(item.id==itm.id){newitm=itm;break}list.push(newitm)}return list},conditions:item=>conditions(item)},template:'\n <tr :class="\'q-student-results userrow \' + (even?\'even\':\'odd\')">\n <td class=\'q-studentinfo q-name\'><fittext maxsize="12pt">{{student.firstname}} {{student.lastname}}</fittext></td>\n <td class=\'q-studentinfo q-email\'><fittext maxsize="12pt">{{lastaccess}}</fittext></td>\n <template v-for="p in structure.periods">\n <template v-if="expansion.periods[p.period.id].expanded && p.lines.length > 0">\n <template v-for="l in p.lines">\n <template v-if="expansion.lines[p.period.id][l.line.id].expanded">\n <template v-for="item in useritems(l)">\n <td class=\'q-result overall\'\n ><q-courseresult\n :item="item"\n :student="student"\n :loading="loading"\n ></q-courseresult\n ></td>\n <template v-if="expansion.items[item.id].expanded">\n <td v-for="(c,idx) in conditions(item)"\n class=\'q-result\'\n ><q-conditionresult\n :item="item"\n :conditionidx="idx"\n :student="student"\n :loading="loading"\n ></q-conditionresult\n ></td>\n </template>\n </template>\n </template>\n <td v-else class=\'q-result collapsed\'> </td>\n </template>\n </template>\n <td v-else colspan="2" class=\'q-result collapsed\'> </td>\n </template>\n </tr>\n '}),Vue.component("q-courseresult",{props:{student:{type:Object},item:{type:Object},loading:{type:Boolean,default:!1}},data:()=>({text:strings.studentresults}),computed:{hasprogressinfo(){const course=this.item.course;return!!course.enrolled&&!!(course.completion||course.competency||course.grades)},completion_icon(){switch(this.item.completion){default:return"circle-o";case"pending":return"question-circle";case"failed":return"times-circle";case"progress":return"exclamation-circle";case"completed":case"good":case"excellent":return"check-circle"}}},methods:{},template:'\n <span class=\'q-courseresult\'>\n <template v-if="loading">\n <div class="spinner-border spinner-border-sm text-info" role="status"></div>\n </template>\n <template v-else-if=\'!item.course.enrolled\'>\n <i v-b-popover.top\n class="fa fa-exclamation-triangle t-not-enrolled-alert"\n :title="text.student_not_tracked"></i>\n </template>\n <template v-else-if="item.lineenrolled" >\n <i v-b-popover.top\n :class="\'fa fa-\'+completion_icon+\n \' r-completion-\'+item.completion"\n :title="text[\'completion_\'+item.completion]"></i>\n </template>\n </span>\n '}),Vue.component("q-conditionresult",{props:{student:{type:Object},item:{type:Object},loading:{type:Boolean,default:!1},conditionidx:{type:Number}},data:()=>({text:strings.studentresults}),computed:{conditions(){return conditions(this.item)},condition(){return this.conditionidx>=0&&this.conditionidx<this.conditions.length?this.conditions[this.conditionidx]:null},hasprogressinfo(){const course=this.item.course;return!!course.enrolled&&(course.completion||course.competency||course.grades)},completion_icon(){switch(this.condition_completion()){default:return"circle-o";case"pending":return"question-circle";case"failed":return"times-circle";case"progress":return"exclamation-circle";case"completed":case"good":case"excellent":return"check-circle"}},condition_value(){const course=this.item.course;if(course.competency){if(this.condition.grade)return this.condition.grade}else if(course.completion){if(this.condition.grade)return this.condition.grade}else if(course.grades)return this.condition.grade;return`<i class='fa fa-${this.completion_icon()}'></i>`},condition_completion(){const course=this.item.course;if(course.competency){const competency=this.condition;return competency.proficient&&competency.courseproficient||competency.proficient?"completed":!1===competency.proficient?"failed":competency.progress?"progress":"incomplete"}return course.completion?this.condition.status:course.grades?this.condition.completion:void 0}},methods:{},template:'\n <span class=\'q-conditionresult\'>\n <fittext v-if="item.lineenrolled" maxsize="10pt" singleline dynamic>\n <template v-if="loading">\n <div class="spinner-border spinner-border-sm text-info" role="status"></div>\n </template>\n <template v-else-if=\'!item.course.enrolled\'>\n <i class="fa fa-ellipsis-h"\n :title="text.student_not_tracked"></i>\n </template>\n <template v-else>\n <span \n :class="\'r-completion-\'+condition_completion"\n :title="text[\'completion_\'+condition_completion]"\n >{{condition_value}}</span\n >\n </template>\n </fittext>\n </span>\n '})}};return _exports.default=_default,_exports.default}));
|
|
|
|
//# sourceMappingURL=studyplan-report-components.min.js.map
|