/* eslint no-var: "error" */ /* eslint no-unused-vars: "off" */ /* eslint linebreak-style: "off" */ /* eslint no-trailing-spaces: "off" */ /* eslint no-empty-function: "off" */ /* eslint-env es6*/ // Put this file in path/to/plugin/amd/src // You can call it anything you like import {call} from 'core/ajax'; import notification from 'core/notification'; // Commented out: import {resetAllFormDirtyStates} from 'core_form/changechecker'; // Moodle 4.00+ only import Vue from './vue/vue'; import EditorComponents from './studyplan-editor-components'; Vue.use(EditorComponents); import TSComponents from './treestudyplan-components'; Vue.use(TSComponents); import ModalComponents from './modedit-modal'; Vue.use(ModalComponents); import Debugger from './util/debugger'; import {addBrowserButtonEvent} from './util/browserbuttonevents'; import {loadStrings} from './util/string-helper'; import {processStudyplan} from './studyplan-processor'; import {download, upload} from './downloader'; import {studyplanTiming} from './util/date-helper'; import mFormComponents from "./util/mform-helper"; Vue.use(mFormComponents); import PortalVue from './portal-vue/portal-vue.esm'; Vue.use(PortalVue); import BootstrapVue from './bootstrap-vue/bootstrap-vue'; Vue.use(BootstrapVue); const debug = new Debugger("treestudyplan"); let resetAllFormDirtyStates = () => { }; import('core_form/changechecker').then((ns) => { debug.info(ns); if (ns.resetAllFormDirtyStates) { resetAllFormDirtyStates = ns.resetAllFormDirtyStates; } return; }).catch(()=>{}); let strings = loadStrings({ studyplan: { 'studyplan_select_placeholder': 'studyplan_select_placeholder', 'advanced_import_from_file': 'advanced_import_from_file', 'advanced_create_from_template': 'advanced_create_from_template', 'studyplan_add': "studyplan_add", }, }); /** * Initialize the Page * @param {int} contextid The context we should attempt to work in (1:1 related to the category) * @param {int} categoryid The category we shoud attempt to work in (1:1 related to the context) * @param {object} options Options to be passed to this script */ export function init(contextid, categoryid, options) { // Make sure the id's are numeric and integer if (undefined === contextid || !Number.isInteger(Number(contextid)) || contextid < 1) { contextid = 1; } else { contextid = Number(contextid); // Ensure a numeric value instead of string } if (undefined === categoryid || !Number.isInteger(Number(categoryid))) { categoryid = 0; } else { categoryid = Number(categoryid); // Ensure a numeric value instead of string } debug.info("options", options); if (options !== null && typeof options === 'object' && !Array.isArray(options)) { if (!options.defaultAggregation) { options.defaultAggregation = "core"; } } else { options = {defaultAggregation: "core"}; } // Setup the initial Vue app for this page let app = new Vue({ el: '#root', data: { create: { studyplan: { name: '', shortname: '', description: '', idnumber: '', slots: 4, startdate: '2020-08-01', enddate: '', context: contextid, aggregation: options.defaultAggregation, 'aggregation_config': '', } }, activestudyplan: null, activepage: null, loadingstudyplan: false, studyplans: [], templatecount: 0, text: strings.studyplan, usedcontexts: [], }, created() { this.$root.$on('studyplanRemoved', (studyplan)=>{ if (app.activestudyplan == studyplan) { app.activestudyplan = null; } // Remove studyplan from index list let index = null; for (let idx in app.studyplans) { if (app.studyplans[idx].id == studyplan.id) { index = idx; break; } } if (index) { app.studyplans.splice(index, 1); } }); }, mounted() { this.initialize(); addBrowserButtonEvent(this.backPressed); }, beforeunmount() { }, computed: { dropdownTitle() { if (this.activestudyplan && this.activestudyplan.name) { return this.activestudyplan.name; } else { return this.text.studyplan_select_placeholder; } }, contextid() { return contextid; }, }, methods: { backPressed() { debug.log("Back button pressed"); if (app.activestudyplan) { debug.log("Closing studyplan"); this.closeStudyplan(); } }, initialize() { call([{ methodname: 'local_treestudyplan_list_studyplans', args: {'context_id': contextid} }])[0].then(function(response) { const timingval = {future: 0, present: 1, past: 2}; response.sort((a, b) => { const timinga = studyplanTiming(a); const timingb = studyplanTiming(b); let t = timingval[timinga] - timingval[timingb]; if (t == 0) { // Sort by start date if timing is equal t = new Date(b.startdate).getTime() - new Date(a.startdate).getTime(); if (t == 0) { // Sort by name if timing is equal t = a.name.localeCompare(b.name); } } return t; }); app.studyplans = response; // Load studyplan from hash if applicable const hash = location.hash.replace('#', ''); if (hash) { const id = hash; for (const p of app.studyplans) { if (p.id == id) { app.selectStudyplan(id); break; } } } return; }).catch(notification.exception); call([{ methodname: 'local_treestudyplan_list_available_categories', args: {operation: 'edit', 'refcontext_id': contextid} }])[0].then(function(response) { app.usedcontexts = response; return; }).catch(notification.exception); this.refreshTemplateCount(); }, refreshTemplateCount() { call([{ methodname: 'local_treestudyplan_count_templates', args: { } }])[0].then(function(response) { app.templatecount = response; return; }).catch(notification.exception); }, closeStudyplan() { app.activestudyplan = null; window.location.hash = ''; }, movedStudyplan(plan, from, to) { // Reload the page in the new context (needed, since a number of links are not reactive in the page) const params = new URLSearchParams(location.search); params.delete('categoryid'); params.set("contextid", to); setTimeout(() => { // Reload page in a timeout to give other form javasccript the change to remove the beforeunload handler. window.location.search = params.toString(); }, 50); }, onStudyPlanCreated(newstudyplan) { if (newstudyplan.context_id != contextid) { // Study plan has changed context id - reload page into new context id and show the plan const params = new URLSearchParams(location.search); params.delete('categoryid'); params.set("contextid", newstudyplan.context_id); // Make sure the form is no longer dirty before reloading the page - avoid beforeunload handler triggering. resetAllFormDirtyStates(); window.location = window.location.pathname + "?" + params.toString() + "#" + newstudyplan.id; } else { app.studyplans.push(newstudyplan); app.selectStudyplan(newstudyplan.id); } }, switchContext(ctxid) { const params = new URLSearchParams(location.search); params.delete('categoryid'); params.set('contextid', ctxid); setTimeout(() => { // Reload page in a timeout to give other form javasccript the change to remove the beforeunload handler. window.location.href = window.location.pathname + "?" + params.toString(); }, 50); }, selectStudyplan(studyplanid) { // Fetch studyplan app.loadingstudyplan = true; app.activestudyplan = null; call([{ methodname: 'local_treestudyplan_get_studyplan_map', args: {id: studyplanid} }])[0].then(function(response) { app.activestudyplan = processStudyplan(response); debug.info('studyplan processed'); app.loadingstudyplan = false; window.location.hash = app.activestudyplan.id; return; }).catch(function(error) { notification.exception(error); app.loadingstudyplan = false; }); }, importStudyplan() { const self = this; upload((filename, content)=>{ call([{ methodname: 'local_treestudyplan_import_plan', args: { content: content, format: "application/json", 'context_id': contextid, }, }])[0].then(function(response) { if (response.success) { self.initialize(); } else { debug.error("Import failed: ", response.msg); } return; }).catch(notification.exception); }, "application/json"); }, }, }); }