moodle_local_treestudyplan/amd/build/report-viewer-components.min.js.map
2024-03-04 23:03:18 +01:00

1 line
188 KiB
Plaintext

{"version":3,"file":"report-viewer-components.min.js","sources":["../src/report-viewer-components.js"],"sourcesContent":["/*eslint no-var: \"error\"*/\n/*eslint no-console: \"off\"*/\n/*eslint no-unused-vars: warn */\n/*eslint max-len: [\"error\", { \"code\": 160 }] */\n/*eslint-disable no-trailing-spaces */\n/*eslint-env es6*/\n// Put this file in path/to/plugin/amd/src\n\nimport {SimpleLine} from './simpleline/simpleline';\nimport {get_strings} from 'core/str';\nimport {load_strings} from './util/string-helper';\nimport {format_date, format_datetime, studyplanPageTiming,studyplanTiming} from './util/date-helper';\nimport {call} from 'core/ajax';\nimport notification from 'core/notification';\nimport {svgarcpath} from './util/svgarc';\nimport Debugger from './util/debugger';\nimport Config from 'core/config';\nimport {ProcessStudyplan, ProcessStudyplanPage, objCopy} from './studyplan-processor';\nimport TSComponents from './treestudyplan-components';\nimport {eventTypes as editSwEventTypes} from 'core/edit_switch';\nimport { premiumenabled, premiumstatus } from \"./util/premium\";\n\n// Make π available as a constant\nconst π = Math.PI;\n// Gravity value for arrow lines - determines how much a line is pulled in the direction of the start/end before changing direction\nconst LINE_GRAVITY = 1.3;\n\n/**\n * Studyline is not enrollable\n * @var int\n */\nconst ENROLLABLE_NONE = 0;\n\n/**\n * Studyline can be enrolled into by the student\n * @var int\n */\nconst ENROLLABLE_SELF = 1;\n\n/**\n * Studyline can be enrolled into by specific role(s)\n * @var int\n */\nconst ENROLLABLE_ROLE = 2;\n\n/**\n * Studyline can be enrolled by user and/or role\n * @var int\n */\nconst ENROLLABLE_SELF_ROLE = 3;\n\n\nexport default {\n install(Vue/*,options*/){\n Vue.use(TSComponents);\n let debug = new Debugger(\"treestudyplan-viewer\");\n let lastCaller = null;\n /**\n * Scroll current period into view\n * @param {*} handle A key to pass so subsequent calls with the same key won't trigger (always triggers when null or undefined)\n */\n function scrollCurrentIntoView(handle){\n const elScrollContainer = document.querySelector(\".r-studyplan-scrollable\");\n const elCurrentHeader = elScrollContainer.querySelector(\".s-studyline-header-period.current\");\n\n if(elCurrentHeader && ((!handle) || (handle != lastCaller))){\n lastCaller = handle;\n elCurrentHeader.scrollIntoView({\n behavior: \"smooth\",\n block: \"start\",\n inline: \"center\",\n });\n }\n }\n\n let strings = load_strings({\n report: {\n loading: \"loadinghelp@core\",\n studyplan_past: \"studyplan_past\",\n studyplan_present: \"studyplan_present\",\n studyplan_future: \"studyplan_future\",\n back: \"back\",\n },\n invalid: {\n error: 'error',\n },\n grading: {\n ungraded: \"ungraded\",\n graded: \"graded\",\n allgraded: \"allgraded\",\n unsubmitted: \"unsubmitted\",\n nogrades: \"nogrades\",\n unknown: \"unknown\",\n },\n completion: {\n completed: \"completion_completed\",\n incomplete: \"completion_incomplete\",\n completed_pass: \"completion_passed\",\n completed_fail: \"completion_failed\",\n ungraded: \"ungraded\",\n aggregation_all: \"aggregation_all\",\n aggregation_any: \"aggregation_any\",\n aggregation_one: \"aggregation_one\",\n aggregation_overall_all: \"aggregation_overall_all\",\n aggregation_overall_any: \"aggregation_overall_any\",\n aggregation_overall_one: \"aggregation_overall_one\",\n completion_not_configured: \"completion_not_configured\",\n configure_completion: \"configure_completion\",\n view_completion_report: \"view_completion_report\",\n completion_incomplete: \"completion_incomplete\",\n completion_failed: \"completion_failed\",\n completion_pending: \"completion_pending\",\n completion_progress: \"completion_progress\",\n completion_completed: \"completion_completed\",\n completion_good: \"completion_good\",\n completion_excellent: \"completion_excellent\",\n view_feedback: \"view_feedback\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\",\n required_goal: \"required_goal\",\n student_not_tracked: \"student_not_tracked\",\n completion_not_enabled: \"completion_not_enabled\",\n },\n badge: {\n share_badge: \"share_badge\",\n dateissued: \"dateissued\",\n dateexpire: \"dateexpire\",\n badgeinfo: \"badgeinfo\",\n badgeissuedstats: \"badgeissuedstats\",\n completion_incomplete: \"completion_incomplete_badge\",\n completion_completed: \"completion_completed_badge\",\n completioninfo: \"completioninfo\",\n badgedisabled: \"badgedisabled\"\n },\n course: {\n completion_incomplete: \"completion_incomplete\",\n completion_failed: \"completion_failed\",\n completion_pending: \"completion_pending\",\n completion_progress: \"completion_progress\",\n completion_completed: \"completion_completed\",\n completion_good: \"completion_good\",\n completion_excellent: \"completion_excellent\",\n view_feedback: \"view_feedback\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\",\n required_goal: \"required_goal\",\n student_not_tracked: \"student_not_tracked\",\n not_enrolled: \"not_enrolled\",\n },\n teachercourse: {\n select_conditions: \"select_conditions\",\n select_grades: \"select_grades\",\n coursetiming_past: \"coursetiming_past\",\n coursetiming_present: \"coursetiming_present\",\n coursetiming_future: \"coursetiming_future\",\n grade_include: \"grade_include\",\n grade_require: \"grade_require\",\n required_goal: \"required_goal\",\n student_from_plan_enrolled: \"student_from_plan_enrolled\",\n students_from_plan_enrolled: \"students_from_plan_enrolled\",\n },\n competency: {\n competency_not_configured: \"competency_not_configured\",\n configure_competency: \"configure_competency\",\n when: \"when\",\n required: \"required\",\n points: \"points@core_grades\",\n heading: \"competency_heading\",\n details: \"competency_details\",\n results: \"results\",\n unrated: \"unrated\",\n progress: \"completion_progress\",\n view_feedback: \"view_feedback\",\n }, \n pageinfo: {\n edit: 'period_edit',\n fullname: 'studyplan_name',\n shortname: 'studyplan_shortname',\n startdate: 'studyplan_startdate',\n enddate: 'studyplan_enddate',\n description: 'studyplan_description',\n duration: 'studyplan_duration',\n details: 'studyplan_details',\n overview: 'overviewreport:all',\n oveviewperiod: 'overviewreport:period'\n },\n lineheader: {\n cannot_enrol: 'line_cannot_enrol',\n can_enrol: 'line_can_enrol',\n is_enrolled: 'line_is_enrolled',\n enrol: 'line_enrol',\n enrolled: 'line_enrolled',\n notenrolled: 'line_notenrolled',\n enrol_question: 'line_enrol_question',\n enrollments: 'line_enrollments',\n enrollment: 'line_enrollment',\n info: 'info@core',\n confirm: 'confirm@core',\n yes: 'yes@core',\n no: 'no@core',\n enrolled_in: 'line_enrolled_in',\n since: 'since@core',\n byname: 'byname@core',\n \n }\n\n });\n\n /************************************\n * *\n * Treestudyplan Viewer components *\n * *\n ************************************/\n\n /**\n * Check if element is visible\n * @param {Object} elem The element to check\n * @returns {boolean} True if visible\n */\n function isVisible(elem){\n return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n }\n\n // Create new eventbus for interaction between item components\n const ItemEventBus = new Vue();\n\n // Add event listener for the edit mode event so we can react to it, or at the very least ignore it\n document.addEventListener(editSwEventTypes.editModeSet,(e) => {\n e.preventDefault();\n ItemEventBus.$emit('editModeSet',e.detail.editMode);\n });\n\n\n Vue.component('r-progress-circle',{\n props: {\n value: {\n type: Number,\n },\n max: {\n type: Number,\n default: 100,\n },\n min: {\n type: Number,\n default: 0,\n },\n stroke: {\n type: Number,\n default: 0.2,\n },\n bgopacity: {\n type: Number,\n default: 0.2,\n },\n title: {\n type: String,\n default: \"\",\n },\n icon: {\n type: String,\n }\n\n },\n data() {\n return {\n selectedstudyplan: null,\n };\n },\n computed: {\n range() {\n return this.max - this.min;\n },\n fraction(){\n if(this.max - this.min == 0){\n return 0;\n // 0 size is always empty :)\n } else {\n return (this.value - this.min)/(this.max - this.min);\n }\n },\n radius() {\n return 50 - (50*this.stroke);\n },\n arcpath() {\n let fraction = 0;\n const r = 50 - (50*this.stroke);\n if(this.max - this.min != 0){\n fraction = (this.value - this.min)/(this.max - this.min);\n }\n\n const Δ = fraction * 2*π;\n return svgarcpath([50,50],[r,r],[0,Δ], 1.5*π);\n },\n },\n methods: {\n },\n template: `\n <div style=\"display: inline-block; width: 1em; height: 1em; position:relative; padding: 0;\">\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 100 100\"\n style=\"position: absolute;top: 0;left: 0;\">\n <title>{{title}}</title>\n <circle v-if=\"fraction >= 1.0\" cx=\"50\" cy=\"50\" :r=\"radius\"\n :style=\"'opacity: 1; stroke-width: '+ (stroke*100)+'; stroke: currentcolor; fill: none;'\"/>\n <g v-else>\n <circle cx=\"50\" cy=\"50\" :r=\"radius\"\n :style=\"'opacity: ' + bgopacity + ';stroke-width: '+ (stroke*100)+'; stroke: currentcolor; fill: none;'\"/>\n <path :d=\"arcpath\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: currentcolor; fill: none;'\"/>\n </g>\n </svg>\n <i v-if='icon' :class=\"'fa fa-'+icon\"\n style=\" position: absolute; top: 0.42em; left: 0.43em; text-align:center; display: inline-block;\n width:1em; font-size: 0.55em; \"\n ></i>\n </div>\n `,\n });\n\n\n Vue.component('r-report', {\n props: {\n invitekey: {\n type: String,\n default() { return null;},\n },\n userid: {\n type: Number,\n default() { return 0;},\n },\n type: {\n type: String,\n default() { return \"own\";},\n },\n },\n data() {\n return {\n text: strings.report,\n studyplans: {\n past: [],\n present: [],\n future: [],\n },\n \n selectedstudyplan: null,\n loadingstudyplan: false,\n loading: true,\n };\n },\n computed: {\n teachermode() {\n return (this.type ==\"teaching\");\n },\n guestmode() {\n return (this.type == \"invited\");\n },\n verified_type() {\n if (! [\"invited\",\"other\",\"teaching\",\"own\"].includes(this.type)) {\n return \"own\";\n } else {\n return this.type;\n }\n },\n studyplancount() {\n return this.studyplans.past.length + this.studyplans.present.length + this.studyplans.future.length;\n }\n },\n updated() {\n\n },\n mounted() {\n this.loadStudyplans();\n },\n\n methods: {\n call_args(o) {\n const args = {};\n if (typeof o == 'object' && !Array.isArray(o) && o !== null) {\n objCopy(args,o);\n }\n\n if(this.verified_type == \"invited\") {\n args[\"invitekey\"] = this.invitekey;\n } else if(this.verified_type == \"other\") {\n args[\"userid\"] = this.userid;\n } \n return args;\n },\n loadStudyplans() {\n const self = this;\n this.loading = true;\n \n call([{\n methodname: `local_treestudyplan_list_${this.verified_type}_studyplans`,\n args: this.call_args(),\n }])[0].then(function(response){\n console.info(\"Loaded: plans\",response);\n const plans = { future: [], present: [], past: [], };\n\n for (const ix in response) {\n const plan = response[ix];\n const timing = studyplanTiming(plan);\n plans[timing].push(plan);\n }\n\n for (const ix in plans) {\n plans[ix].sort((a,b) => {\n const t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime();\n if (t == 0) {\n // sort by name if timing is equal\n t = a.name.localeCompare(b.name);\n }\n return t;\n });\n }\n\n self.studyplans = plans;\n self.loading = false;\n\n if (self.studyplans.present.length == 1) {\n // Directly show the current study plan if it's the only one\n self.selectStudyplan(self.studyplans.present[0]);\n } else {\n // If there is but a single studyplan, select it anyway, even if it is not current...\n if (this.studyplancount == 1) {\n if(self.studyplans.future.lengh > 0) {\n self.selectStudyplan(self.studyplans.future[0]);\n } else {\n self.selectStudyplan(self.studyplans.past[0]);\n }\n }\n }\n }).catch(notification.exception);\n },\n selectStudyplan(plan) {\n const self = this;\n this.loadingstudyplan = true;\n call([{\n methodname: `local_treestudyplan_get_${this.verified_type}_studyplan`,\n args: this.call_args({\n studyplanid: plan.id,\n }),\n }])[0].then(function(response){\n self.selectedstudyplan = ProcessStudyplan(response);\n self.loadingstudyplan = false;\n }).catch(notification.exception);\n },\n deselectStudyplan() {\n this.selectedstudyplan = null;\n this.loadStudyplans(); // Reload the list of studyplans.\n }\n },\n template: `\n <div class='t-studyplan-container r-report-tabs'>\n <div v-if='loading' class=\"vue-loader spinner-border text-primary\" role=\"status\"></div>\n <template v-else>\n <div v-if='!loadingstudyplan && selectedstudyplan'>\n <div class=\"mb-2\">\n <a href='#' @click='deselectStudyplan'><h5 class=\"d-inline\"><i class=\"fa fa-chevron-left\"></i> {{ text.back }}</h5></a>\n <h4 class=\"d-inline ml-3\">{{ selectedstudyplan.name}}\n <s-studyplan-details \n class=\"mb-2\"\n size=\"sm\"\n v-model=\"selectedstudyplan\" \n v-if=\"selectedstudyplan.description\"\n ><i class='fa fa-info-circle'></i></s-studyplan-details></h4>\n </div>\n <r-studyplan\n v-model='selectedstudyplan'\n :guestmode='guestmode'\n :teachermode='teachermode'\n ></r-studyplan>\n </div>\n <div v-else-if='loadingstudyplan' class=\"vue-loader spinner-border text-primary\" role=\"status\">\n <span class=\"sr-only\">{{ text.loading }}</span>\n </div>\n <div v-else class='t-studyplan-notselected'>\n <template v-for=\"timing in ['present', 'past', 'future']\">\n <template v-if=\"studyplans[timing].length > 0\">\n <h4>{{ text[\"studyplan_\"+timing]}}:</h4>\n <b-card-group deck>\n <s-studyplan-card\n v-for='(studyplan, planindex) in studyplans[timing]'\n :key='studyplan.id'\n v-model='studyplans[timing][planindex]'\n open\n @open='selectStudyplan(studyplan)'\n ></s-studyplan-card>\n </b-card-group>\n </template>\n </template>\n </div>\n </template>\n </div>\n `,\n });\n\n Vue.component('r-studyplan', {\n props: {\n value: {\n type: Object,\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n },\n },\n data() {\n return {\n selectedpageindex: -1,\n text: strings.pageinfo,\n };\n },\n computed: {\n\n selectedpage() {\n return this.value.pages[this.selectedpageindex];\n },\n startpageindex() {\n let startpageindex = 0;\n let firststart = null;\n for(const ix in this.value.pages) {\n const page = this.value.pages[ix];\n if(studyplanPageTiming(page) == \"present\") {\n const s = new Date(page.startdate);\n if( (!firststart) || firststart > s) {\n startpageindex = ix;\n firststart = s;\n }\n }\n }\n return startpageindex;\n },\n wwwroot() {\n return Config.wwwroot;\n },\n },\n methods: {\n pageduration(page){\n return format_date(page.startdate,false) + \" - \" + format_date(page.enddate,false);\n },\n columns(page) {\n return 1+ (page.periods * 2);\n },\n columns_stylerule(page) {\n // Uses css variables, so width for slots and filters can be configured in css\n let s = \"grid-template-columns: var(--studyplan-filter-width)\"; // use css variable here\n for(let i=0; i<page.periods;i++){\n s+= \" var(--studyplan-course-width) var(--studyplan-filter-width)\";\n }\n return s+\";\";\n },\n countLineLayers(line,page){\n let maxLayer = -1;\n for(let i = 0; i <= page.periods; i++){\n const slot = line.slots[i];\n // Determine the amount of used layers in a studyline slot\n for(const ix in line.slots[i].courses){\n const item = line.slots[i].courses[ix];\n if(item.layer > maxLayer){\n maxLayer = item.layer;\n }\n }\n for(const ix in line.slots[i].filters){\n const item = line.slots[i].filters[ix];\n if(item.layer > maxLayer){\n maxLayer = item.layer;\n }\n }\n }\n return (maxLayer >= 0)?(maxLayer+1):1;\n },\n showslot(page,line,index, layeridx, type){\n // check if the slot should be hidden because a previous slot has an item with a span\n // so big that it hides this slot\n const forGradable = (type == 'gradable')?true:false;\n const periods = page.periods;\n let show = true;\n for(let i = 0; i < periods; i++){\n if(line.slots[index-i] && line.slots[index-i].courses){\n const list = line.slots[index-i].courses;\n for(const ix in list){ // Really wish that 'for of' would work with the minifier moodle uses\n const item = list[ix];\n if(item.layer == layeridx){\n if(forGradable){\n if(i > 0 && (item.span - i) > 0){\n show = false;\n }\n } else {\n if((item.span - i) > 1){\n show = false;\n }\n }\n }\n }\n }\n }\n\n return show;\n },\n selectedpageChanged(newTabIndex,prevTabIndex) {\n \n ItemEventBus.$emit('redrawLines', null);\n scrollCurrentIntoView(this.selectedpage.id);\n },\n },\n mounted() {\n// scrollCurrentIntoView(this.selectedpage.id);\n this.$root.$emit('redrawLines');\n },\n updated() {\n\n scrollCurrentIntoView(this.selectedpage.id);\n ItemEventBus.$emit('lineHeightChange', null);\n this.$root.$emit('redrawLines');\n ItemEventBus.$emit('redrawLines');\n },\n template: `\n <div>\n <b-card no-body>\n <b-tabs \n v-model='selectedpageindex' \n @activate-tab='selectedpageChanged'\n content-class=\"mt-1\">\n <b-tab\n v-for=\"(page,pageindex) in value.pages\"\n :active=\"(pageindex == startpageindex)\"\n :key=\"page.id\"\n :title-item-class=\"'s-studyplanpage-tab '+ page.timing\"\n ><template #title>\n <span v-b-tooltip.hover :title='page.fullname'>{{page.shortname}}</span>\n <a href=\"#\" v-b-modal=\"'studyplanpage-info-'+page.id\" class='text-info'\n v-if='pageindex == selectedpageindex'\n ><i class='fa fa-info-circle'></i></a>\n </template>\n \n <b-modal\n :id=\"'studyplanpage-info-'+page.id\"\n scrollable\n ok-only\n >\n <template #modal-title>\n {{page.fullname}}\n </template>\n <b-container>\n <b-row>\n <b-col cols=\"4\"><b>{{ text.shortname}}</b></b-col>\n <b-col cols=\"8\">\n {{ page.shortname }}\n </b-col>\n </b-row>\n <b-row>\n <b-col cols=\"4\"><b>{{ text.duration}}</b></b-col>\n <b-col cols=\"8\">\n {{ pageduration(page) }}\n </b-col>\n </b-row>\n <b-row v-if=\"page.description\">\n <b-col cols=\"12\"><b>{{ text.description}}</b></b-col>\n </b-row>\n <b-row v-if=\"page.description\">\n <b-col cols=\"12\">\n <span v-html=\"page.description\"></span>\n </b-col>\n </b-row>\n </b-container>\n </b-modal>\n <div v-if=\"page.studylines.length > 0\" class='r-studyplan-content'>\n <!-- First paint the headings-->\n <div class='r-studyplan-headings'\n ><s-studyline-header-heading :identifier=\"Number(page.id)\"\n ><a v-if=\"teachermode && selectedpage\" class=\"ml-2\"\n :href=\"wwwroot+'//local/treestudyplan/result-overview.php?page='+selectedpage.id\"\n \n target='_blank'><i class='fa fa-list-ul'></i>&nbsp;{{text.overview}}</a\n ></s-studyline-header-heading>\n <r-studyline-heading v-for=\"(line,lineindex) in page.studylines\"\n :key=\"line.id\"\n :teachermode=\"teachermode\"\n :guestmode=\"guestmode\"\n v-model=\"page.studylines[lineindex]\"\n :layers='countLineLayers(line,page)+1'\n :studentid=\"value.userid\"\n @enrolupdate=\"page.studylines[lineindex].enrol = $event\"\n :class=\" 't-studyline' + ((lineindex%2==0)?' odd ' :' even ' )\n + ((lineindex==0)?' first ':' ')\n + ((lineindex==page.studylines.length-1)?' last ':' ')\"\n ></r-studyline-heading\n ></div>\n <!-- Next, paint all the cells in the scrollable -->\n <div class=\"r-studyplan-scrollable\" >\n <div class=\"r-studyplan-timeline\" :style=\"columns_stylerule(page)\">\n <!-- add period information -->\n <template v-for=\"(n,index) in (page.periods+1)\">\n <s-studyline-header-period\n v-if=\"index > 0\"\n v-model=\"page.perioddesc[index-1]\"\n :identifier=\"Number(page.id)\"\n ><a v-if=\"teachermode && selectedpage\"\n v-b-tooltip.hover\n :href=\"wwwroot+'//local/treestudyplan/result-overview.php?page='+selectedpage.id\n +'&firstperiod='+index+'&lastperiod='+index\"\n target='_blank'\n :title=\"text.overviewperiod\"><i class='fa fa-list-ul'></i></a\n ></s-studyline-header-period>\n <div class=\"s-studyline-header-filter\"></div>\n </template>\n\n <!-- Line by line add the items -->\n <!-- The grid layout handles putting it in rows and columns -->\n <template v-for=\"(line,lineindex) in page.studylines\"\n ><template v-for=\"(layernr,layeridx) in countLineLayers(line,page)\"\n ><template v-for=\"(n,index) in (page.periods+1)\"\n ><r-studyline-slot\n v-if=\"index > 0 && showslot(page,line, index, layeridx, 'gradable')\"\n type='gradable'\n v-model=\"line.slots[index].courses\"\n :key=\"'c-'+lineindex+'-'+index+'-'+layernr\"\n :slotindex=\"index\"\n :line=\"line\"\n :plan=\"value\"\n :page=\"page\"\n :period=\"page.perioddesc[index-1]\"\n :guestmode='guestmode'\n :teachermode='teachermode'\n :layer=\"layeridx\"\n :class=\"'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')\n + ((lineindex==0 && layernr==1)?' first ':' ')\n + ((lineindex==page.studylines.length-1)?' last ':' ')\n + ((layernr == countLineLayers(line,page))?' lastlyr ':' ')\"\n ></r-studyline-slot\n ><r-studyline-slot\n v-if=\"showslot(page,line, index, layeridx, 'filter')\"\n type='filter'\n v-model=\"line.slots[index].filters\"\n :teachermode='teachermode'\n :key=\"'f-'+lineindex+'-'+index+'-'+layernr\"\n :slotindex=\"index\"\n :line=\"line\"\n :plan=\"value\"\n :page=\"page\"\n :layer=\"layeridx\"\n :class=\"'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')\n + ((lineindex==0 && layernr==1)?' first ':'')\n + ((lineindex==page.studylines.length-1)?' last ':' ')\n + ((index==page.periods)?' rightmost':'')\n + ((layernr == countLineLayers(line,page))?' lastlyr ':' ')\"\n >\n </r-studyline-slot\n ></template\n ></template\n ></template\n ></div\n ></div\n ></div>\n </b-tab>\n </b-tabs>\n </b-card>\n </div>\n `,\n });\n\n /*\n * R-STUDYLINE-HEADER\n */\n Vue.component('r-studyline-heading', {\n props: {\n value : {\n type: Object, // Studyline\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n },\n layers: {\n type: Number,\n default: 1,\n },\n studentid: {\n type: Number,\n },\n },\n data() {\n return {\n layerHeights: {},\n text: strings.lineheader,\n students: null,\n can_unenrol: false,\n sorting: {\n asc: true,\n field: 'enrolled'\n }\n };\n },\n created() {\n // Listener for the signal that a new connection was made and needs to be drawn\n // Sent by the incoming item - By convention, outgoing items are responsible for drawing the lines\n ItemEventBus.$on('lineHeightChange', this.onLineHeightChange);\n },\n computed: {\n enrollable() {\n return this.value.enrol.enrollable > ENROLLABLE_NONE;\n },\n enrollable_self() {\n return [ENROLLABLE_SELF,ENROLLABLE_SELF_ROLE].includes(this.value.enrol.enrollable);\n },\n enrollable_role() {\n return [ENROLLABLE_ROLE,ENROLLABLE_SELF_ROLE].includes(this.value.enrol.enrollable);\n },\n enrolled() {\n return this.value.enrol.enrolled?true:false;\n },\n can_enrol() {\n return this.value.enrol.can_enrol?true:false;\n },\n enrol_question() {\n return this.text.enrol_question.replace('{$a}',this.value.name);\n },\n enrolled_in() {\n return this.text.enrolled_in.replace('{$a}',this.value.name);\n },\n by() {\n return this.text.byname.replace('{$a}','');\n },\n enrolldate() {\n return format_datetime(this.value.enrol.enrolled_time);\n },\n sorted_students() {\n const self =this;\n const list = Array.isArray(this.students)?this.students:[];\n list.sort((a,b) => {\n let d = a;\n let e = b;\n if (!self.sorting.asc) {\n d = b;\n e = a;\n } \n let df = d;\n let ef = e;\n const field = self.sorting.field;\n if (d.user && d.user.hasOwnProperty(field)) {\n df = d.user;\n ef = e.user;\n } else if (d.enrol && d.enrol.hasOwnProperty(field)) {\n df = d.enrol;\n ef = e.enrol;\n }\n if (field == 'enrolled') {\n return ((df.enrolled)?1:0) - ((ef.enrolled)?1:0);\n } else {\n return String(d[this.sorting.header]).localeCompare(String(e[this.sorting.header]));\n }\n\n });\n return list;\n }\n },\n methods: {\n premiumenabled,\n onLineHeightChange(lineid){\n // All layers for this line have the first slot send an update message on layer height change.\n // When one of those updates is received, record the height and recalculate the total height of the\n // header\n if(this.$refs.mainEl && (lineid == this.value.id || lineid === null)){\n const items = document.querySelectorAll(\n `.r-studyline-slot-0[data-studyline='${this.value.id}']`);\n // determine the height of all the lines and add them up.\n let heightSum = 0;\n items.forEach((el) => {\n // getBoundingClientRect() Gets the actual fractional height instead of rounded to integer pixels\n const r = el.getBoundingClientRect();\n const height = r.height;\n heightSum += height;\n });\n\n const heightStyle=`${heightSum}px`;\n this.$refs.mainEl.style.height = heightStyle;\n }\n },\n enrol_self() {\n const self=this;\n call([{\n methodname: 'local_treestudyplan_line_enrol_self',\n args: { id: self.value.id},\n }])[0].then(function(response){\n self.$emit('enrolupdate',response);\n }).catch(notification.exception);\n },\n\n enrol_student(id) {\n const self=this;\n call([{\n methodname: 'local_treestudyplan_line_enrol_students',\n args: { id: self.value.id, users: [id] },\n }])[0].then(function(response){\n self.$emit('enrolupdate',response);\n }).catch(notification.exception);\n },\n unenrol_student(id) {\n const self=this;\n call([{\n methodname: 'local_treestudyplan_line_unenrol_students',\n args: { id: self.value.id, users: [id] },\n }])[0].then(function(response){\n self.$emit('enrolupdate',response);\n }).catch(notification.exception);\n },\n load_students() {\n const self=this;\n call([{\n methodname: 'local_treestudyplan_list_line_enrolled_students',\n args: { id: self.value.id },\n }])[0].then(function(response){\n self.students = response.userinfo;\n self.can_unenrol = response.can_unenrol;\n }).catch(notification.exception);\n\n \n }\n\n },\n template: `\n <div class=\"r-studyline r-studyline-heading \"\n :data-studyline=\"value.id\" ref=\"mainEl\"\n ><div class=\"r-studyline-handle\" :style=\"'background-color: ' + value.color\"></div>\n <div class=\"r-studyline-title\"><div>\n <abbr v-b-tooltip.hover :title=\"value.name\">{{ value.shortname }}</abbr>\n <template v-if=\"premiumenabled() && enrollable\">\n <template v-if=\"teachermode\">\n <a v-if=\"!can_enrol\"\n href='#' @click.prevent=\"\"\n v-b-modal=\"'r-enrollments-'+value.id\"\n :title=\"text.cannot_enrol\"\n ><i class='fa fa-lock text-danger'></i>&nbsp;{{text.enrollments}}</a>\n <a v-else\n href='#' @click.prevent=\"\"\n v-b-modal=\"'r-enrollments-'+value.id\"\n :title=\"text.can_enrol\"\n ><i class='fa fa-unlock-alt text-success'></i>&nbsp;{{text.enrollments}}</a>\n <b-modal\n :id=\"'r-enrollments-'+value.id\"\n ok-only\n scrollable\n >\n <table>\n <tr v-if=\"students == null\"><td>\n <div class=\"spinner-border spinner-border-sm text-info\" role=\"status\"></div>\n </td></tr>\n <template v-if=\"students && can_enrol\">\n <tr v-for=\"student in students\">\n\n </template>\n <template v-else-if=\"students\">\n \n </template>\n </table>\n </b-modal>\n </template>\n <template v-else>\n <a v-if=\"!enrolled && !can_enrol\"\n href='#' @click.prevent=\"\"\n v-b-tooltip.focus\n :title=\"text.cannot_enrol\"\n ><i class='fa fa-lock text-danger'></i>&nbsp;{{text.cannot_enrol}}</a>\n <a v-else-if=\"!enrolled && can_enrol\"\n href='#' @click.prevent=\"\"\n v-b-modal=\"'r-enrol-'+value.id\"\n :title=\"text.can_enrol\"\n ><i class='fa fa-unlock-alt text-success'></i>&nbsp;{{text.enrol}}</a>\n <a v-else-if=\"enrolled\"\n href='#' @click.prevent=\"\"\n v-b-modal=\"'r-enrollment-'+value.id\"\n :title=\"text.enrolled\"\n ><i class='fa fa-unlock text-success'></i>&nbsp;{{text.enrolled}}</a>\n <b-modal\n :id=\"'r-enrol-'+value.id\"\n :title=\"text.confirm\"\n :ok-title=\"text.yes\"\n :cancel-title=\"text.no\"\n ok-variant=\"success\"\n cancel-variant=\"danger\"\n @ok=\"enrol_self\"\n >\n <p>{{enrol_question}}</p>\n </b-modal>\n <b-modal\n :id=\"'r-enrollment-'+value.id\"\n ok-only\n :title=\"text.enrollment\"\n >\n <p>{{enrolled_in}}<p>\n <p><b>{{text.since}}</b> {{enrolldate}}<br>\n <b>{{by}}</b> {{this.value.enrol.enrolled_by}}</p>\n </b-modal> \n </template>\n </template>\n </div></div>\n </div>\n `,\n });\n\n Vue.component('r-studyline-slot', {\n props: {\n value: {\n type: Array, // item to display\n default(){ return [];},\n },\n type : {\n type: String,\n default: 'gradable',\n },\n slotindex : {\n type: Number,\n default: 0,\n },\n line : {\n type: Object,\n default(){ return null;},\n },\n layer : {\n type: Number,\n },\n plan: {\n type: Object,\n default(){ return null;},\n },\n page: {\n type: Object,\n default(){ return null;},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n },\n period: {\n type: Object,\n default(){ return null;},\n }\n },\n mounted() {\n const self=this;\n if(self.type == \"gradable\" && self.slotindex == 1){\n self.resizeListener = new ResizeObserver(() => {\n if(self.$refs.sizeElement){\n const height = self.$refs.sizeElement.getBoundingClientRect().height;\n ItemEventBus.$emit('lineHeightChange', self.line.id, self.layer, height);\n }\n }).observe(self.$refs.sizeElement);\n }\n },\n computed: {\n item(){\n for(const ix in this.value){\n const itm = this.value[ix];\n if(itm.layer == this.layer){\n return itm;\n }\n }\n return null;\n },\n spanCss(){\n if(this.item && this.item.span > 1){\n const span = (2 * this.item.span) - 1;\n return `width: 100%; grid-column: span ${span};`;\n } else {\n return \"\";\n }\n }\n },\n data() {\n return {\n };\n },\n methods: {\n\n },\n template: `\n <div :class=\" 'r-studyline-slot ' + type + ' '\n + 'r-studyline-slot-' + slotindex + ' '\n + ((slotindex==0)?'r-studyline-firstcolumn ':' ')\"\n :data-studyline=\"line.id\" ref=\"sizeElement\"\n :style='spanCss'\n ><div class=\"r-slot-item\" v-if=\"item\"\n ><r-item\n v-model=\"item\"\n :plan=\"plan\"\n :guestmode='guestmode'\n :teachermode='teachermode'></r-item\n ></div\n ></r-item\n ></div>\n `,\n });\n\n\n Vue.component('r-item', {\n props: {\n value :{\n type: Object,\n default: function(){ return null;},\n },\n plan: {\n type: Object,\n default(){ return null;}\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n lines: [],\n };\n },\n methods: {\n lineColor(){\n if(this.teachermode){\n return \"var(--gray)\";\n }\n else{\n switch(this.value.completion){\n default: // \"incomplete\"\n return \"var(--gray)\";\n case \"failed\":\n return \"var(--danger)\";\n case \"progress\":\n return \"var(--warning)\";\n case \"completed\":\n return \"var(--success)\";\n case \"good\":\n return \"var(--info)\";\n case \"excellent\":\n return \"var(--blue)\";\n }\n }\n },\n redrawLine(conn){\n let lineColor = this.lineColor();\n // draw new line...\n let start = document.getElementById('studyitem-'+conn.from_id);\n let end= document.getElementById('studyitem-'+conn.to_id);\n\n // delete old line\n if(this.lines[conn.to_id]){\n this.lines[conn.to_id].remove();\n delete this.lines[conn.to_id];\n }\n\n if(start !== null && end !== null && isVisible(start) && isVisible(end)){\n this.lines[conn.to_id] = new SimpleLine(start,end,{\n color: lineColor,\n gravity: {\n start: LINE_GRAVITY,\n end: LINE_GRAVITY,\n },\n });\n }\n },\n redrawLines(){\n // Clean all old lines\n for(let ix in this.lines){\n let lineinfo = this.lines[ix];\n if(lineinfo && lineinfo.line){\n lineinfo.line.remove();\n lineinfo.line = undefined;\n }\n }\n\n // Create new lines\n for(let i in this.value.connections.out){\n let conn = this.value.connections.out[i];\n this.redrawLine(conn);\n }\n },\n onWindowResize(){\n this.redrawLines();\n },\n onRedrawLines(){\n this.redrawLines();\n },\n removeLine(conn){\n if(this.lines[conn.to_id]){\n this.lines[conn.to_id].remove();\n delete this.lines[conn.to_id];\n }\n },\n\n },\n computed: {\n hasConnectionsOut() {\n return !([\"finish\",].includes(this.value.type));\n },\n hasConnectionsIn() {\n return !([\"start\",].includes(this.value.type));\n },\n hasContext() {\n return ['start','junction','finish'].includes(this.value.type);\n }\n },\n created(){\n ItemEventBus.$on('redrawLines', this.onRedrawLines);\n },\n mounted(){\n // Initialize connection lines when mounting\n\n this.redrawLines();\n setTimeout(()=>{\n this.redrawLines();\n },50);\n\n // Add resize event listener\n window.addEventListener('resize',this.onWindowResize);\n },\n beforeDestroy(){\n for(let i in this.value.connections.out){\n let conn = this.value.connections.out[i];\n this.removeLine(conn);\n }\n // Remove resize event listener\n window.removeEventListener('resize',this.onWindowResize);\n ItemEventBus.$off('redrawLines', this.onRedrawLines);\n },\n beforeUpdate(){\n },\n updated(){\n if(!this.dummy) {\n this.redrawLines();\n }\n },\n template: `\n <div class=\"r-item-base\" :id=\"'studyitem-'+value.id\" :data-x='value.type'>\n <r-item-competency v-if=\"value.type == 'competency'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-competency>\n <r-item-course v-if=\"value.type == 'course' && !teachermode\" :plan=\"plan\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-course>\n <r-item-teachercourse v-if=\"value.type == 'course' && teachermode\" :plan=\"plan\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-teachercourse>\n <r-item-junction v-if=\"value.type == 'junction'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-junction>\n <r-item-start v-if=\"value.type == 'start'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-start>\n <r-item-finish v-if=\"value.type == 'finish'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-finish>\n <r-item-badge v-if=\"value.type == 'badge'\"\n v-model=\"value\" :guestmode=\"guestmode\" :teachermode=\"teachermode\" ></r-item-badge>\n <r-item-invalid v-if=\"value.type == 'invalid' && teachermode\"\n v-model=\"value\" ></r-item-invalid>\n </div>\n `,\n });\n\n Vue.component('r-item-invalid', {\n props: {\n 'value' :{\n type: Object,\n default: function(){ return null;},\n },\n },\n data() {\n return {\n text: strings.invalid,\n };\n },\n methods: {\n },\n template: `\n <div class=\"r-item-invalid\">\n <b-card no-body class=\"r-item-invalid\">\n <b-row no-gutters>\n <b-col md=\"1\">\n <span class=\"r-timing-indicator timing-invalid\"></span>\n </b-col>\n <b-col md=\"11\">\n <b-card-body class=\"align-items-center\">\n <i class=\"fa fa-exclamation\"></i> {{ text.error }}\n </b-card-body>\n </b-col>\n </b-row>\n </b-card>\n </div>\n `,\n });\n\n //TAG: Item Course\n Vue.component('r-item-course', {\n props: {\n value :{\n type: Object,\n default(){ return null;},\n },\n guestmode: {\n type: Boolean,\n default(){ return false;}\n },\n teachermode: {\n type: Boolean,\n default(){ return false;}\n },\n plan: {\n type: Object,\n default(){ return null;}\n }\n },\n data() {\n return {\n text: strings.course,\n };\n },\n computed: {\n startdate(){\n return format_date(this.value.course.startdate);\n },\n enddate(){\n if(this.value.course.enddate){\n return format_date(this.value.course.enddate);\n }\n else {\n return this.text.noenddate;\n }\n },\n courseprogress() {\n if (!this.value.course.enrolled) {\n return 0;\n } else if(this.value.course.completion) {\n return (this.value.course.completion.progress / this.value.course.completion.count); \n } else if(this.value.course.competency) {\n return (this.value.course.competency.progress / this.value.course.competency.count); \n } else if(this.value.course.grades) {\n return (this.gradeprogress(this.value.course.grades) / this.value.course.grades.length); \n } else {\n return 0;\n }\n },\n hasprogressinfo() {\n if (!this.value.course.enrolled) {\n return false;\n } else {\n return (this.value.course.completion || this.value.course.competency || this.value.course.grades);\n }\n },\n wwwroot() {\n return Config.wwwroot;\n }\n },\n created(){\n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return \"circle-o\";\n case \"pending\":\n return \"question-circle\";\n case \"failed\":\n return \"times-circle\";\n case \"progress\":\n return \"exclamation-circle\";\n case \"completed\":\n return \"check-circle\";\n case \"good\":\n return \"check-circle\";\n case \"excellent\":\n return \"check-circle\";\n }\n },\n circle_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return null;\n case \"failed\":\n return \"times\";\n case \"progress\":\n return \"\";\n case \"completed\":\n return \"check\";\n case \"good\":\n return \"check\";\n case \"excellent\":\n return \"check\";\n }\n },\n gradeprogress(grades) {\n let progress = 0;\n for (const ix in grades) {\n const g = grades[ix];\n if ([\"completed\",\"excellent\",\"good\"].includes(g.completion)) {\n progress++;\n }\n }\n return progress;\n },\n },\n template: `\n <div :class=\"'r-item-competency completion-'+value.completion\">\n <b-card no-body >\n <b-row no-gutters>\n <b-col md=\"1\">\n <span\n :title=\"text['coursetiming_'+value.course.timing]\"\n v-b-popover.hover.top=\"startdate+' - '+enddate\"\n :class=\"'r-timing-indicator timing-'+value.course.timing\"></span>\n </b-col>\n <b-col md=\"11\" class=\"align-items-center\">\n <b-card-body >\n <template v-if='!value.course.enrolled'>\n <i v-b-popover.top\n class=\"r-course-result fa fa-exclamation-triangle t-not-enrolled-alert\"\n :title=\"text.student_not_tracked\"></i>\n </template>\n <template v-else-if='hasprogressinfo'>\n <r-progress-circle v-if='[\"failed\", \"progress\",\"incomplete\"].includes(value.completion)'\n :value='courseprogress'\n :max='1'\n :min='0'\n :class=\"'r-course-result r-completion-'+value.completion\"\n :icon='circle_icon(value.completion)'\n :title=\"text['completion_'+value.completion]\"\n ></r-progress-circle>\n <i v-else v-b-popover.top\n :class=\"'r-course-result fa fa-'+completion_icon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <template v-else>\n <i v-b-popover.top\n :class=\"'r-course-result fa fa-'+completion_icon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <a v-b-modal=\"'r-item-course-details-'+value.id\"\n :href=\"(!guestmode)?(wwwroot+'/course/view.php?id='+value.course.id):'#'\"\n @click.prevent.stop=''\n >{{ value.course.displayname }}</i></a>\n </b-card-body>\n </b-col>\n </b-row>\n\n <b-modal\n :id=\"'r-item-course-details-'+value.id\"\n :title=\"value.course.displayname + ' - ' + value.course.fullname\"\n size=\"lg\"\n ok-only\n centered\n scrollable\n header-class=\"r-item-course-header\"\n >\n <template #modal-header >\n <div class=\"r-item-course-header-details\">\n <div>\n <h1><a :href=\"(!guestmode)?(wwwroot+'/course/view.php?id='+value.course.id):undefined\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a></h1>\n {{ value.course.context.path.join(\" / \")}}\n </div>\n <div class=\"r-course-detail-header-right\">\n <div class=\"r-completion-detail-header\">\n <template v-if='!value.course.enrolled'>\n {{text.not_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='hasprogressinfo && !value.course.showprogressbar'>\n {{text['completion_'+value.completion]}}\n <r-progress-circle v-if='[\"failed\", \"progress\",\"incomplete\"].includes(value.completion)'\n :value='courseprogress'\n :max='1'\n :min='0'\n :class=\"'r-progress-circle-popup r-completion-'+value.completion\"\n :icon='circle_icon(value.completion)'\n :title=\"text['completion_'+value.completion]\"\n ></r-progress-circle>\n <i v-else v-b-popover.top\n :class=\"'fa fa-'+completion_icon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n <template v-else>\n {{text['completion_'+value.completion]}}\n <i :class=\"'fa fa-'+completion_icon(value.completion)+' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n </div>\n <div :class=\"'r-timing-'+value.course.timing\">\n {{text['coursetiming_'+value.course.timing]}}<br>\n {{ startdate }} - {{ enddate }}\n </div>\n </div>\n </div>\n <s-progress-bar \n v-if='value.course.showprogressbar && hasprogressinfo'\n v-model=\"courseprogress\"\n ></s-progress-bar>\n </template>\n <s-course-extrafields \n v-if=\"value.course.extrafields\" \n v-model=\"value.course.extrafields\"\n position=\"above\"\n ></s-course-extrafields>\n <r-item-studentgrades\n v-if='!!value.course.grades && value.course.grades.length > 0'\n v-model='value'\n :guestmode='guestmode'></r-item-studentgrades>\n <r-item-studentcompletion\n v-if='!!value.course.completion'\n v-model='value.course.completion'\n :course='value.course'\n :guestmode='guestmode'></r-item-studentcompletion>\n <r-item-student-course-competency\n v-if='!!value.course.competency'\n v-model='value.course.competency'\n :item='value'\n ></r-item-student-course-competency>\n <s-course-extrafields \n v-if=\"value.course.extrafields\" \n v-model=\"value.course.extrafields\"\n position=\"below\"\n ></s-course-extrafields>\n </b-modal>\n </b-card></div>\n `,\n });\n\n //Selected activities dispaly\n Vue.component('r-item-studentgrades',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n },\n data() {\n return {\n text: strings.course,\n };\n },\n computed: {\n pendingsubmission(){\n let result = false;\n for(const ix in this.value.course.grades){\n const g = this.value.course.grades[ix];\n if(g.pendingsubmission){\n result = true;\n break;\n }\n }\n return result;\n },\n useRequiredGrades() {\n if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useRequiredGrades !== undefined){\n return this.plan.aggregation_info.useRequiredGrades;\n }\n else {\n return false;\n }\n },\n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n default: // case \"incomplete\"\n return \"circle-o\";\n case \"pending\":\n return \"question-circle\";\n case \"failed\":\n return \"times-circle\";\n case \"progress\":\n return \"exclamation-circle\";\n case \"completed\":\n return \"check-circle\";\n case \"good\":\n return \"check-circle\";\n case \"excellent\":\n return \"check-circle\";\n }\n },\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <tr v-for=\"g in value.course.grades\">\n <td><span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span\n ><a\n :href=\"(!guestmode)?(g.link):undefined\" target=\"_blank\"><span v-html=\"g.name\"></span></a>\n <abbr v-if=\"useRequiredGrades && g.required\" :title=\"text.required_goal\"\n :class=\"'s-required ' + g.completion\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td><span :class=\"' r-completion-'+g.completion\">{{g.grade}}</span></td>\n <td><i :class=\"'fa fa-'+completion_icon(g.completion)+' r-completion-'+g.completion\"\n :title=\"text['completion_'+g.completion]\"></i>\n <i v-if='g.pendingsubmission' :title=\"text['completion_pending']\"\n class=\"r-pendingsubmission fa fa-clock-o\"></i></td>\n <td v-if=\"g.feedback\">\n <a v-b-modal=\"'r-grade-feedback-'+g.id\"\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+g.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-graduation-cap\"></i>{{ value.course.fullname }}</h2><br>\n <span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span>{{g.name}}\n </template>\n <span v-html=\"g.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </table>\n `,\n });\n\n // Core completion version of student course info\n Vue.component('r-item-studentcompletion',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n course: {\n type: Object,\n default: function(){ return {};},\n },\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n created(){\n },\n computed: {\n },\n methods: {\n completion_icon(completion) {\n switch(completion){\n case \"progress\":\n return \"exclamation-circle\";\n case \"complete\":\n return \"check-circle\";\n case \"complete-pass\":\n return \"check-circle\";\n case \"complete-fail\":\n return \"times-circle\";\n default: // case \"incomplete\"\n return \"circle-o\";\n }\n },\n completion_tag(cgroup){\n return cgroup.completion?'completed':'incomplete';\n },\n hasCompletions() {\n if(this.value.conditions) {\n for(const cgroup of this.value.conditions){\n if(cgroup.items && cgroup.items.length > 0){\n return true;\n }\n }\n }\n return false;\n },\n requirementHTML(requirements) {\n const rqs = requirements.split(/, */);\n let html = \"\";\n for(const ix in rqs) {\n const rq = rqs[ix];\n html += `${rq}<br>`;\n }\n return html;\n },\n addTargetBlank(html) {\n const m = /^([^<]*\\< *a +)(.*)/.exec(html);\n if(m){\n return `${m[1]} target=\"_blank\" ${m[2]}`;\n } else {\n return html;\n }\n }\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <tr v-if=\"hasCompletions\">\n <td colspan='2'\n ><span v-if=\"value.conditions.length <= 1\">{{ text.aggregation_overall_one }}</span\n ><span v-else if=\"value.aggregation == 'all'\">{{ text.aggregation_overall_all}}</span\n ><span v-else>{{ text.aggregation_overall_any }}</span\n ></td>\n </tr>\n <tr v-else>\n <td colspan='2'>{{text.completion_not_configured}}!\n </td>\n </tr>\n <template v-for='cgroup in value.conditions' v-if='value.enabled && value.tracked'>\n <tr>\n <th colspan='2'><span v-if=\"cgroup.items.length > 1\"\n ><span v-if=\"cgroup.aggregation == 'all'\">{{ text.aggregation_all}}</span\n ><span v-else>{{ text.aggregation_any}}</span></span\n ><span v-else>{{ text.aggregation_one }}</span>\n {{ cgroup.title.toLowerCase() }}:\n </th>\n <th><r-progress-circle v-if=\"cgroup.progress < cgroup.count\"\n :value='cgroup.progress'\n :max='cgroup.count'\n :class=\"'r-completion-'+cgroup.status\"\n :title=\"text['completion_'+cgroup.status]\"\n ></r-progress-circle>\n <i v-else :class=\"'fa fa-check-circle r-completion-'+cgroup.status\"></i>\n </th>\n </tr>\n <tr v-for='ci in cgroup.items'>\n <td><span v-if='guestmode'><span v-html=\"ci.title\"></span></span>\n <span v-else v-html='addTargetBlank(ci.details.criteria)'></span>\n <a href=\"#\" v-b-tooltip.click.hover.right.html=\"{ customClass: 'r-tooltip ' + ci.status}\"\n :title=\"requirementHTML(ci.details.requirement)\"\n class=\"text-primary\"><i v-if=\"ci.details.requirement\"\n class='fa fa-question-circle'\n ></i></a>\n <td\n ><span :class=\"' r-completion-'+ci.status\">{{ci.grade}}</span>\n <span v-if=\"ci.warning\"\n ><i class=\"text-primary fa fa-exclamation-triangle\"\n v-b-tooltip.hover.right.click=\"{ customClass: 'r-tooltip info' }\"\n :title=\"ci.warning\"\n ></i\n ></span\n ></td>\n <td><i :class=\"'fa fa-'+completion_icon(ci.status)+' r-completion-'+ci.status\"\n :title=\"text['completion_'+ci.status]\"></i>\n <i v-if='ci.pending' :title=\"text['completion_pending']\"\n class=\"r-pendingsubmission fa fa-clock-o\"></i>\n </td>\n <td v-if=\"ci.feedback\">\n <a v-b-modal=\"'r-grade-feedback-'+ci.id\"\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+ci.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-graduation-cap\"></i>{{ course.fullname }}</h2><br>\n <span class=\"r-activity-icon\" :title=\"ci.typename\" v-html=\"ci.icon\"></span>{{ci.name}}\n </template>\n <span v-html=\"ci.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </template>\n <template v-else>\n <tr v-if='! value.enabled'>\n <td colspan='4'>{{text.completion_not_enabled}}</td>\n </tr>\n <tr v-else>\n <td colspan='4'>{{text.student_not_tracked}}</td>\n </tr>\n </template>\n </table>\n `,\n });\n\n //TAG: STUDENT Course competency\n Vue.component('r-item-student-course-competency',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n item: {\n type: Object,\n default: function(){ return { id: null};},\n }\n },\n data() {\n return {\n text: strings.competency,\n };\n },\n created(){\n\n },\n computed: {\n hasCompletions() {\n if(this.value.conditions) {\n for(const cgroup of this.value.conditions){\n if(cgroup.items && cgroup.items.length > 0){\n return true;\n }\n }\n }\n return false;\n },\n wwwroot() {\n return Config.wwwroot;\n }\n },\n methods: {\n completion_icon(competency) {\n if (competency.proficient && competency.courseproficient) {\n return \"check-circle\";\n } else if (competency.proficient) {\n return \"check\";\n } else if (competency.proficient === false) {\n return \"times-circle\";\n } else {\n return \"circle-o\";\n }\n },\n\n completion_tag(competency){\n if (competency.proficient && competency.courseproficient) {\n return \"completed\";\n } else if (competency.proficient) {\n return \"completed\";\n } else if (competency.proficient === false) {\n return \"failed\";\n } else if (competency.progress) {\n return \"progress\";\n } else {\n return \"incomplete\";\n }\n },\n\n pathtags(competency) {\n const path = competency.path;\n let s = \"\";\n for (const ix in path) {\n const p = path[ix];\n if ( ix > 0) {\n s += \" / \";\n }\n let url;\n if (p.type =='competency') { \n url = Config.wwwroot+`/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${p.id}`;\n } else {\n url = this.competencyurl(p);\n }\n \n s += `<a href=\"${url}\" target=\"_blank\">${p.title}</a>`;\n }\n return s;\n },\n competencyurl(c) {\n return Config.wwwroot+`/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${c.id}`;\n },\n usercompetencyurl(c) {\n return Config.wwwroot+`/admin/tool/lp/user_competency.php?id=${c.ucid}`;\n }\n },\n template: `\n <table class=\"r-item-course-competency-list\">\n <tr v-if=\"value.competencies.length == 0\">\n <td colspan='2'>{{text.competencies_not_configured}}!\n <br><a :href=\"wwwroot+'/admin/tool/lp/coursecompetencies.php?courseid='+item.course.id\" target='_blank'>{{text.configure_competencies}}</a>\n </td>\n </tr>\n <template v-else>\n <tr v-for='c in value.competencies'>\n <td>\n <a href=\"#\" v-b-modal=\"'modal-competency-id-'+c.id\" @click.prevent.stop=''><span v-html='c.title' ></span></a>\n </td>\n <td class='details' >\n <a v-if=\"c.details\" href=\"#\" v-b-modal=\"'modal-competency-id-'+c.id\" @click.prevent.stop='' ><span v-html='c.details'></span></a>\n <abbr v-if=\"c.required\" :title=\"text.required\"\n :class=\"'s-required ' + + completion_tag(c)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr> \n </td>\n <td :colspan=\"(c.required)?1:2\">\n <span :class=\"'r-completion-'+completion_tag(c)\">\n <template v-if=\"!c.progress && !c.count\">\n <i :class=\"'fa fa-'+completion_icon(c)\" :title=\"text['completion_'+completion_tag(c)]\"></i>\n {{ (c.proficient === null)?text.unrated:c.grade }}\n </template>\n <template v-else>\n <r-progress-circle v-if='!c.proficient'\n :value='c.progress'\n :max='c.count'\n :min='0'\n :class=\"'r-completion-'+completion_tag(c)\"\n :title=\"text['completion_'+completion_tag(c)]\"\n ></r-progress-circle>\n <i v-else :class=\"'fa fa-'+completion_icon(c)\" :title=\"text['completion_'+completion_tag(c)]\"></i>\n {{ (c.proficient === null)?((c.progress)?text.progress:text.unrated):c.grade }}\n </template>\n </span>\n </td>\n <td v-if=\"c.feedback\">\n <a v-b-modal=\"'r-competency-feedback-'+c.id\"\n @click.prevent.stop=''\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+c.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-puzzle-piece\"></i>{{ c.title }}</h2><br>\n </template>\n <span v-html=\"c.feedback\"></span>\n </b-modal>\n </td>\n <b-modal :id=\"'modal-competency-id-'+c.id\"\n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><i class=\"fa fa-puzzle-piece\"></i>\n <a :href=\"wwwroot+'/admin/tool/lp/competencies.php?competencyid='+c.id\" target=\"_blank\"\n >{{c.title}} {{c.details}} </a\n ></h1>\n <div><span v-html=\"pathtags(c)\"></span></div>\n </div>\n </template>\n <div class=\"mb-2\" v-if=\"c.description\"><span v-html='c.description'></span></div>\n\n <template v-if=\"c.rule && c.children\">\n <div>{{ c.ruleoutcome }} {{ text.when}} <span v-html=\"c.rule.toLocaleLowerCase()\"></span></div>\n <table v-if=\"c.children\" class='r-item-course-competency-list'>\n <tr class='t-item-course-competency-headers'>\n <th colspan=\"2\">{{text.heading}}</th>\n <th colspan=\"3\">{{text.results}}</th>\n </tr>\n <tr v-for=\"cc in c.children\">\n <td >\n <a :href='usercompetencyurl(cc)' target=\"_blank\"><span v-html='cc.title'></span></a>\n </td>\n <td class='details'>\n <a v-if=\"cc.details\" :href='usercompetencyurl(cc)' target=\"_blank\"><span v-html='cc.details'></span></a>\n <abbr v-if=\"c.required\" :title=\"text.required\"\n :class=\"'s-required ' + + completion_tag(cc)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td><span :class=\"'r-completion-'+completion_tag(cc)\"\n ><i :class=\"'fa fa-'+completion_icon(cc)\" :title=\"text['completion_'+completion_tag(cc)]\"></i>\n {{ (cc.proficient === null)?text.unrated:cc.grade }}</span></td>\n <td><span class=\"text-info\">{{ cc.points }} {{ text.points }}</span></td>\n <td>\n </td>\n <td v-if=\"cc.feedback\">\n <a v-b-modal=\"'r-competency-feedback-'+cc.id\"\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+cc.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-puzzle-piece\"></i>{{ cc.title }}</h2><br>\n </template>\n <span v-html=\"cc.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </table>\n </template>\n </b-modal>\n </tr>\n </template>\n </table>\n `,\n });\n\n //TAG: Teacher course\n Vue.component('r-item-teachercourse', {\n props: {\n value :{\n type: Object,\n default(){ return null;}\n },\n guestmode: {\n type: Boolean,\n default(){ return false;}\n },\n teachermode: {\n type: Boolean,\n default(){ return false;}\n },\n plan: {\n type: Object,\n default(){ return null;}\n }\n },\n data() {\n return {\n text: strings.teachercourse,\n txt: {\n grading: strings.grading,\n }\n };\n },\n computed: {\n course_grading_needed(){\n return this.course_grading_state();\n },\n course_grading_icon(){\n return this.determine_grading_icon(this.course_grading_state());\n },\n filtered_grades(){\n return this.value.course.grades.filter(g => g.selected);\n },\n useRequiredGrades() {\n if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useRequiredGrades !== undefined){\n return this.plan.aggregation_info.useRequiredGrades;\n }\n else {\n return false;\n }\n },\n isCompletable() {\n let completable = false;\n if(this.value.course.completion){\n if(this.value.course.completion.conditions.length > 0){\n completable = true;\n }\n } else if (this.value.course.grades){\n if(this.value.course.grades.length > 0){\n completable = true;\n }\n }\n\n return completable;\n },\n progress_circle() { \n const status = {\n students: 0,\n completed: 0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };\n\n if(this.value.course.completion) {\n for(const cond of this.value.course.completion.conditions) {\n for(const itm of cond.items) {\n if(itm.progress) {\n status.students += itm.progress.students;\n status.completed += itm.progress.completed;\n status.completed_pass += itm.progress.completed_pass;\n status.completed_fail += itm.progress.completed_fail;\n status.ungraded += itm.progress.ungraded;\n }\n }\n }\n } else if (this.value.course.competency) {\n status.students = this.value.course.competency.total;\n status.completed = this.value.course.competency.proficient;\n } else if (this.value.course.grades) {\n for( const g of this.value.course.grades) {\n if(g.grading) {\n status.students += g.grading.students;\n status.completed += g.grading.completed;\n status.completed_pass += g.grading.completed_pass;\n status.completed_fail += g.grading.completed_fail;\n status.ungraded += g.grading.ungraded;\n }\n }\n } \n\n return status;\n },\n startdate(){\n return format_date(this.value.course.startdate);\n },\n enddate(){\n if(this.value.course.enddate){\n return format_date(this.value.course.enddate);\n }\n else {\n return this.text.noenddate;\n }\n },\n wwwroot() {\n return Config.wwwroot;\n }\n\n },\n created(){\n\n },\n methods: {\n course_grading_state(){\n let ungraded = 0;\n let unknown = 0;\n let graded = 0;\n let allgraded = 0;\n const grades = this.filtered_grades;\n\n if(!Array.isArray(grades) || grades == 0){\n return 'nogrades';\n }\n\n for(const ix in grades){\n const grade = grades[ix];\n if(grade.grading){\n if(Number(grade.grading.ungraded) > 0){\n ungraded++;\n }\n else if(Number(grade.grading.graded) > 0) {\n if(Number(grade.grading.graded) == Number(grade.grading.students)){\n allgraded++;\n } else {\n graded++;\n }\n }\n } else {\n unknown = true;\n }\n }\n\n if(ungraded > 0){\n return 'ungraded';\n } else if(unknown) {\n return 'unknown';\n } else if(graded){\n return 'graded';\n } else if(allgraded){\n return 'allgraded';\n } else {\n return 'unsubmitted';\n }\n },\n determine_grading_icon(gradingstate){\n switch(gradingstate){\n default: // \"nogrades\":\n return \"circle-o\";\n case \"ungraded\":\n return \"exclamation-circle\";\n case \"unknown\":\n return \"question-circle-o\";\n case \"graded\":\n return \"check\";\n case \"allgraded\":\n return \"check\";\n case \"unsubmitted\":\n return \"dot-circle-o\";\n }\n },\n },\n template: `\n <div :class=\"'r-item-competency '+ (value.course.amteacher?'r-course-am-teacher':'')\">\n <b-card no-body>\n <div class='d-flex flex-wrap mr-0 ml-0'>\n <div>\n <span\n :title=\"text['coursetiming_'+value.course.timing]\"\n v-b-popover.hover.top=\"startdate+' - '+enddate\"\n :class=\"'r-timing-indicator timing-'+value.course.timing\"></span>\n </div>\n <div class=\"flex-fill align-items-center\">\n <b-card-body>\n <a v-b-modal=\"'r-item-course-details-'+value.id\"\n :href=\"(!guestmode)?(wwwroot+'/course/view.php?id='+value.course.id):'#'\"\n @click.prevent.stop=''\n >{{ value.course.displayname }}</i></a>\n <r-completion-circle class=\"r-course-graded\" :disabled=\"!isCompletable\"\n v-model=\"progress_circle\"></r-completion-circle>\n </b-card-body>\n </div>\n </div>\n <b-modal\n v-if=\"true\"\n :id=\"'r-item-course-details-'+value.id\"\n :title=\"value.course.displayname + ' - ' + value.course.fullname\"\n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><a :href=\"(!guestmode)?(wwwroot+'/course/view.php?id='+value.course.id):undefined\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a>\n <r-item-teacher-gradepicker v-model=\"value\"\n v-if=\"value.course.grades && value.course.grades.length > 0\"\n :useRequiredGrades=\"useRequiredGrades\"\n :plan=\"plan\"\n ></r-item-teacher-gradepicker>\n <a v-if='!!value.course.completion && value.course.amteacher'\n :href=\"wwwroot+'/course/completion.php?id='+value.course.id\" target=\"_blank\"\n :title=\"text.configure_completion\"><i class=\"fa fa-gear\"></i></a>\n </h1>\n {{ value.course.context.path.join(\" / \") }}\n <div class='mt-1 text-info'>\n <span v-if='value.course.numenrolled != 1'>{{ value.course.numenrolled }} {{ text.students_from_plan_enrolled }}</span>\n <span v-else> 1 {{ text.student_from_plan_enrolled }} </span>\n </div>\n </div>\n <div class=\"r-course-detail-header-right\">\n <div class=\"r-completion-detail-header\">\n <r-completion-circle class=\"r-progress-circle-popup\" :disabled=\"!isCompletable\"\n v-model=\"progress_circle\"></r-completion-circle>\n </div>\n <div :class=\"'r-timing-'+value.course.timing\">\n {{ text['coursetiming_'+value.course.timing] }}<br>\n {{ startdate }} - {{ enddate }}\n </div>\n </div>\n </template>\n <s-course-extrafields \n v-if=\"value.course.extrafields\" \n v-model=\"value.course.extrafields\"\n position=\"above\"\n ></s-course-extrafields>\n <r-item-teachergrades\n v-if='!!value.course.grades && value.course.grades.length > 0'\n v-model='value.course'\n :useRequiredGrades=\"useRequiredGrades\"\n ></r-item-teachergrades>\n <r-item-teachercompletion\n v-if='!!value.course.completion'\n v-model='value.course.completion'\n :course='value.course'\n ></r-item-teachercompletion>\n <r-item-teacher-course-competency\n v-if='!!value.course.competency'\n v-model='value.course.competency'\n :item='value'\n ></r-item-teacher-course-competency>\n <s-course-extrafields \n v-if=\"value.course.extrafields\" \n v-model=\"value.course.extrafields\"\n position=\"below\"\n ></s-course-extrafields>\n </b-modal>\n\n </b-card>\n </div>\n `,\n });\n\n\n //Select activities to use in grade overview\n Vue.component('r-item-teacher-gradepicker', {\n props: {\n value : {\n type: Object, // Item\n default: function(){ return {};},\n },\n useRequiredGrades: {\n type: Boolean,\n default(){ return null;}\n }\n },\n data() {\n return {\n text: strings.teachercourse,\n };\n },\n computed: {\n wwwroot() {\n return Config.wwwroot;\n }\n },\n methods: {\n includeChanged(newValue,g){\n call([{\n methodname: 'local_treestudyplan_include_grade',\n args: { 'grade_id': g.id,\n 'item_id': this.value.id,\n 'include': newValue,\n 'required': g.required,\n }\n }])[0].catch(notification.exception);\n },\n requiredChanged(newValue,g){\n call([{\n methodname: 'local_treestudyplan_include_grade',\n args: { 'grade_id': g.id,\n 'item_id': this.value.id,\n 'include': g.selected,\n 'required': newValue,\n }\n }])[0].catch(notification.exception);\n },\n },\n template: `\n <a v-if=\"value.course.canselectgradables\" href='#'\n v-b-modal=\"'r-item-course-config-'+value.id\"\n @click.prevent.stop=''\n ><i class='fa fa-cog'></i>\n <b-modal v-if='value.course.canselectgradables'\n :id=\"'r-item-course-config-'+value.id\"\n :title=\"value.course.displayname + ' - ' + value.course.fullname\"\n ok-only\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><a :href=\"wwwroot+'/course/view.php?id='+value.course.id\" target=\"_blank\"\n ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a></h1>\n {{ value.course.context.path.join(\" / \")}} / {{value.course.displayname}}\n </div>\n <div class=\"r-course-detail-header-right\">\n <div :class=\"'r-timing-'+value.course.timing\">\n {{text['coursetiming_'+value.course.timing]}}<br>\n {{ value.course.startdate }} - {{ value.course.enddate }}\n </div>\n </div>\n <s-\n </template>\n <b-form-group\n :label=\"text.select_grades\"\n ><ul class=\"t-item-module-children\">\n <li class=\"t-item-course-gradeinfo\">\n <span class='t-item-course-chk-lbl'>{{text.grade_include}}</span\n ><span v-if=\"useRequiredGrades\" class='t-item-course-chk-lbl'>{{text.grade_require}}</span>\n </li>\n <li class=\"t-item-course-gradeinfo\" v-for=\"g in value.course.grades\">\n <b-form-checkbox inline\n @change=\"includeChanged($event,g)\" v-model=\"g.selected\"\n ></b-form-checkbox>\n <b-form-checkbox v-if=\"useRequiredGrades\" inline :disabled=\"!g.selected\"\n @change=\"requiredChanged($event,g)\" v-model=\"g.required\"\n ></b-form-checkbox>\n <span :title=\"g.typename\" v-html=\"g.icon\"></span><a\n :href=\"g.link\" target=\"_blank\">{{g.name}}</a>\n <s-edit-mod\n :title=\"value.course.fullname\"\n @saved=\"(fd) => g.name = fd.get('name')\"\n v-if=\"g.cmid > 0\"\n :cmid=\"g.cmid\"\n :coursectxid=\"value.course.ctxid\"\n genericonly></s-edit-mod>\n </li>\n </ul>\n </b-form-group>\n </b-modal>\n </a>\n `,\n });\n\n\n\n //Selected activities dispaly\n Vue.component('r-item-teachergrades',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n useRequiredGrades: {\n type: Boolean,\n default: false,\n },\n },\n data() {\n return {\n text: strings.teachercourse,\n txt: {\n grading: strings.grading,\n }\n };\n },\n computed: {\n pendingsubmission(){\n let result = false;\n for(const ix in this.value.grades){\n const g = this.value.grades[ix];\n if(g.pendingsubmission){\n result = true;\n break;\n }\n }\n return result;\n },\n filtered_grades(){\n return this.value.grades.filter(g => g.selected);\n },\n },\n methods: {\n determine_grading_icon(gradingstate){\n switch(gradingstate){\n default: // \"nogrades\":\n return \"circle-o\";\n case \"ungraded\":\n return \"exclamation-circle\";\n case \"unknown\":\n return \"question-circle-o\";\n case \"graded\":\n return \"check\";\n case \"allgraded\":\n return \"check\";\n case \"unsubmitted\":\n return \"dot-circle-o\";\n }\n },\n grading_icon(grade){\n return this.determine_grading_icon(this.is_grading_needed(grade));\n },\n is_grading_needed(grade){\n if(grade.grading){\n if(grade.grading.ungraded){\n return 'ungraded';\n }\n else if(grade.grading.completed_pass || grade.grading.completed || grade.grading.completed_fail) {\n if(Number(grade.grading.completed) + Number(grade.grading.completed_pass)\n + Number(grade.grading.completed_fail)\n == Number(grade.grading.students)){\n return 'allgraded';\n }\n else {\n return 'graded';\n }\n }\n else {\n return 'unsubmitted';\n }\n } else {\n return 'unknown';\n }\n },\n\n },\n template: `\n <div>\n <table class=\"r-item-course-grade-details\">\n <tr v-for=\"g in filtered_grades\">\n <td><span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon\"></span\n ><a\n :href=\"g.gradinglink\"\n target=\"_blank\" :title=\"g.name\"><span v-html=\"g.name\"></span></a>\n <s-edit-mod\n :title=\"value.fullname\"\n @saved=\"(fd) => g.name = fd.get('name')\"\n v-if=\"g.cmid > 0\"\n :cmid=\"g.cmid\"\n :coursectxid=\"value.ctxid\"\n genericonly></s-edit-mod>\n <abbr v-if=\"useRequiredGrades && g.required\" :title=\"text.required_goal\"\n :class=\"'s-required ' + is_grading_needed(g)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td v-if='g.grading'\n ><i :class=\"'r-course-grading fa fa-'+grading_icon(g)+' r-graded-'+is_grading_needed(g)\"\n :title=\"txt.grading[is_grading_needed(g)]\"></i>\n </td>\n <td v-if='g.grading'>\n <r-completion-bar v-model=\"g.grading\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </td>\n </tr>\n </table>\n </div>\n `,\n });\n\n // Core completion version of student course info\n Vue.component('r-item-teachercompletion',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n course: {\n type: Object,\n default: function(){ return {};},\n },\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n created(){\n const self = this;\n // Get text strings for condition settings\n let stringkeys = [];\n for(const key in this.text){\n stringkeys.push({ key: key, component: 'local_treestudyplan'});\n }\n get_strings(stringkeys).then(function(strings){\n let i = 0;\n for(const key in self.text){\n self.text[key] = strings[i];\n i++;\n }\n });\n },\n computed: {\n completionreport(){\n return `${Config.wwwroot}/report/completion/index.php?course=${this.course.id}`;\n },\n wwwroot() {\n return Config.wwwroot;\n }\n\n },\n methods: {\n hasCompletions() {\n if(this.value.conditions) {\n for(const cgroup of this.value.conditions){\n if(cgroup.items && cgroup.items.length > 0){\n return true;\n }\n }\n }\n return false;\n },\n },\n template: `\n <table class=\"r-item-course-grade-details\">\n <tr v-if=\"hasCompletions\">\n <td colspan='2'\n ><span v-if=\"value.conditions.length <= 1\">{{ text.aggregation_overall_one }}</span\n ><span v-else if=\"value.aggregation == 'all'\">{{ text.aggregation_overall_all}}</span\n ><span v-else>{{ text.aggregation_overall_any }}</span\n ></td>\n </tr>\n <tr v-else>\n <td colspan='2'>{{text.completion_not_configured}}!\n <span v-if=\"course.amteacher\">\n <br><a :href=\"wwwroot+'/course/completion.php?id='+course.id\" target='_blank'>{{text.configure_completion}}</a>\n </span>\n </td>\n </tr>\n <template v-for='cgroup in value.conditions'>\n <tr>\n <th colspan='2'><span v-if=\"cgroup.items.length > 1\"\n ><span v-if=\"cgroup.aggregation == 'all'\">{{ text.aggregation_all}}</span\n ><span v-else>{{ text.aggregation_any}}</span></span\n ><span v-else>{{ text.aggregation_one }}</span>\n {{ cgroup.title.toLowerCase() }}:\n </th>\n </tr>\n <tr v-for='ci in cgroup.items'>\n <td><span v-html='ci.details.criteria'></span>\n <a href=\"#\" v-b-tooltip.click\n :title=\"ci.details.requirement\"\n class='text-info'><i v-if=\"ci.details.requirement\"\n class='fa fa-question-circle'\n ></i></a>\n </td>\n <td>\n <r-completion-bar v-model=\"ci.progress\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </td>\n </tr>\n </template>\n <tr><td colspan='2' class='pt-2'>\n <a target=\"_blank\" :href='completionreport'>{{ text.view_completion_report}}\n <i class='fa fa-external-link'></i></a></td></tr>\n </table>\n `,\n });\n\n\n //TAG: Teacher Course competency\n Vue.component('r-item-teacher-course-competency',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n item: {\n type: Object,\n default: function(){ return { id: null};},\n }\n },\n data() {\n return {\n text: strings.competency,\n };\n },\n created(){\n\n },\n computed: {\n hasCompletions() {\n if(this.value.conditions) {\n for(const cgroup of this.value.conditions){\n if(cgroup.items && cgroup.items.length > 0){\n return true;\n }\n }\n }\n return false;\n },\n wwwroot() {\n return Config.wwwroot;\n }\n },\n methods: {\n completion_icon(competency) {\n if (competency.proficient && competency.courseproficient) {\n return \"check-circle\";\n } else if (competency.proficient) {\n return \"check\";\n } else if (competency.proficient === false) {\n return \"times-circle\";\n } else {\n return \"circle-o\";\n }\n },\n\n completion_tag(competency){\n if (competency.proficient && competency.courseproficient) {\n return \"completed\";\n } else if (competency.proficient) {\n return \"completed\";\n } else if (competency.proficient === false) {\n return \"failed\";\n } else if (competency.progress) {\n return \"progress\";\n } else {\n return \"incomplete\";\n }\n },\n\n pathtags(competency) {\n const path = competency.path;\n let s = \"\";\n for (const ix in path) {\n const p = path[ix];\n if ( ix > 0) {\n s += \" / \";\n }\n let url;\n if (p.type =='competency') { \n url = Config.wwwroot+`/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${p.id}`;\n } else {\n url = this.competencyurl(p);\n }\n \n s += `<a href=\"${url}\" target=\"_blank\">${p.title}</a>`;\n }\n return s;\n },\n competencyurl(c) {\n return Config.wwwroot+`/admin/tool/lp/user_competency_in_course.php?courseid=${this.item.course.id}&competencyid=${c.id}`;\n },\n },\n template: `\n <table class=\"r-item-course-competency-list\">\n <tr v-if=\"value.competencies.length == 0\">\n <td colspan='2'>{{text.competencies_not_configured}}!\n <br><a :href=\"wwwroot+'/admin/tool/lp/coursecompetencies.php?courseid='+item.course.id\" target='_blank'>{{text.configure_competencies}}</a>\n </td>\n </tr>\n <template v-else>\n <tr v-for='c in value.competencies'>\n <td>\n <a href=\"#\" v-b-modal=\"'modal-competency-id-'+c.id\"><span v-html='c.title'></span></a>\n </td>\n <td class='details'>\n <a v-if=\"c.details\" href=\"#\" v-b-modal=\"'modal-competency-id-'+c.id\"><span v-html='c.details'></span></a>\n <abbr v-if=\"c.required\" :title=\"text.required\"\n :class=\"'s-required ' + + completion_tag(c)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr> \n </td>\n <td><r-completion-bar v-model=\"c.completionstats\" :width=\"150\" :height=\"15\"></td>\n <td v-if=\"c.feedback\">\n <a v-b-modal=\"'r-competency-feedback-'+c.id\"\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+c.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-puzzle-piece\"></i>{{ c.title }}</h2><br>\n </template>\n <span v-html=\"c.feedback\"></span>\n </b-modal>\n </td>\n <b-modal :id=\"'modal-competency-id-'+c.id\"\n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><i class=\"fa fa-puzzle-piece\"></i>\n <a :href=\"wwwroot+'/admin/tool/lp/competencies.php?competencyid='+c.id\" target=\"_blank\"\n >{{c.title}} {{c.details}} </a\n ></h1>\n <div><span v-html=\"pathtags(c)\"></span></div>\n </div>\n </template>\n <div class=\"mb-2\" v-if=\"c.description\"><span v-html='c.description'></span></div>\n\n <template v-if=\"c.rule && c.children\">\n <div>{{ c.ruleoutcome }} {{ text.when}} <span v-html=\"c.rule.toLocaleLowerCase()\"></span></div>\n <table v-if=\"c.children\" class='r-item-course-competency-list'>\n <tr class='t-item-course-competency-headers'>\n <th colspan=\"2\">{{text.heading}}</th>\n <th colspan=\"3\">{{text.results}}</th>\n </tr>\n <tr v-for=\"cc in c.children\">\n <td>\n <a :href='competencyurl(cc)' target=\"_blank\"><span v-html='cc.title'></span></a>\n </td>\n <td class='details'>\n <a v-if=\"cc.details\" :href='competencyurl(cc)' target=\"_blank\"><span v-html='cc.details'></span></a>\n <abbr v-if=\"c.required\" :title=\"text.required\"\n :class=\"'s-required ' + completion_tag(cc)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td><r-completion-bar v-model=\"cc.completionstats\" :width=\"150\" :height=\"15\"></r-completion-bar></td>\n <td><span class=\"text-info\">{{ cc.points }} {{ text.points }}</span></td>\n <td v-if=\"cc.feedback\">\n <a v-b-modal=\"'r-competency-feedback-'+cc.id\"\n href=\"#\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+cc.id\"\n size=\"sm\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <h2><i class=\"fa fa-puzzle-piece\"></i>{{ cc.title }}</h2><br>\n </template>\n <span v-html=\"cc.feedback\"></span>\n </b-modal>\n </td>\n </tr>\n </table>\n </template>\n </b-modal>\n </tr>\n </template>\n </table>\n `,\n });\n\n\n Vue.component('r-grading-bar',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n width: {\n type: Number,\n default: 150,\n },\n height: {\n type: Number,\n default: 15,\n }\n },\n data() {\n return {\n text: strings.grading,\n };\n },\n computed: {\n width_unsubmitted() {\n return this.width * this.fraction_unsubmitted();\n },\n width_graded() {\n return this.width * this.fraction_graded();\n },\n width_ungraded() {\n return this.width * this.fraction_ungraded();\n },\n count_unsubmitted(){\n return (this.value.students - this.value.graded - this.value.ungraded);\n }\n },\n methods: {\n fraction_unsubmitted() {\n if(this.value.students > 0){\n return 1 - ((this.value.graded + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_graded() {\n if(this.value.students > 0){\n return this.value.graded / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <span class=\"r-grading-bar\" :style=\"{height: height+'px'}\"\n ><span :style=\"{height: height+'px', width: width_ungraded+'px'}\"\n class='r-grading-bar-segment r-grading-bar-ungraded'\n :title=\"text.ungraded + ' (' + this.value.ungraded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_graded+'px'}\"\n class='r-grading-bar-segment r-grading-bar-graded'\n :title=\"text.graded+ ' (' + this.value.graded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_unsubmitted+'px'}\"\n class='r-grading-bar-segment r-grading-bar-unsubmitted'\n :title=\"text.unsubmitted + ' (' + count_unsubmitted + ')'\" v-b-popover.hover.top\n ></span\n ></span>\n `,\n });\n\n Vue.component('r-completion-bar',{\n props: {\n value : {\n type: Object,\n default: function(){ return {\n students: 0,\n completed: 0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };},\n },\n width: {\n type: Number,\n default: 150,\n },\n height: {\n type: Number,\n default: 15,\n }\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n computed: {\n width_incomplete() {\n return this.width * this.fraction_incomplete();\n },\n width_completed() {\n return this.width * this.fraction_completed();\n },\n width_completed_pass() {\n return this.width * this.fraction_completed_pass();\n },\n width_completed_fail() {\n return this.width * this.fraction_completed_fail();\n },\n width_ungraded() {\n return this.width * this.fraction_ungraded();\n },\n count_incomplete(){\n return (this.value.students - this.value.completed - this.value.completed_pass\n - this.value.completed_fail - this.value.ungraded);\n }\n },\n methods: {\n fraction_incomplete() {\n if(this.value.students > 0){\n return 1 - (\n (this.value.completed + this.value.completed_pass +\n this.value.completed_fail + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_completed() {\n if(this.value.students > 0){\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_pass() {\n if(this.value.students > 0){\n return this.value.completed_pass / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_fail() {\n if(this.value.students > 0){\n return this.value.completed_fail / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <span class=\"r-grading-bar\" :style=\"{height: height+'px'}\"\n ><span :style=\"{height: height+'px', width: width_ungraded+'px'}\"\n class='r-grading-bar-segment r-completion-bar-ungraded'\n :title=\"text.ungraded + ' (' + this.value.ungraded + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed'\n :title=\"text.completed + ' (' + this.value.completed + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed_pass+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed-pass'\n :title=\"text.completed_pass + ' (' + this.value.completed_pass + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_completed_fail+'px'}\"\n class='r-grading-bar-segment r-completion-bar-completed-fail'\n :title=\"text.completed_fail + ' (' + this.value.completed_fail + ')'\" v-b-popover.hover.top\n ></span\n ><span :style=\"{height: height+'px', width: width_incomplete+'px'}\"\n class='r-grading-bar-segment r-completion-bar-incomplete'\n :title=\"text.incomplete + ' (' + count_incomplete + ')'\" v-b-popover.hover.top\n ></span\n ></span>\n `,\n });\n\n Vue.component('r-completion-circle',{\n props: {\n value : {\n type: Object,\n default: function(){ return {\n students: 10,\n completed: 2,\n completed_pass: 2,\n completed_fail: 2,\n ungraded: 2,\n };},\n },\n stroke: {\n type: Number,\n default: 0.2,\n },\n disabled: {\n type: Boolean,\n default: false,\n },\n title: {\n type: String,\n default: \"\",\n }\n },\n computed: {\n radius() {\n return 50 - (50*this.stroke);\n },\n\n arcpath_ungraded() {\n const begin = 0;\n return this.arcpath(begin,this.fraction_ungraded());\n },\n arcpath_completed() {\n const begin = this.fraction_ungraded();\n return this.arcpath(begin,this.fraction_completed());\n },\n arcpath_completed_pass() {\n const begin = this.fraction_ungraded()\n + this.fraction_completed();\n return this.arcpath(begin,this.fraction_completed_pass());\n },\n arcpath_completed_fail() {\n const begin = this.fraction_ungraded()\n + this.fraction_completed()\n + this.fraction_completed_pass();\n return this.arcpath(begin,this.fraction_completed_fail());\n },\n arcpath_incomplete() {\n const begin = this.fraction_ungraded()\n + this.fraction_completed()\n + this.fraction_completed_pass()\n + this.fraction_completed_fail();\n return this.arcpath(begin,this.fraction_incomplete());\n },\n\n },\n methods: {\n arcpath(start, end) {\n const r = 50 - (50*this.stroke);\n\n const t1 = start * 2*π;\n const Δ = end * 2*π;\n return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π);\n },\n fraction_incomplete() {\n if(this.value.students > 0){\n return 1 - (\n (this.value.completed + this.value.completed_pass +\n this.value.completed_fail + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fraction_completed() {\n if(this.value.students > 0){\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_pass() {\n if(this.value.students > 0){\n return this.value.completed_pass / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_completed_fail() {\n if(this.value.students > 0){\n return this.value.completed_fail / this.value.students;\n } else {\n return 0;\n }\n },\n fraction_ungraded() {\n if(this.value.students > 0){\n return this.value.ungraded / this.value.students;\n } else {\n return 0;\n }\n },\n },\n template: `\n <svg width=\"1em\" height=\"1em\" viewBox=\"0 0 100 100\">\n <title>{{title}}</title>\n <circle cx=\"50\" cy=\"50\" :r=\"radius\"\n :style=\"'stroke-width: ' + (stroke*100)+'; stroke: #ccc; fill: none;'\"/>\n <path :d=\"arcpath_ungraded\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--warning); fill: none;'\"/>\n <path :d=\"arcpath_completed\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--info); fill: none;'\"/>\n <path :d=\"arcpath_completed_pass\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--success); fill: none;'\"/>\n <path :d=\"arcpath_completed_fail\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--danger); fill: none;'\"/>\n\n <circle v-if=\"disabled\" cx=\"50\" cy=\"50\" :r=\"radius/2\"\n :style=\"'fill: var(--dark);'\"/>\n <circle v-else-if=\"value.ungraded > 0\" cx=\"50\" cy=\"50\" :r=\"radius/2\"\n :style=\"'fill: var(--warning);'\"/>\n </g>\n </svg>\n `,\n });\n\n Vue.component('r-item-junction',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n },\n methods: {\n\n },\n template: `\n <div :class=\"'r-item-junction r-item-filter completion-'+completion\">\n <i v-if=\"value.completion=='incomplete'\" class=\"fa fa-circle-o\"></i>\n <i v-else-if=\"value.completion=='failed'\" class=\"fa fa-times-circle\"></i>\n <i v-else-if=\"value.completion=='progress'\" class=\"fa fa-exclamation-circle\"></i>\n <i v-else class=\"fa fa-check-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-finish',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-finish r-item-filter completion-'+completion\">\n <i class=\"fa fa-stop-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-start',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n };\n },\n computed: {\n completion(){\n if(this.value.completion){\n return this.value.completion;\n } else {\n return \"incomplete\";\n }\n }\n },\n created(){\n\n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-start r-item-filter completion-'+completion\">\n <i class=\"fa fa-play-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-badge',{\n props: {\n value : {\n type: Object,\n default: function(){ return {};},\n },\n guestmode: {\n type: Boolean,\n default: false,\n },\n teachermode: {\n type: Boolean,\n default: false,\n }\n },\n data() {\n return {\n text: strings.badge,\n };\n },\n computed: {\n completion() {\n return this.value.badge.issued?\"completed\":\"incomplete\";\n },\n issued_icon(){\n switch(this.value.badge.issued){\n default: // \"nogrades\":\n return \"circle-o\";\n case true:\n return \"check\";\n }\n },\n issuestats(){\n // so the r-completion-bar can be used to show issuing stats\n return {\n students: (this.value.badge.studentcount)?this.value.badge.studentcount:0,\n completed: (this.value.badge.issuedcount)?this.value.badge.issuedcount:0,\n completed_pass: 0,\n completed_fail: 0,\n ungraded: 0,\n };\n },\n arcpath_issued(){\n if(this.value.badge.studentcount){\n const fraction = this.value.badge.issuedcount/this.value.badge.studentcount;\n return this.arcpath(0,fraction);\n } else {\n return \"\"; // no path\n }\n },\n arcpath_progress(){\n if(this.value.badge.completion){\n const fraction = this.value.badge.completion.progress/this.value.badge.completion.count;\n return this.arcpath(0,fraction);\n } else {\n return \"\"; // no path\n }\n },\n badgeinprogress(){\n return ( this.value.badge.issued\n || this.teachermode\n || (this.value.badge.completion \n && this.value.badge.completion.progress >= this.value.badge.completion.count)\n );\n }\n },\n methods: {\n arcpath(start, end) {\n const r = 44;\n\n const t1 = start * 2*π;\n const Δ = (end * 2*π-0.01);\n return svgarcpath([50,50],[r,r],[t1,Δ], 1.5*π);\n },\n addTargetBlank(html) {\n const m = /^([^<]*\\< *a +)(.*)/.exec(html);\n if(m){\n return `${m[1]} target=\"_blank\" ${m[2]}`;\n } else {\n return html;\n }\n },\n completion_icon_rq(complete) {\n if (complete) {\n return \"check-square-o\";\n } else {\n return \"square-o\";\n }\n },\n completion_icon(complete) {\n if (complete) {\n return \"check-circle\";\n } else {\n return \"times-circle\";\n }\n },\n status(complete) {\n if (complete) {\n return \"complete\";\n } else {\n return \"incomplete\";\n }\n }\n },\n template: `\n <div :class=\"'r-item-badge r-item-filter r-completion-'+completion\" v-b-tooltip.hover :title=\"value.badge.name\">\n <a v-b-modal=\"'r-item-badge-details-'+value.id\"\n ><svg class=\"r-badge-backdrop \" width='50px' height='50px' viewBox=\"0 0 100 100\">\n <title>{{value.badge.name}}</title>\n <template v-if=\"teachermode\">\n <circle cx=\"50\" cy=\"50\" r=\"44\"\n style=\"stroke: #ccc; stroke-width: 8; fill: #ddd; fill-opacity: 0.8;\"/>\n <path :d=\"arcpath_issued\"\n :style=\"'stroke-width: 8; stroke: var(--info); fill: none;'\"/>\n </template>\n <circle v-else-if=\"value.badge.issued\" cx=\"50\" cy=\"50\" r=\"46\"\n style=\"stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;\"/>\n <template v-else-if=\"value.badge.completion\">\n <circle cx=\"50\" cy=\"50\" r=\"44\"\n style=\"stroke: #ccc; stroke-width: 8; fill: #ddd; fill-opacity: 0.8;\"/>\n <path :d=\"arcpath_progress\"\n :style=\"'stroke-width: 8; stroke: var(--info); fill: none;'\"/>\n </template>\n <circle v-else cx=\"50\" cy=\"50\" r=\"46\"\n stroke-dasharray=\"6 9\"\n style=\"stroke: #999; stroke-width: 6; fill: #ddd; fill-opacity: 0.8;\"/>\n <image class=\"badge-image\" clip-path=\"circle() fill-box\"\n :href=\"value.badge.imageurl\" x=\"12\" y=\"12\" width=\"76\" height=\"76\"\n :style=\"(badgeinprogress)?'':'opacity: 0.4;'\" />\n </svg></a>\n\n <b-modal\n :id=\"'r-item-badge-details-'+value.id\"\n :title=\"value.badge.name\"\n size=\"lg\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h1><i class=\"fa fa-certificate\"></i>\n <a :href=\"(!guestmode)?(value.badge.infolink):undefined\" target=\"_blank\"\n >{{ value.badge.name }}</a\n ></h1>\n </div>\n <div class=\"r-course-detail-header-right\" v-if=\"!teachermode\">\n <div class=\"r-completion-detail-header\">\n {{ text['completion_'+completion] }}\n <i v-b-popover.hover :class=\"'fa fa-'+issued_icon+' r-completion-'+completion\"\n :title=\"text['completion_'+completion]\"></i>\n </div>\n </div>\n </template>\n <b-container fluid>\n <b-row><b-col cols=\"3\">\n <img :src=\"value.badge.imageurl\"/>\n </b-col><b-col cols=\"9\">\n <p>{{value.badge.description}}</p>\n <ul v-if=\"value.badge.issued\" class=\"list-unstyled pt-1 mb-1 border-grey border-top\">\n <li><strong><i class=\"fa fa-calendar-check-o r-completion-complete-pass\"></i>\n {{text.dateissued}}:</strong> {{ value.badge.dateissued }}</li>\n <li v-if='value.badge.dateexpired'\n ><strong><i class=\"fa fa-calendar-times-o r-completion-complete\"></i>\n {{text.dateexpired}}:</strong> {{ value.badge.dateexpired }}</li>\n <li><strong><i class=\"fa fa-share-alt r-completion-complete-pass\"></i>\n <a :href=\"value.badge.issuedlink\">{{text.share_badge}}</a></strong> </li>\n </ul>\n <table v-if='value.badge.completion && !value.badge.issued' class=\"r-item-course-grade-details mb-2\">\n <tr v-if=\"value.badge.completion.types.length > 1\">\n <th colspan=\"2\"><span v-html=\"value.badge.completion.title\"></span></th>\n </tr>\n <template v-for='cgroup in value.badge.completion.types' >\n <tr>\n <td colspan=\"2\" v-if=\"value.badge.completion.types.length > 1\"\n ><span v-html=\"cgroup.title\"></span></td>\n <th colspan=\"2\" v-else><span v-html=\"cgroup.title\"></span></th>\n </tr>\n <template v-for='ci in cgroup.criteria'>\n <tr>\n <td class=\"pl-3\"><span v-if='guestmode'><span v-html=\"ci.title\"></span></span>\n <a target='_blank' v-else-if='ci.link' :href='ci.link'\n ><span v-html=\"ci.title\"></span></a>\n <span v-else><span v-html=\"ci.title\"></span></span>\n <td><i :class=\"'fa fa-'+completion_icon(ci.completed)+' r-completion-'+status(ci.completed)\"\n :title=\"text['completion_'+status(ci.completed)]\"></i>\n </td>\n </tr>\n <template v-if=\"ci.requirements.length > 1\">\n <tr v-for=\"rq in ci.requirements\">\n <td class=\"pl-4\" colspan=\"2\"\n ><i :class=\"'fa fa-'+completion_icon_rq(rq.completed)+' r-completion-incomplete'\"\n :title=\"text['completion_'+status(rq.completed)]\"></i>\n <span class=\"t-badge-criteria-requirement\"><span v-html=\"rq.title\"></span></span></td>\n </tr>\n </template>\n </template>\n </template>\n <tr v-if=\"!value.badge.active\" class=\"mt-1\">\n <td colspan=\"2\" class=\"alert alert-warning alert-block\">{{text.badgedisabled}}</td>\n </tr>\n </table>\n <ul class=\"list-unstyled w-100 border-grey border-top border-bottom pt-1 pb-1 mb-1\"\n v-if=\"value.badge.criteria\"><li v-for=\"crit in value.badge.criteria\"\n ><span v-html='crit'></span></li></ul>\n <p v-if=\"(!guestmode)\"><strong><i class=\"fa fa-link\"></i>\n <a :href=\"value.badge.infolink\" target=\"_blank\"\n >{{ text.badgeinfo }}</a></strong></p>\n <p v-if=\"teachermode && !guestmode\"\n >{{text.badgeissuedstats}}:<br>\n <r-completion-bar v-model=\"issuestats\" :width=\"150\" :height=\"15\"></r-completion-bar>\n </p>\n </b-col></b-row>\n </b-container>\n </b-modal>\n </div>\n `,\n });\n },\n};"],"names":["π","Math","PI","ENROLLABLE_SELF","ENROLLABLE_ROLE","ENROLLABLE_SELF_ROLE","install","Vue","use","TSComponents","Debugger","lastCaller","scrollCurrentIntoView","handle","elCurrentHeader","document","querySelector","scrollIntoView","behavior","block","inline","strings","report","loading","studyplan_past","studyplan_present","studyplan_future","back","invalid","error","grading","ungraded","graded","allgraded","unsubmitted","nogrades","unknown","completion","completed","incomplete","completed_pass","completed_fail","aggregation_all","aggregation_any","aggregation_one","aggregation_overall_all","aggregation_overall_any","aggregation_overall_one","completion_not_configured","configure_completion","view_completion_report","completion_incomplete","completion_failed","completion_pending","completion_progress","completion_completed","completion_good","completion_excellent","view_feedback","coursetiming_past","coursetiming_present","coursetiming_future","required_goal","student_not_tracked","completion_not_enabled","badge","share_badge","dateissued","dateexpire","badgeinfo","badgeissuedstats","completioninfo","badgedisabled","course","not_enrolled","teachercourse","select_conditions","select_grades","grade_include","grade_require","student_from_plan_enrolled","students_from_plan_enrolled","competency","competency_not_configured","configure_competency","when","required","points","heading","details","results","unrated","progress","pageinfo","edit","fullname","shortname","startdate","enddate","description","duration","overview","oveviewperiod","lineheader","cannot_enrol","can_enrol","is_enrolled","enrol","enrolled","notenrolled","enrol_question","enrollments","enrollment","info","confirm","yes","no","enrolled_in","since","byname","isVisible","elem","offsetWidth","offsetHeight","getClientRects","length","ItemEventBus","addEventListener","editSwEventTypes","editModeSet","e","preventDefault","$emit","detail","editMode","component","props","value","type","Number","max","default","min","stroke","bgopacity","title","String","icon","data","selectedstudyplan","computed","range","this","fraction","radius","arcpath","r","Δ","methods","template","invitekey","userid","text","studyplans","past","present","future","loadingstudyplan","teachermode","guestmode","verified_type","includes","studyplancount","updated","mounted","loadStudyplans","call_args","o","args","Array","isArray","self","methodname","then","response","console","plans","ix","plan","push","sort","a","b","t","Date","getTime","name","localeCompare","selectStudyplan","lengh","catch","notification","exception","studyplanid","id","deselectStudyplan","Object","Boolean","selectedpageindex","selectedpage","pages","startpageindex","firststart","page","s","wwwroot","Config","pageduration","columns","periods","columns_stylerule","i","countLineLayers","line","maxLayer","slots","courses","item","layer","filters","showslot","index","layeridx","forGradable","show","list","span","selectedpageChanged","newTabIndex","prevTabIndex","$root","layers","studentid","layerHeights","students","can_unenrol","sorting","asc","field","created","$on","onLineHeightChange","enrollable","enrollable_self","enrollable_role","replace","by","enrolldate","enrolled_time","sorted_students","d","df","ef","user","hasOwnProperty","header","premiumenabled","lineid","$refs","mainEl","items","querySelectorAll","heightSum","forEach","el","height","getBoundingClientRect","heightStyle","style","enrol_self","enrol_student","users","unenrol_student","load_students","userinfo","slotindex","period","resizeListener","ResizeObserver","sizeElement","observe","itm","spanCss","lines","lineColor","redrawLine","conn","start","getElementById","from_id","end","to_id","remove","SimpleLine","color","gravity","redrawLines","lineinfo","undefined","connections","out","onWindowResize","onRedrawLines","removeLine","hasConnectionsOut","hasConnectionsIn","hasContext","setTimeout","window","beforeDestroy","removeEventListener","$off","beforeUpdate","dummy","noenddate","courseprogress","count","grades","gradeprogress","hasprogressinfo","completion_icon","circle_icon","g","pendingsubmission","result","useRequiredGrades","aggregation_info","completion_tag","cgroup","hasCompletions","conditions","requirementHTML","requirements","rqs","split","html","addTargetBlank","m","exec","proficient","courseproficient","pathtags","path","p","url","competencyurl","c","usercompetencyurl","ucid","txt","course_grading_needed","course_grading_state","course_grading_icon","determine_grading_icon","filtered_grades","filter","selected","isCompletable","completable","progress_circle","status","cond","total","grade","gradingstate","includeChanged","newValue","requiredChanged","grading_icon","is_grading_needed","stringkeys","key","completionreport","width","width_unsubmitted","fraction_unsubmitted","width_graded","fraction_graded","width_ungraded","fraction_ungraded","count_unsubmitted","width_incomplete","fraction_incomplete","width_completed","fraction_completed","width_completed_pass","fraction_completed_pass","width_completed_fail","fraction_completed_fail","count_incomplete","disabled","arcpath_ungraded","arcpath_completed","begin","arcpath_completed_pass","arcpath_completed_fail","arcpath_incomplete","t1","issued","issued_icon","issuestats","studentcount","issuedcount","arcpath_issued","arcpath_progress","badgeinprogress","completion_icon_rq","complete"],"mappings":"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"}