/*eslint no-var: "error"*/ /*eslint no-console: "off"*/ /*eslint-disable no-trailing-spaces */ /*eslint-env es6*/ // Put this file in path/to/plugin/amd/src import {load_strings} from './util/string-helper'; import {format_date, studyplanDates, studyplanTiming} from './util/date-helper'; import FitTextVue from './util/fittext-vue'; export default { install(Vue/*,options*/){ Vue.use(FitTextVue); let strings = load_strings({ studyplancard: { open: "open", noenddate: "noenddate", idnumber: "studyplan_idnumber", description: "studyplan_description", completed: "completed", details: "studyplan_details", suspended: "suspended", }, details: { details: "studyplan_details", }, extrafields: { show: "show@core" }, prevnext: { prev: "prev@core", previous: "previous@core", next: "next@core", select: "selectanoptions@core", } }); // Create new eventbus for interaction between item components const ItemEventBus = new Vue(); Vue.component('s-studyplan-card', { props: { value: { type: Object, }, open: { type: Boolean }, ignoresuspend: { type: Boolean, default: false, }, }, data() { return { text: strings.studyplancard }; }, computed: { timeless() { const plan = this.value; if (!plan.pages || plan.pages.length == 0 || plan.pages[0].timeless) { return true; } else { return false; } }, timing(){ return studyplanTiming(this.value); }, dates(){ const dates = studyplanDates(this.value); return { start: format_date(dates.start), end: (dates.end)?format_date(dates.end):this.text.noenddate, }; }, suspended() { return (this.value.suspended && !this.ignoresuspend); } }, methods: { onOpenClick(e) { this.$emit('open',e); } }, template: `
{{value.name}}
{{text.suspended}}
{{ text.idnumber }}: {{ value.idnumber }}
`, }); Vue.component('s-progress-bar', { props: { value: { type: Number, }, min: { type: Number, default() { return 0;} }, max: { type: Number, default() { return 1;} } }, data() { return { text: strings.studyplancard }; }, computed: { width_completed() { if(this.value) { const v = ( (this.value - this.min) / (this.max - this.min)); return v * 100; } else { return 0; } }, width_incomplete() { if(this.value) { const v = ( (this.value - this.min) / (this.max - this.min)); return (1-v) * 100; } else { return 100; } }, percentage_complete() { if(this.value) { const v = ( (this.value - this.min) / (this.max - this.min)); return Math.round(v * 100) + "%"; } else { return "0%"; } } }, template: `
{{ percentage_complete}} {{ text.completed.toLowerCase() }}
`, }); /* * S-STUDYLINE-HEADER-HEADING * The only reasing this is not a simple empty div, is the fact that the header height * needs to match that of the period headers */ Vue.component('s-studyline-header-heading', { props: { identifier: { type: Number, // Page reference. default() { return 0;} } }, data() { return { layerHeights: {} }; }, created() { // Listener for the signal that a new connection was made and needs to be drawn // Sent by the incoming item - By convention, outgoing items are responsible for drawing the lines ItemEventBus.$on('headerHeightChange', this.onHeaderHeightChange); }, computed: { }, methods: { onHeaderHeightChange(newheight,identifier){ if (this.identifier == identifier) { if(this.$refs.main){ this.$refs.main.style.height = `${newheight}px`; } } } }, template: `
`, }); Vue.component('s-studyline-header-period', { props: { value: { type: Object, // dict with layer as index }, identifier: { type: Number, // Page reference. default() { return 0;} } }, mounted() { const self=this; if(self.value.period == 1){ self.resizeListener = new ResizeObserver(() => { if(self.$refs.main){ const size = self.$refs.main.getBoundingClientRect(); ItemEventBus.$emit('headerHeightChange', size.height, self.identifier); } }).observe(self.$refs.main); } }, unmounted() { if(this.resizeListener) { this.resizeListener.disconnect(); } }, computed: { startdate(){ return format_date(this.value.startdate); }, enddate(){ return format_date(this.value.enddate); }, current(){ if( this.value && this.value.startdate && this.value.enddate){ const now = new Date(); const pstart = new Date(this.value.startdate); const pend = new Date(this.value.enddate); return (now >= pstart && now < pend); } else { return false; } } }, data() { return { }; }, template: `

{{ value.shortname }} {{ value.fullname }}
{{ startdate }} - {{ enddate }}

{{ startdate }} - {{ enddate }}

`, }); Vue.component('s-studyplan-details', { props: { value: { type: Object, }, variant: { type: String, default() { return "info"; } }, pill: { type: Boolean, default() { return false; } }, size: { type: String, default() { return "";} } }, data() { return { text: strings.details, }; }, template: ` {{ text.details}} `, }); Vue.component('s-course-extrafields', { props: { value: { type: Array, }, variant: { type: String, default() { return "info"; } }, position: { type: String, default() { return "below"; } }, size: { type: String, default() { return "";} } }, data() { return { text: strings.extrafields, }; }, computed: { fields() { const fields = []; for (const ix in this.value) { const field = this.value[ix]; if (field.position == this.position && field.value && field.value.length > 0) { fields.push(field); } } return fields; }, }, methods: { displaydate(field) { return format_date(field.value,false); }, }, template: `
{{ field.title}} {{ displaydate(field) }} {{ field.value }} {{text.show}}...
`, }); Vue.component('s-prevnext-selector', { props: { value: { type: Object, default() { return null;} }, options: { type: Array, }, grouped: { type: Boolean, default: false, }, titlefield: { type: String, default: "title", }, labelfield: { type: String, default: "label", }, optionsfield: { type: String, default: "options", }, defaultselectable: { type: Boolean, default: false, }, variant: { type: String, default: "", }, arrows: { type: Boolean, default: false, }, }, data() { return { text: strings.prevnext, }; }, computed: { fields() { const f = []; if(this.defaultselectable) { f.push(null); } if (this.grouped) { for ( const gix in this.options) { const group = this.options[gix]; for ( const ix in group[this.optionsfield]) { const v = group[this.optionsfield][ix]; f.push(v); } } } else { for ( const ix in this.options) { const v = this.options[ix]; f.push(v); } } return f; }, bubblevalue: { get() { return (this.value)?this.value:null;}, set(v) { this.$emit('input',(v)?v:null);}, } }, methods: { atFirst() { if (this.fields.length > 0) { return this.fields[0] == this.value; } return true; // Since it disables the button, do so if pressing it would make no sense. }, atLast() { if (this.fields.length > 0) { const l = this.fields.length -1; return this.fields[l] == this.value; } return true; // Since it disables the button, do so if pressing it would make no sense. }, prev() { if (this.fields.length > 0) { const index = this.fields.indexOf(this.value); if (index > 0) { this.$emit("input",this.fields[index -1]); this.$emit("change",this.fields[index -1]); } } }, next() { if (this.fields.length > 0) { const index = this.fields.indexOf(this.value); const l = this.fields.length -1; if (index >= 0 && index < l) { this.$emit("input",this.fields[index + 1]); this.$emit("change",this.fields[index + 1]); } } }, selectedchanged(value) { this.$emit("change",value); } }, template: `
{{text.select}}
`, }); } };