This repository has been archived on 2025-01-01. You can view files and clone it, but cannot push or open issues or pull requests.
moodle-local_treestudyplan/amd/src/page-edit-plan.js

302 lines
11 KiB
JavaScript

/* 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");
},
},
});
}