2023-05-17 21:19:14 +02:00
|
|
|
/*eslint no-var: "error" */
|
|
|
|
/*eslint no-unused-vars: "off" */
|
|
|
|
/*eslint linebreak-style: "off" */
|
|
|
|
/*eslint no-trailing-spaces: "off" */
|
|
|
|
/*eslint-env es6*/
|
|
|
|
// Put this file in path/to/plugin/amd/src
|
|
|
|
// You can call it anything you like
|
|
|
|
|
|
|
|
import {get_string,get_strings} from 'core/str';
|
|
|
|
import {call} from 'core/ajax';
|
|
|
|
import notification from 'core/notification';
|
2023-08-19 17:54:40 +02:00
|
|
|
|
2023-08-22 23:12:33 +02:00
|
|
|
import Vue from './vue/vue';
|
|
|
|
|
2023-08-19 17:54:40 +02:00
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
import EditorComponents from './studyplan-editor-components';
|
2023-08-19 17:54:40 +02:00
|
|
|
Vue.use(EditorComponents);
|
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
import TSComponents from './treestudyplan-components';
|
2023-08-19 17:54:40 +02:00
|
|
|
Vue.use(TSComponents);
|
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
import ModalComponents from './modedit-modal';
|
2023-08-19 17:54:40 +02:00
|
|
|
Vue.use(ModalComponents);
|
|
|
|
import Debugger from './util/debugger';
|
2023-05-17 21:19:14 +02:00
|
|
|
|
2023-08-19 17:54:40 +02:00
|
|
|
import {load_strings} from './util/string-helper';
|
2023-07-18 13:19:48 +02:00
|
|
|
import {ProcessStudyplan} from './studyplan-processor';
|
2023-05-17 21:19:14 +02:00
|
|
|
import {download,upload} from './downloader';
|
2023-11-23 07:44:04 +01:00
|
|
|
import {studyplanTiming} from './util/date-helper';
|
2023-05-17 21:19:14 +02:00
|
|
|
|
2023-08-19 17:54:40 +02:00
|
|
|
import PortalVue from './portal-vue/portal-vue.esm';
|
2023-05-17 21:19:14 +02:00
|
|
|
Vue.use(PortalVue);
|
2023-08-31 07:40:55 +02:00
|
|
|
import BootstrapVue from './bootstrap-vue/bootstrap-vue';
|
2023-05-17 21:19:14 +02:00
|
|
|
Vue.use(BootstrapVue);
|
2023-08-19 17:54:40 +02:00
|
|
|
|
2023-08-23 23:03:53 +02:00
|
|
|
import {Drag, Drop, DropList} from './vue-easy-dnd/vue-easy-dnd.esm';
|
2023-05-17 21:19:14 +02:00
|
|
|
Vue.component('drag',Drag);
|
|
|
|
Vue.component('drop',Drop);
|
|
|
|
Vue.component('drop-list',DropList);
|
|
|
|
|
|
|
|
const debug = new Debugger("treestudyplan");
|
|
|
|
|
|
|
|
let strings = load_strings({
|
|
|
|
studyplan: {
|
|
|
|
studyplan_select_placeholder: 'studyplan_select_placeholder',
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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)
|
2023-09-09 21:06:11 +02:00
|
|
|
* @param {object} options Options to be passed to this script
|
2023-05-17 21:19:14 +02:00
|
|
|
*/
|
2023-09-09 21:06:11 +02:00
|
|
|
export function init(contextid,categoryid,options) {
|
2023-05-17 21:19:14 +02:00
|
|
|
// Make sure the id's are numeric and integer
|
2023-09-08 12:47:29 +02:00
|
|
|
if(undefined === contextid || !Number.isInteger(Number(contextid)) || contextid < 1 ){ contextid = 1;}
|
2023-08-17 23:29:32 +02:00
|
|
|
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
|
2023-05-17 21:19:14 +02:00
|
|
|
|
2023-09-09 21:06:11 +02:00
|
|
|
debug.info("options",options);
|
|
|
|
if ( options !== null && typeof options === 'object' && !Array.isArray(options) ) {
|
|
|
|
if ( !options.defaultAggregation ) {
|
|
|
|
options.defaultAggregation = "core";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
options = { defaultAggregation: "core"};
|
|
|
|
}
|
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
const in_systemcontext = (contextid <= 1);
|
|
|
|
|
|
|
|
// Setup the initial Vue app for this page
|
|
|
|
let app = new Vue({
|
|
|
|
el: '#root',
|
|
|
|
data: {
|
|
|
|
create: {
|
|
|
|
studyplan: {
|
|
|
|
name: '',
|
|
|
|
shortname: '',
|
|
|
|
description: '',
|
2023-08-09 09:48:06 +02:00
|
|
|
idnumber: '',
|
2023-05-17 21:19:14 +02:00
|
|
|
slots : 4,
|
|
|
|
startdate: '2020-08-01',
|
|
|
|
enddate: '',
|
2023-08-07 17:03:49 +02:00
|
|
|
context: contextid,
|
2023-09-09 21:06:11 +02:00
|
|
|
aggregation: options.defaultAggregation,
|
2023-05-17 21:19:14 +02:00
|
|
|
aggregation_config: '',
|
|
|
|
}
|
|
|
|
},
|
|
|
|
toolbox: {
|
2023-09-03 20:57:14 +02:00
|
|
|
shown: false,
|
2023-05-17 21:19:14 +02:00
|
|
|
right: true,
|
|
|
|
},
|
|
|
|
activestudyplan: null,
|
|
|
|
loadingstudyplan: false,
|
|
|
|
studyplans: [],
|
|
|
|
frameworks: [],
|
|
|
|
badges: [],
|
|
|
|
courses: [],
|
|
|
|
text: strings.studyplan,
|
|
|
|
usedcontexts: [],
|
|
|
|
},
|
|
|
|
created() {
|
|
|
|
this.$root.$on('studyplanRemoved',(studyplan)=>{
|
2023-09-08 12:47:29 +02:00
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
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() {
|
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_list_studyplans',
|
|
|
|
args: { context_id: contextid}
|
|
|
|
}])[0].done(function(response){
|
|
|
|
const timingval = { future: 0, present: 1, past: 2, };
|
|
|
|
response.sort((a,b) => {
|
2023-11-23 07:44:04 +01:00
|
|
|
const timinga = studyplanTiming(a);
|
|
|
|
const timingb = studyplanTiming(b);
|
2023-05-17 21:19:14 +02:00
|
|
|
|
|
|
|
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();
|
2023-09-08 12:47:29 +02:00
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
if (t == 0) {
|
|
|
|
// sort by name if timing is equal
|
|
|
|
t = a.name.localeCompare(b.name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return t;
|
2023-09-08 12:47:29 +02:00
|
|
|
});
|
2023-05-17 21:19:14 +02:00
|
|
|
app.studyplans = response;
|
|
|
|
|
|
|
|
// load studyplan from hash if applicable
|
|
|
|
const hash = location.hash.replace('#','');
|
|
|
|
if(hash){
|
|
|
|
for(let idx in app.studyplans){
|
|
|
|
if(app.studyplans[idx].id == hash){
|
|
|
|
app.selectStudyplan(app.studyplans[idx]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).fail(notification.exception);
|
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_list_badges',
|
|
|
|
args: {}
|
|
|
|
}])[0].done(function(response){
|
|
|
|
app.badges = response;
|
2023-09-08 12:47:29 +02:00
|
|
|
}).fail(notification.exception);
|
2023-05-17 21:19:14 +02:00
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_map_categories',
|
|
|
|
args: {root_id: categoryid}
|
|
|
|
}])[0].done(function(response){
|
|
|
|
app.courses = response;
|
2023-09-08 12:47:29 +02:00
|
|
|
}).fail(notification.exception);
|
2023-05-17 21:19:14 +02:00
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_list_used_categories',
|
|
|
|
args: { operation: 'edit'}
|
|
|
|
}])[0].done(function(response){
|
|
|
|
app.usedcontexts = response;
|
2023-09-08 12:47:29 +02:00
|
|
|
}).fail(notification.exception);
|
2023-05-17 21:19:14 +02:00
|
|
|
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
dropdown_title(){
|
|
|
|
if(this.activestudyplan && this.activestudyplan.name){
|
|
|
|
return this.activestudyplan.name;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
return this.text.studyplan_select_placeholder;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
contextid(){
|
|
|
|
return contextid;
|
2023-08-04 11:54:16 +02:00
|
|
|
},
|
|
|
|
filterComponentType(){
|
|
|
|
return {
|
2023-08-15 15:34:53 +02:00
|
|
|
item: false,
|
|
|
|
component: true,
|
2023-08-04 11:54:16 +02:00
|
|
|
span: 1,
|
|
|
|
type: 'filter',
|
|
|
|
};
|
|
|
|
},
|
2023-05-17 21:19:14 +02:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
closeStudyplan() {
|
|
|
|
app.activestudyplan = null;
|
2023-09-03 17:12:44 +02:00
|
|
|
window.location.hash = '';
|
2023-09-08 12:47:29 +02:00
|
|
|
},
|
2023-05-17 21:19:14 +02:00
|
|
|
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);
|
|
|
|
window.location.search = params.toString();
|
|
|
|
},
|
|
|
|
onStudyPlanCreated(newstudyplan){
|
|
|
|
app.studyplans.push(newstudyplan);
|
|
|
|
app.selectStudyplan(newstudyplan);
|
|
|
|
|
|
|
|
},
|
|
|
|
switchContext(ctx){
|
|
|
|
const params = new URLSearchParams(location.search);
|
|
|
|
params.set('categoryid', ctx.id);
|
|
|
|
window.location.search = params.toString();
|
2023-09-08 12:47:29 +02:00
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
},
|
|
|
|
selectStudyplan(studyplan){
|
|
|
|
// fetch studyplan
|
|
|
|
app.loadingstudyplan = true;
|
|
|
|
app.activestudyplan = null;
|
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_get_studyplan_map',
|
|
|
|
args: { id: studyplan.id}
|
|
|
|
}])[0].done(function(response){
|
2023-11-05 15:49:32 +01:00
|
|
|
app.activestudyplan = ProcessStudyplan(response);
|
2023-05-17 21:19:14 +02:00
|
|
|
debug.info('studyplan processed');
|
|
|
|
app.loadingstudyplan = false;
|
2023-09-03 17:12:44 +02:00
|
|
|
window.location.hash = app.activestudyplan.id;
|
2023-05-17 21:19:14 +02:00
|
|
|
}).fail(function(error){
|
|
|
|
notification.exception(error);
|
|
|
|
app.loadingstudyplan = false;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
import_studyplan(){
|
|
|
|
upload((filename,content)=>{
|
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_import_plan',
|
|
|
|
args: {
|
|
|
|
content: content,
|
|
|
|
format: "application/json",
|
2023-05-19 16:45:15 +02:00
|
|
|
context_id: contextid,
|
2023-05-17 21:19:14 +02:00
|
|
|
},
|
|
|
|
}])[0].done(function(response){
|
|
|
|
if(response.success){
|
|
|
|
location.reload();
|
|
|
|
} else {
|
|
|
|
debug.error("Import failed: ",response.msg);
|
|
|
|
}
|
2023-09-08 12:47:29 +02:00
|
|
|
|
|
|
|
}).fail(notification.exception);
|
2023-05-17 21:19:14 +02:00
|
|
|
}, "application/json");
|
|
|
|
},
|
|
|
|
export_plan(plan,format){
|
|
|
|
let self = this;
|
|
|
|
if(format == undefined || !["json","csv"].includes(format)){
|
|
|
|
format = "json";
|
|
|
|
}
|
|
|
|
call([{
|
|
|
|
methodname: 'local_treestudyplan_export_plan',
|
|
|
|
args: {
|
|
|
|
studyplan_id: plan.id,
|
|
|
|
format: format
|
|
|
|
},
|
|
|
|
}])[0].done(function(response){
|
2023-09-08 12:47:29 +02:00
|
|
|
|
2023-05-17 21:19:14 +02:00
|
|
|
download(plan.shortname+".json",response.content,response.format);
|
2023-09-08 12:47:29 +02:00
|
|
|
}).fail(notification.exception);
|
2023-05-17 21:19:14 +02:00
|
|
|
},
|
2023-09-03 20:57:14 +02:00
|
|
|
toggletoolbox(event) {
|
|
|
|
debug.info(event);
|
|
|
|
this.toolbox.shown = event;
|
|
|
|
}
|
2023-05-17 21:19:14 +02:00
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|