moodle_local_treestudyplan/amd/build/report-viewer-components.min.js.map

1 line
202 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 promise/no-nesting: \"off\" */\n/* eslint max-depth: [\"error\", 6] */\n/* eslint no-trailing-spaces: warn */\n/* eslint-env es6*/\n\nimport {SimpleLine} from './simpleline/simpleline';\nimport {loadStrings} from './util/string-helper';\nimport {formatDate, formatDatetime, studyplanPageTiming, studyplanTiming} from './util/date-helper';\nimport {addBrowserButtonEvent} from './util/browserbuttonevents';\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, objCopy} from './studyplan-processor';\nimport TSComponents from './treestudyplan-components';\nimport FitTextVue from './util/fittext-vue';\n\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 Vue.use(FitTextVue);\n let debug = new Debugger(\"treestudyplan-viewer\");\n\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 = loadStrings({\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 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 noenddate: \"noenddate\",\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 noenddate: \"noenddate\",\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 unenrol: 'line_unenrol',\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 students: 'students@core',\n firstname: 'firstname@core',\n lastname: 'lastname@core',\n email: 'email@core',\n 'enrol_student_question': 'line_enrol_student_question',\n 'unenrol_student_question': 'line_unenrol_student_question',\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 /*\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() {\n return null;\n },\n },\n userid: {\n type: Number,\n default() {\n return 0;\n },\n },\n type: {\n type: String,\n default() {\n return \"own\";\n },\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 verifiedType() {\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\n mounted() {\n this.loadStudyplans();\n addBrowserButtonEvent(this.backPressed);\n },\n\n methods: {\n backPressed() {\n debug.log(\"Back button pressed\");\n if (this.selectedstudyplan) {\n debug.log(\"Closing studyplan\");\n this.deselectStudyplan();\n }\n },\n callArgs(o) {\n const args = {};\n if (typeof o == 'object' && !Array.isArray(o) && o !== null) {\n objCopy(args, o);\n }\n\n if (this.verifiedType == \"invited\") {\n args.invitekey = this.invitekey;\n } else if (this.verifiedType == \"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.verifiedType}_studyplans`,\n args: this.callArgs(),\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 let 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 // Load studyplan from hash if applicable\n const hash = window.location.hash.replace('#', '');\n const parts = hash.split(\"-\");\n\n if (!!parts && parts.length > 0) {\n for (const k in self.studyplans) {\n const list = self.studyplans[k];\n for (const idx in list) {\n const plan = list[idx];\n if (plan.id == parts[0] && !plan.suspended) {\n self.selectStudyplan(plan);\n return;\n }\n }\n }\n }\n\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.present.length > 0) {\n // Directly show the current study plan if it's the only current one\n const plan = self.studyplans.present[0];\n if (!plan.suspended) {\n self.selectStudyplan(plan);\n }\n } else if (self.studyplans.future.lengh > 0) {\n const plan = self.studyplans.future[0];\n if (!plan.suspended) {\n self.selectStudyplan(plan);\n }\n } else {\n const plan = self.studyplans.past[0];\n if (!plan.suspended) {\n self.selectStudyplan(plan);\n }\n }\n }\n return;\n }).catch(notification.exception);\n },\n selectStudyplan(plan) {\n const self = this;\n this.loadingstudyplan = true;\n call([{\n methodname: `local_treestudyplan_get_${this.verifiedType}_studyplan`,\n args: this.callArgs({\n studyplanid: plan.id,\n }),\n }])[0].then(function(response) {\n self.selectedstudyplan = processStudyplan(response);\n self.loadingstudyplan = false;\n window.location.hash = self.selectedstudyplan.id;\n return;\n }).catch(notification.exception);\n },\n deselectStudyplan() {\n this.selectedstudyplan = null;\n this.loadStudyplans(); // Reload the list of studyplans.\n window.location.hash = '';\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 coaching: {\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 formatDate(page.startdate, false) + \" - \" + formatDate(page.enddate, false);\n },\n columns(page) {\n return 1 + (page.periods * 2);\n },\n columnsStylerule(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)\"; // Ese 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 // 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) {\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(/* Params: newTabIndex, prevTabIndex */) {\n\n ItemEventBus.$emit('redrawLines', null);\n scrollCurrentIntoView(this.selectedpage.id);\n },\n },\n mounted() {\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 v-if=\"!page.timeless\">\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 && !coaching\" 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=\"columnsStylerule(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 && !coaching\"\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() {\n return {};\n },\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 canUnenrol: false,\n sorting: {\n asc: false,\n field: 'enrolled_time'\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 enrollableSelf() {\n return [ENROLLABLE_SELF, ENROLLABLE_SELF_ROLE].includes(this.value.enrol.enrollable);\n },\n enrollableRole() {\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 canEnrol() {\n return this.value.enrol.can_enrol ? true : false;\n },\n enrolQuestion() {\n return this.text.enrol_question.replace('{$a}', this.value.name);\n },\n enrolledIn() {\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 formatDatetime(this.value.enrol.enrolled_time);\n },\n sortedStudents() {\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 if (field == \"enrolled_time\") {\n const dvalue = (df[field] && d.enrol.enrolled) ? df[field] : 0;\n const evalue = (ef[field] && e.enrol.enrolled) ? ef[field] : 0;\n return dvalue - evalue;\n } else {\n return String(df[this.sorting.field]).localeCompare(String(ef[this.sorting.field]));\n }\n\n });\n return list;\n }\n },\n methods: {\n formatDatetime,\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 // Function 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 enrolSelf() {\n const self = this;\n call([{\n methodname: 'local_treestudyplan_line_enrol_self',\n args: {\n id: self.value.id,\n },\n }])[0].then(function(response) {\n self.$emit('enrolupdate', response);\n return;\n }).catch(notification.exception);\n },\n\n enrolStudent(student) {\n const self = this;\n const user = student.user;\n let question = self.text.enrol_student_question.replace('{$a}', `${user.firstname} ${user.lastname}`);\n const options = {\n okTitle: self.text.yes,\n cancelTitle: self.text.no,\n okVariant: \"success\",\n cancelVariant: \"danger\",\n };\n this.$bvModal.msgBoxConfirm(question, options).then(reply => {\n if (reply) {\n call([{\n methodname: 'local_treestudyplan_line_enrol_students',\n args: {\n id: self.value.id,\n users: [user.id],\n },\n }])[0].then(function(response) {\n student.enrol = response[0].enrol;\n return;\n }).catch(notification.exception);\n }\n return;\n }).catch(notification.exception);\n },\n unenrolStudent(student) {\n const self = this;\n const user = student.user;\n let question = self.text.unenrol_student_question.replace('{$a}', `${user.firstname} ${user.lastname}`);\n const options = {\n okTitle: self.text.yes,\n cancelTitle: self.text.no,\n okVariant: \"success\",\n cancelVariant: \"danger\",\n };\n this.$bvModal.msgBoxConfirm(question, options).then(reply => {\n if (reply) {\n call([{\n methodname: 'local_treestudyplan_line_unenrol_students',\n args: {\n id: self.value.id,\n users: [user.id],\n },\n }])[0].then(function(response) {\n student.enrol = response[0].enrol;\n return;\n }).catch(notification.exception);\n }\n return;\n }).catch(notification.exception);\n },\n loadStudents() {\n const self = this;\n self.students = null;\n self.canUnenrol = false;\n call([{\n methodname: 'local_treestudyplan_list_line_enrolled_students',\n args: {\n id: self.value.id,\n },\n }])[0].then(function(response) {\n self.students = response.userinfo;\n self.canUnenrol = response.can_unenrol;\n return;\n }).catch(notification.exception);\n },\n toggleSort(header) {\n if (this.sorting.field == header) {\n this.sorting.asc = !this.sorting.asc;\n } else {\n this.sorting.field = header;\n this.sorting.asc = true;\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=\"enrollable\">\n <template v-if=\"teachermode\">\n <br>\n <a v-if=\"!canEnrol\"\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 @show=\"loadStudents\"\n size=\"xl\"\n ok-only\n scrollable\n :title=\"value.name\"\n >\n <table class=\"r-line-enroll-userlist\">\n <thead>\n <th><a href='#' @click.prevent=\"toggleSort('firstname')\"\n >{{text.firstname}}</a>\n <i v-if=\"sorting.field=='firstname' && sorting.asc\" class='fa fa-sort-asc fa-fw'></i\n ><i v-else-if=\"sorting.field=='firstname' && !sorting.asc\" class='fa fa-sort-desc fa-fw'></i>\n </th>\n <th><a href='#' @click.prevent=\"toggleSort('lastname')\"\n >{{text.lastname}}</a>\n <i v-if=\"sorting.field=='lastname' && sorting.asc\" class='fa fa-sort-asc fa-fw'></i\n ><i v-else-if=\"sorting.field=='lastname' && !sorting.asc\" class='fa fa-sort-desc fa-fw'></i>\n </th>\n <th><a href='#' @click.prevent=\"toggleSort('enrolled')\"\n >{{text.enrolled}}</a>\n <i v-if=\"sorting.field=='enrolled' && sorting.asc\" class='fa fa-sort-asc fa-fw'></i\n ><i v-else-if=\"sorting.field=='enrolled' && !sorting.asc\" class='fa fa-sort-desc fa-fw'></i>\n </th>\n <th><a href='#' @click.prevent=\"toggleSort('enrolled_time')\"\n >{{text.since}}</a>\n <i v-if=\"sorting.field=='enrolled_time' && sorting.asc\" class='fa fa-sort-asc fa-fw'></i\n ><i v-else-if=\"sorting.field=='enrolled_time' && !sorting.asc\" class='fa fa-sort-desc fa-fw'></i>\n </th>\n <th><a href='#' @click.prevent=\"toggleSort('enrolled_by')\"\n >{{by}}</a>\n <i v-if=\"sorting.field=='enrolled_by' && sorting.asc\" class='fa fa-sort-asc fa-fw'></i\n ><i v-else-if=\"sorting.field=='enrolled_by' && !sorting.asc\" class='fa fa-sort-desc fa-fw'></i>\n </th>\n <th v-if=\"canEnrol || canUnenrol\">{{text.enrol}}</th>\n </thead>\n <tbody>\n <tr v-if=\"students == null\"><td\n :colspan=\"4+(canEnrol?1:0)\">\n <div class=\"spinner-border spinner-border-sm text-info\" role=\"status\"></div>\n </td></tr>\n <template v-else>\n <tr v-for=\"student in sortedStudents\">\n <td>{{student.user.firstname}}</td>\n <td>{{student.user.lastname}}</td>\n <td><span v-if=\"student.enrol.enrolled\" class=\"text-success\">{{text.enrolled}}</span\n ><span v-else class=\"text-danger\">{{text.notenrolled}}</span></td>\n <td><span v-if=\"student.enrol.enrolled\"\n >{{formatDatetime(student.enrol.enrolled_time)}}</span></td>\n <td><span v-if=\"student.enrol.enrolled\"\n >{{student.enrol.enrolled_by}}</span></td>\n <td ><b-button v-if=\"!student.enrol.enrolled && (canEnrol || canUnenrol)\"\n variant=\"success\"\n size=\"sm\"\n @click=\"enrolStudent(student)\"\n >{{text.enrol}}</b-button\n ><b-button v-else-if=\"student.enrol.enrolled && canUnenrol\"\n variant=\"danger\"\n size=\"sm\"\n @click=\"unenrolStudent(student)\"\n >{{text.unenrol}}</b-button>\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n </b-modal>\n </template>\n <template v-else-if=\"value.enrol.selfview\">\n <br>\n <a v-if=\"!enrolled && !canEnrol\"\n @click.prevent=\"\"\n href='#'\n v-b-tooltip.focus\n :title=\"text.cannot_enrol\"\n ><fittext maxsize=\"12pt\"><i class='fa fa-lock text-danger'></i>&nbsp;{{text.cannot_enrol}}</fittext></a>\n <a v-else-if=\"!enrolled && canEnrol\"\n @click.prevent=\"\"\n href='#'\n v-b-modal=\"'r-enrol-'+value.id\"\n :title=\"text.can_enrol\"\n ><fittext maxsize=\"12pt\"><i class='fa fa-unlock-alt text-info'></i>&nbsp;{{text.enrol}}</fittext></a>\n <a v-else-if=\"enrolled\"\n @click.prevent=\"\"\n href='#'\n v-b-modal=\"'r-enrollment-'+value.id\"\n :title=\"text.enrolled\"\n ><fittext maxsize=\"12pt\"><i class='fa fa-unlock text-success'></i>&nbsp;{{text.enrolled}}</fittext></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=\"enrolSelf\"\n >\n <p>{{enrolQuestion}}</p>\n </b-modal>\n <b-modal\n :id=\"'r-enrollment-'+value.id\"\n ok-only\n :title=\"text.enrollment\"\n >\n <p>{{enrolledIn}}<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 v-else>\n &nbsp;\n <i v-if=\"!enrolled\" class='fa fa-lock text-danger'></i>\n <i v-else class='fa fa-unlock text-success'></i>\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() {\n return [];\n },\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() {\n return null;\n },\n },\n layer: {\n type: Number,\n },\n plan: {\n type: Object,\n default() {\n return null;\n },\n },\n page: {\n type: Object,\n default() {\n return null;\n },\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() {\n return null;\n },\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 cloud() {\n const enrol = this.line.enrol;\n return (!this.teachermode) && (enrol.enrollable > 0) && (!enrol.enrolled);\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 + 'periodcount-' + page.periods + ' '\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 :cloud=\"cloud\"\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() {\n return null;\n },\n },\n plan: {\n type: Object,\n default() {\n return null;\n }\n },\n guestmode: {\n type: Boolean,\n 'default': false,\n },\n teachermode: {\n type: Boolean,\n 'default': false,\n },\n cloud: {\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 } else if (this.cloud) {\n return \"#ccc\";\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 'class': (this.cloud ? \"r-dummy-line\" : \"\"),\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 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 <template v-if=\"cloud\">\n <r-item-dummy-course v-if=\"value.type == 'course'\"></r-item-dummy-course>\n <r-item-dummy-badge v-else-if=\"value.type == 'badge'\"></r-item-dummy-badge>\n <r-item-dummy-filter v-else></r-item-dummy-filter>\n </template>\n <template v-else>\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 </template>\n </div>\n `,\n });\n\n Vue.component('r-item-invalid', {\n props: {\n 'value': {\n type: Object,\n default() {\n return null;\n },\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() {\n return null;\n },\n },\n guestmode: {\n type: Boolean,\n default() {\n return false;\n }\n },\n teachermode: {\n type: Boolean,\n default() {\n return false;\n }\n },\n plan: {\n type: Object,\n default() {\n return null;\n }\n }\n },\n data() {\n return {\n text: strings.course,\n };\n },\n computed: {\n startdate() {\n return formatDate(this.value.course.startdate);\n },\n enddate() {\n if (this.value.course.enddate > 0) {\n return formatDate(this.value.course.enddate);\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 methods: {\n completionIcon(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 circleIcon(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-course card completion-'+value.completion\">\n <div class='r-item-course-cardwrapper mr-0 ml-0 h-100 '>\n <div\n :title=\"text['coursetiming_'+value.course.timing]\"\n v-b-popover.hover.top=\"startdate+' - '+enddate\"\n :class=\"'r-timing-indicator timing-'+value.course.timing\"\n ></div>\n <div class=\"r-item-course-title card-body h-100\">\n <fittext maxsize=\"12pt\" minsize=\"9pt\">\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 }}</a>\n </fittext>\n </div>\n <div class=\"h-100 r-item-course-indicator \">\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='circleIcon(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-'+completionIcon(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-'+completionIcon(value.completion)+\n ' r-completion-'+value.completion\"\n :title=\"text['completion_'+value.completion]\"></i>\n </template>\n </div>\n </div>\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='circleIcon(value.completion)'\n :title=\"text['completion_'+value.completion]\"\n ></r-progress-circle>\n <i v-else v-b-popover.top\n :class=\"'fa fa-'+completionIcon(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-'+completionIcon(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 </div>\n `,\n });\n\n // Selected activities dispaly\n Vue.component('r-item-studentgrades', {\n props: {\n value: {\n type: Object,\n default() {\n return {};\n },\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 } else {\n return false;\n }\n },\n },\n methods: {\n completionIcon(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-'+completionIcon(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 @click.prevent.stop=\"\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+g.id\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-graduation-cap\"></i>{{ value.course.fullname }}</h3><br>\n <span class=\"r-activity-icon\" :title=\"g.typename\" v-html=\"g.icon + g.name\"></span>\n </div>\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() {\n return {};\n },\n },\n guestmode: {\n type: Boolean,\n 'default': false,\n },\n course: {\n type: Object,\n default() {\n return {};\n },\n },\n },\n data() {\n return {\n text: strings.completion,\n };\n },\n computed: {\n },\n methods: {\n completionIcon(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 completionTag(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-'+completionIcon(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 @click.prevent.stop=\"\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-grade-feedback-'+ci.id\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-graduation-cap\"></i>{{ course.fullname }}</h3>\n <span class=\"r-activity-icon\" :title=\"ci.typename\" v-html=\"ci.icon + ci.name\"></span>\n </div>\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() {\n return {};\n },\n },\n guestmode: {\n type: Boolean,\n 'default': false,\n },\n item: {\n type: Object,\n default() {\n return {id: null};\n },\n }\n },\n data() {\n return {\n text: strings.competency,\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 completionIcon(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 completionTag(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 ' + + completionTag(c)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td :colspan=\"(c.required)?1:2\">\n <span :class=\"'r-completion-'+completionTag(c)\">\n <template v-if=\"!c.progress && !c.count\">\n <i :class=\"'fa fa-'+completionIcon(c)\" :title=\"text['completion_'+completionTag(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-'+completionTag(c)\"\n :title=\"text['completion_'+completionTag(c)]\"\n ></r-progress-circle>\n <i v-else :class=\"'fa fa-'+completionIcon(c)\" :title=\"text['completion_'+completionTag(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 ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-puzzle-piece\"></i>{{ c.title }}</h3>\n </div>\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 ' + + completionTag(cc)\"\n ><i class='fa fa-asterisk' ></i\n ></abbr>\n </td>\n <td><span :class=\"'r-completion-'+completionTag(cc)\"\n ><i :class=\"'fa fa-'+completionIcon(cc)\" :title=\"text['completion_'+completionTag(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 @click.prevent.stop=\"\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+cc.id\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-puzzle-piece\"></i>{{ cc.title }}</h3><br>\n </div>\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() {\n return null;\n }\n },\n guestmode: {\n type: Boolean,\n default() {\n return false;\n }\n },\n teachermode: {\n type: Boolean,\n default() {\n return false;\n }\n },\n plan: {\n type: Object,\n default() {\n return null;\n }\n }\n },\n data() {\n return {\n text: strings.teachercourse,\n txt: {\n grading: strings.grading,\n }\n };\n },\n computed: {\n courseGradingNeeded() {\n return this.courseGradingState();\n },\n courseGradingIcon() {\n return this.determineGradingIcon(this.courseGradingState());\n },\n filteredGrades() {\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 } 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 progressCircle() {\n const status = {\n students: 0,\n completed: 0,\n completedPass: 0,\n completedFail: 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.completedPass += itm.progress.completed_pass;\n status.completedFail += 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.completedPass += g.grading.completed_pass;\n status.completedFail += g.grading.completed_fail;\n status.ungraded += g.grading.ungraded;\n }\n }\n }\n\n return status;\n },\n startdate() {\n return formatDate(this.value.course.startdate);\n },\n enddate() {\n if (this.value.course.enddate > 0) {\n return formatDate(this.value.course.enddate);\n } else {\n return this.text.noenddate;\n }\n },\n wwwroot() {\n return Config.wwwroot;\n }\n\n },\n methods: {\n courseGradingState() {\n let ungraded = 0;\n let unknown = 0;\n let graded = 0;\n let allgraded = 0;\n const grades = this.filteredGrades;\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 } 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 determineGradingIcon(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-course card '+ (value.course.amteacher?'r-course-am-teacher':'')\">\n <div class='r-item-course-cardwrapper mr-0 ml-0 h-100 '>\n <div\n :title=\"text['coursetiming_'+value.course.timing]\"\n v-b-popover.hover.top=\"startdate+' - '+enddate\"\n :class=\"'r-timing-indicator timing-'+value.course.timing\"\n ></div>\n <div class=\"r-item-course-title card-body h-100\">\n <fittext maxsize=\"12pt\" minsize=\"9pt\">\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 }}</a>\n </fittext>\n </div>\n <div class=\"h-100 r-item-course-indicator \">\n <r-completion-circle class=\"r-course-graded\" :disabled=\"!isCompletable\"\n v-model=\"progressCircle\"></r-completion-circle>\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=\"progressCircle\"></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() {\n return {};\n },\n },\n useRequiredGrades: {\n type: Boolean,\n default() {\n return null;\n }\n }\n },\n data() {\n return {\n text: strings.teachercourse,\n };\n },\n computed: {\n startdate() {\n return formatDate(this.value.course.startdate);\n },\n enddate() {\n if (this.value.course.enddate > 0) {\n return formatDate(this.value.course.enddate);\n } else {\n return this.text.noenddate;\n }\n },\n wwwroot() {\n return Config.wwwroot;\n }\n },\n methods: {\n includeChanged(newValue, g) {\n call([{\n methodname: 'local_treestudyplan_include_grade',\n args: {\n '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: {\n '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 {{ startdate }} - {{ enddate }}\n </div>\n </div>\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 // Selected activities dispaly\n Vue.component('r-item-teachergrades', {\n props: {\n value: {\n type: Object,\n default() {\n return {};\n },\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 filteredGrades() {\n return this.value.grades.filter(g => g.selected);\n },\n },\n methods: {\n determineGradingIcon(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 gradingIcon(grade) {\n return this.determineGradingIcon(this.isGradingNeeded(grade));\n },\n isGradingNeeded(grade) {\n if (grade.grading) {\n if (grade.grading.ungraded) {\n return 'ungraded';\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 } else {\n return 'graded';\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 filteredGrades\">\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 ' + isGradingNeeded(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-'+gradingIcon(g)+' r-graded-'+isGradingNeeded(g)\"\n :title=\"txt.grading[isGradingNeeded(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() {\n return {};\n },\n },\n guestmode: {\n type: Boolean,\n 'default': false,\n },\n course: {\n type: Object,\n default() {\n return {};\n },\n },\n },\n data() {\n return {\n text: strings.completion,\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 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() {\n return {};\n },\n },\n guestmode: {\n type: Boolean,\n 'default': false,\n },\n item: {\n type: Object,\n default() {\n return {id: null};\n },\n }\n },\n data() {\n return {\n text: strings.competency,\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 completionIcon(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 completionTag(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 ' + + completionTag(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\"></r-completion-bar></td>\n <td v-if=\"c.feedback\">\n <a v-b-modal=\"'r-competency-feedback-'+c.id\"\n href=\"#\"\n @click.prevent.stop=\"\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+c.id\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-puzzle-piece\"></i>{{ c.title }}</h3><br>\n </div>\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 ' + completionTag(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 @click.prevent.stop=\"\"\n >{{ text[\"view_feedback\"]}}</a>\n <b-modal\n :id=\"'r-competency-feedback-'+cc.id\"\n ok-only\n centered\n scrollable\n >\n <template #modal-header>\n <div>\n <h3><i class=\"fa fa-puzzle-piece\"></i>{{ cc.title }}</h3><br>\n </div>\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() {\n return {};\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.grading,\n };\n },\n computed: {\n widthUnsubmitted() {\n return this.width * this.fractionUnsubmitted();\n },\n widthGraded() {\n return this.width * this.fractionGraded();\n },\n widthUngraded() {\n return this.width * this.fractionUngraded();\n },\n countUnsubmitted() {\n return (this.value.students - this.value.graded - this.value.ungraded);\n }\n },\n methods: {\n fractionUnsubmitted() {\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 fractionGraded() {\n if (this.value.students > 0) {\n return this.value.graded / this.value.students;\n } else {\n return 0;\n }\n },\n fractionUngraded() {\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: widthUngraded+'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: widthGraded+'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: widthUnsubmitted+'px'}\"\n class='r-grading-bar-segment r-grading-bar-unsubmitted'\n :title=\"text.unsubmitted + ' (' + countUnsubmitted + ')'\" 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() {\n return {\n students: 0,\n completed: 0,\n 'completed_pass': 0,\n 'completed_fail': 0,\n ungraded: 0,\n };\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 widthIncomplete() {\n return this.width * this.fractionIncomplete();\n },\n widthCompleted() {\n return this.width * this.fractionCompleted();\n },\n widthCompletedPass() {\n return this.width * this.fractionCompletedPass();\n },\n widthCompletedFail() {\n return this.width * this.fractionCompletedFail();\n },\n widthUngraded() {\n return this.width * this.fractionUngraded();\n },\n countIncomplete() {\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 fractionIncomplete() {\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 fractionCompleted() {\n if (this.value.students > 0) {\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fractionCompletedPass() {\n if (this.value.students > 0) {\n return this.value.completed_pass / this.value.students;\n } else {\n return 0;\n }\n },\n fractionCompletedFail() {\n if (this.value.students > 0) {\n return this.value.completed_fail / this.value.students;\n } else {\n return 0;\n }\n },\n fractionUngraded() {\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: widthUngraded+'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: widthCompleted+'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: widthCompletedPass+'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: widthCompletedFail+'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: widthIncomplete+'px'}\"\n class='r-grading-bar-segment r-completion-bar-incomplete'\n :title=\"text.incomplete + ' (' + countIncomplete + ')'\" 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() {\n return {\n students: 10,\n completed: 2,\n completedPass: 2,\n completedFail: 2,\n ungraded: 2,\n };\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 completedPass() {\n if (this.value.completed_pass) {\n return this.value.completed_pass;\n } else {\n return this.value.completedPass;\n }\n },\n completedFail() {\n if (this.value.completed_fail) {\n return this.value.completed_fail;\n } else {\n return this.value.completedFail;\n }\n },\n radius() {\n return 50 - (50 * this.stroke);\n },\n\n arcpathUngraded() {\n const begin = 0;\n return this.arcpath(begin, this.fractionUngraded());\n },\n arcpathCompleted() {\n const begin = this.fractionUngraded();\n return this.arcpath(begin, this.fractionCompleted());\n },\n arcpathCompletedPass() {\n const begin = this.fractionUngraded()\n + this.fractionCompleted();\n return this.arcpath(begin, this.fractionCompletedPass());\n },\n arcpathCompletedFail() {\n const begin = this.fractionUngraded()\n + this.fractionCompleted()\n + this.fractionCompletedPass();\n return this.arcpath(begin, this.fractionCompletedFail());\n },\n arcpathIncomplete() {\n const begin = this.fractionUngraded()\n + this.fractionCompleted()\n + this.fractionCompletedPass()\n + this.fractionCompletedFail();\n return this.arcpath(begin, this.fractionIncomplete());\n },\n\n },\n methods: {\n arcpath(start, end) {\n const r = 50 - (50 * this.stroke);\n const t1 = start * 2 * π;\n const Δ = end * 2 * π;\n return svgarcpath([50, 50], [r, r], [t1, Δ], 1.5 * π);\n },\n fractionIncomplete() {\n if (this.value.students > 0) {\n return 1 - (\n (this.value.completed + this.completedPass +\n this.completedFail + this.value.ungraded) / this.value.students);\n } else {\n return 1;\n }\n },\n fractionCompleted() {\n if (this.value.students > 0) {\n return this.value.completed / this.value.students;\n } else {\n return 0;\n }\n },\n fractionCompletedPass() {\n if (this.value.students > 0) {\n return this.completedPass / this.value.students;\n } else {\n return 0;\n }\n },\n fractionCompletedFail() {\n if (this.value.students > 0) {\n return this.completedFail / this.value.students;\n } else {\n return 0;\n }\n },\n fractionUngraded() {\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=\"arcpathUngraded\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--warning); fill: none;'\"/>\n <path :d=\"arcpathCompleted\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--info); fill: none;'\"/>\n <path :d=\"arcpathCompletedPass\"\n :style=\"'stroke-width: ' + (stroke*100) +'; stroke: var(--success); fill: none;'\"/>\n <path :d=\"arcpathCompletedFail\"\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() {\n return {};\n },\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() {\n return {};\n },\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() {\n return {};\n },\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-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() {\n return {};\n },\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 issuedIcon() {\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 arcpathIssued() {\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 arcpathProgress() {\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 (\n this.value.badge.issued || this.teachermode ||\n (\n this.value.badge.completion\n && this.value.badge.completion.progress >= this.value.badge.completion.count\n )\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 completionIconRq(complete) {\n if (complete) {\n return \"check-square-o\";\n } else {\n return \"square-o\";\n }\n },\n completionIcon(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=\"arcpathIssued\"\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=\"arcpathProgress\"\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-'+issuedIcon+' 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-'+completionIcon(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-'+completionIconRq(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 Vue.component('r-item-dummy-course', {\n props: {\n value: {\n type: Object,\n default() {\n return null;\n },\n },\n },\n data() {\n return {\n text: strings.invalid,\n };\n },\n methods: {\n },\n template: `\n <div class=\"r-item-dummy-course\">\n <b-card no-body class=\"r-item-course\">\n <b-row no-gutters>\n <b-col md=\"1\">\n <span class=\"r-timing-indicator timing-dummy\"></span>\n </b-col>\n <b-col md=\"11\">\n <b-card-body class=\"align-items-center\">\n \n </b-card-body>\n </b-col>\n </b-row>\n </b-card>\n </div>\n `,\n });\n\n Vue.component('r-item-dummy-filter', {\n props: {\n },\n data() {\n return {};\n },\n computed: {\n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-dummy-filter'\">\n <i class=\"fa fa-circle\"></i>\n </div>\n `,\n });\n\n Vue.component('r-item-dummy-badge', {\n props: {\n },\n data() {\n return {};\n },\n computed: {\n },\n methods: {\n },\n template: `\n <div :class=\"'r-item-dummy-badge'\" >\n <i class=\"fa fa-circle\"></i>\n </div>\n `,\n });\n },\n};"],"names":["π","Math","PI","ENROLLABLE_SELF","ENROLLABLE_ROLE","ENROLLABLE_SELF_ROLE","install","Vue","use","TSComponents","FitTextVue","debug","Debugger","lastCaller","scrollCurrentIntoView","handle","elCurrentHeader","document","querySelector","scrollIntoView","behavior","block","inline","strings","report","loading","back","invalid","error","grading","ungraded","graded","allgraded","unsubmitted","nogrades","unknown","completion","completed","incomplete","badge","dateissued","dateexpire","badgeinfo","badgeissuedstats","badgedisabled","course","noenddate","teachercourse","competency","when","required","points","heading","details","results","unrated","progress","pageinfo","edit","fullname","shortname","startdate","enddate","description","duration","overview","oveviewperiod","lineheader","enrol","unenrol","enrolled","notenrolled","enrollments","enrollment","info","confirm","yes","no","since","byname","students","firstname","lastname","email","isVisible","elem","offsetWidth","offsetHeight","getClientRects","length","ItemEventBus","component","props","value","type","Number","max","min","stroke","bgopacity","title","String","icon","data","selectedstudyplan","computed","range","this","fraction","radius","arcpath","r","Δ","methods","template","invitekey","default","userid","text","studyplans","past","present","future","loadingstudyplan","teachermode","guestmode","verifiedType","includes","studyplancount","mounted","loadStudyplans","backPressed","log","deselectStudyplan","callArgs","o","args","Array","isArray","self","methodname","then","response","console","plans","ix","plan","push","sort","a","b","t","Date","getTime","name","localeCompare","parts","window","location","hash","replace","split","k","list","idx","id","suspended","selectStudyplan","lengh","catch","notification","exception","studyplanid","Object","Boolean","coaching","selectedpageindex","selectedpage","pages","startpageindex","firststart","page","s","wwwroot","Config","pageduration","columns","periods","columnsStylerule","i","countLineLayers","line","maxLayer","slots","courses","item","layer","filters","showslot","index","layeridx","forGradable","show","span","selectedpageChanged","$emit","$root","updated","layers","studentid","layerHeights","canUnenrol","sorting","asc","field","created","$on","onLineHeightChange","enrollable","enrollableSelf","enrollableRole","canEnrol","can_enrol","enrolQuestion","enrol_question","enrolledIn","enrolled_in","by","enrolldate","enrolled_time","sortedStudents","d","e","df","ef","user","hasOwnProperty","formatDatetime","lineid","$refs","mainEl","items","querySelectorAll","heightSum","forEach","el","height","getBoundingClientRect","heightStyle","style","enrolSelf","enrolStudent","student","question","enrol_student_question","options","okTitle","cancelTitle","okVariant","cancelVariant","$bvModal","msgBoxConfirm","reply","users","unenrolStudent","unenrol_student_question","loadStudents","userinfo","can_unenrol","toggleSort","header","slotindex","period","resizeListener","ResizeObserver","sizeElement","observe","itm","spanCss","cloud","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","addEventListener","beforeDestroy","removeEventListener","$off","dummy","courseprogress","count","grades","gradeprogress","hasprogressinfo","completionIcon","circleIcon","g","pendingsubmission","result","useRequiredGrades","aggregation_info","completionTag","cgroup","hasCompletions","conditions","requirementHTML","requirements","rqs","html","addTargetBlank","m","exec","proficient","courseproficient","pathtags","path","p","url","competencyurl","c","usercompetencyurl","ucid","txt","courseGradingNeeded","courseGradingState","courseGradingIcon","determineGradingIcon","filteredGrades","filter","selected","isCompletable","completable","progressCircle","status","completedPass","completedFail","cond","completed_pass","completed_fail","total","grade","gradingstate","includeChanged","newValue","requiredChanged","gradingIcon","isGradingNeeded","completionreport","width","widthUnsubmitted","fractionUnsubmitted","widthGraded","fractionGraded","widthUngraded","fractionUngraded","countUnsubmitted","widthIncomplete","fractionIncomplete","widthCompleted","fractionCompleted","widthCompletedPass","fractionCompletedPass","widthCompletedFail","fractionCompletedFail","countIncomplete","disabled","arcpathUngraded","arcpathCompleted","begin","arcpathCompletedPass","arcpathCompletedFail","arcpathIncomplete","t1","issued","issuedIcon","issuestats","studentcount","issuedcount","arcpathIssued","arcpathProgress","badgeinprogress","completionIconRq","complete"],"mappings":"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"}