{"version":3,"file":"studyplan-editor-components.min.js","sources":["../src/studyplan-editor-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-disable no-trailing-spaces */\n/*eslint-env es6*/\n// Put this file in path/to/plugin/amd/src\n\nimport {SimpleLine} from \"./simpleline\";\nimport {call} from 'core/ajax';\nimport notification from 'core/notification';\nimport {get_strings} from 'core/str';\nimport {load_stringkeys, load_strings, format_date, datespaninfo} from './string-helper';\nimport {objCopy,transportItem} from './studyplan-processor';\nimport Debugger from './debugger';\nimport {download,upload} from './downloader';\n\nconst STUDYPLAN_EDITOR_FIELDS = \n['name','shortname','description','context_id', 'aggregation','aggregation_config'];\nconst STUDYPLAN_EDITOR_PAGE_FIELDS =  //TODO: Add 'fullname', 'shortname' and 'description' when implementing proper page management\n['context_id', 'periods','startdate','enddate'];\nconst PERIOD_EDITOR_FIELDS =   \n['fullname','shortname','startdate','enddate'];\n\nconst LINE_GRAVITY = 1.3;\n\nconst datechanger_globals = {\n    default: false,\n    defaultchoice: false,\n    hidewarn: false,\n};\n\nexport default {\n    STUDYPLAN_EDITOR_FIELDS: STUDYPLAN_EDITOR_FIELDS, // make copy available in plugin\n    install(Vue/*,options*/){\n\n        let debug = new Debugger(\"treestudyplan-editor\");\n        debug.enable();\n        /************************************\n         *                                  *\n         * Treestudyplan Editor 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\n        // Create new eventbus for interaction between item components\n        const ItemEventBus = new Vue();\n\n        let string_keys = load_stringkeys({\n            conditions: [\n                { value: null,  textkey: 'condition_default'},\n                { value: 'ALL', textkey: 'condition_all'},\n                { value: '67',  textkey: 'condition_67'},\n                { value: '50',  textkey: 'condition_50'},\n                { value: 'ANY', textkey: 'condition_any'},\n            ],\n        });\n\n        let strings = load_strings({\n            studyplan_text: {\n                studyline_editmode: 'studyline_editmode',\n                editmode_modules_hidden:'editmode_modules_hidden',\n                studyline_add: 'studyline_add',\n                add$core: 'add$core',\n                edit$core: 'edit$core',\n                studyline_name: 'studyline_name',\n                studyline_name_ph: 'studyline_name_ph',\n                studyline_shortname: 'studyline_shortname',\n                studyline_shortname_ph: 'studyline_shortname_ph',\n                studyline_color: 'studyline_color',\n                associations: 'associations',\n                associated_cohorts: 'associated_cohorts',\n                associated_users: 'associated_users',\n                studyline_edit: 'studyline_edit',\n                studyplan_name: 'studyplan_name',\n                studyplan_name_ph: 'studyplan_name_ph',\n                studyplan_shortname: 'studyplan_shortname',\n                studyplan_shortname_ph: 'studyplan_shortname_ph',\n                studyplan_description: 'studyplan_description',\n                studyplan_description_ph: 'studyplan_description_ph',\n                studyplan_slots: 'studyplan_slots',\n                studyplan_startdate: 'studyplan_startdate',\n                studyplan_enddate: 'studyplan_enddate',\n            },\n            studyplan_advanced: {\n                advanced_tools: 'advanced_tools',\n                confirm_cancel: 'confirm_cancel',\n                confirm_ok: 'confirm_ok',\n                success$core: 'success$core',\n                error$core: 'failed$core',\n                advanced_converted: 'advanced_converted',\n                advanced_skipped: 'advanced_skipped',\n                advanced_failed: 'advanced_failed',\n                advanced_locked: 'advanced_locked',\n                advanced_multiple: 'advanced_multiple',\n                advanced_error: 'advanced_error',\n                advanced_tools_heading: 'advanced_tools_heading',\n                advanced_warning_title: 'advanced_warning_title',\n                advanced_warning: 'advanced_warning',\n                advanced_pick_scale: 'advanced_pick_scale',\n                advanced_course_manipulation_title: 'advanced_course_manipulation_title',\n                advanced_force_scale_title: 'advanced_force_scale_title',\n                advanced_force_scale_desc: 'advanced_force_scale_desc',\n                advanced_force_scale_button: 'advanced_force_scale_button',\n                advanced_disable_autoenddate_title: 'advanced_disable_autoenddate_title',\n                advanced_disable_autoenddate_desc: 'advanced_disable_autoenddate_desc',\n                advanced_disable_autoenddate_button: 'advanced_disable_autoenddate_button',\n                advanced_confirm_header: 'advanced_confirm_header',\n                advanced_force_scale_confirm: 'advanced_force_scale_confirm',\n                advanced_import: 'advanced_import',\n                advanced_export: 'advanced_export',\n                advanced_export_csv: 'advanced_export_csv',\n                advanced_import_from_file: 'advanced_import_from_file',\n                advanced_purge: \"advanced_purge\",\n                advanced_purge_expl: \"advanced_purge_expl\",\n                advanced_cascade_cohortsync_title: \"advanced_cascade_cohortsync_title\",\n                advanced_cascade_cohortsync_desc: \"advanced_cascade_cohortsync_desc\",\n                advanced_cascade_cohortsync: \"advanced_cascade_cohortsync\",\n            },\n            studyplan_edit: {\n                studyplan_edit: 'studyplan_edit',\n                studyplan_name: 'studyplan_name',\n                studyplan_name_ph: 'studyplan_name_ph',\n                studyplan_shortname: 'studyplan_shortname',\n                studyplan_shortname_ph: 'studyplan_shortname_ph',\n                studyplan_description: 'studyplan_description',\n                studyplan_description_ph: 'studyplan_description_ph',\n                studyplan_context: 'studyplan_context',\n                studyplan_slots: 'studyplan_slots',\n                studyplan_startdate: 'studyplan_startdate',\n                studyplan_enddate: 'studyplan_enddate',\n                choose_aggregation_style: 'choose_aggregation_style',\n                setting_bistate_thresh_excellent: 'setting_bistate_thresh_excellent',\n                settingdesc_bistate_thresh_excellent: 'settingdesc_bistate_thresh_excellent',\n                setting_bistate_thresh_good: 'setting_bistate_thresh_good',\n                settingdesc_bistate_thresh_good: 'settingdesc_bistate_thresh_good',\n                setting_bistate_thresh_completed: 'setting_bistate_thresh_completed',\n                settingdesc_bistate_thresh_completed: 'settingdesc_bistate_thresh_completed',\n                setting_bistate_support_failed: 'setting_bistate_support_failed',\n                settingdesc_bistate_support_failed: 'settingdesc_bistate_support_failed',\n                setting_bistate_thresh_progress: 'setting_bistate_thresh_progress',\n                settingdesc_bistate_thresh_progress: 'settingdesc_bistate_thresh_progress',\n                setting_bistate_accept_pending_submitted: 'setting_bistate_accept_pending_submitted',\n                settingdesc_bistate_accept_pending_submitted: 'settingdesc_bistate_accept_pending_submitted',\n            },\n            period_edit: {\n                edit: 'period_edit',\n                fullname: 'studyplan_name',\n                shortname: 'studyplan_shortname',\n                startdate: 'studyplan_startdate',\n                enddate: 'studyplan_enddate',\n            },\n            course_timing: {\n                title: 'course_timing_title',\n                desc: 'course_timing_desc',\n                question: 'course_timing_question',\n                warning: 'course_timing_warning',\n                timing_ok: 'course_timing_ok',\n                timing_off: 'course_timing_off',\n                course: 'course$core',\n                period: 'period',\n                yes: 'yes$core',\n                no: 'no$core',\n                duration: 'duration',\n                years: 'years$core',\n                year: 'year$core',\n                weeks: 'weeks$core',\n                week: 'week$core',\n                days: 'days$core',\n                day: 'day$core',\n                rememberchoice: 'course_timing_rememberchoice',\n                hidewarning: 'course_timing_hidewarning',\n                periodspan: 'course_period_span',\n                periods: 'periods',\n                periodspan_desc: 'course_period_span_desc',\n            },\n            studyplan_associate: {\n                associations: 'associations',\n                associated_cohorts: 'associated_cohorts',\n                associated_users: 'associated_users',\n                associate_cohorts: 'associate_cohorts',\n                associate_users: 'associate_users',\n                add_association: 'add_association',\n                delete_association: 'delete_association',\n                associations_empty: 'associations_empty',\n                associations_search: 'associations_search',\n                cohorts: 'cohorts',\n                users: 'users',\n                selected: 'selected',\n                name: 'name',\n                context: 'context',\n            },\n            item_text: {\n                select_conditions: \"select_conditions\",\n                item_configuration: \"item_configuration\",\n            },\n            item_course_text: {\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                ok: \"ok$core\",    \n            },\n            invalid: {\n                error: 'error',\n            },\n            completion: {\n                completion_completed: \"completion_completed\",\n                completion_incomplete: \"completion_incomplete\",\n                aggregation_all: \"aggregation_all\",\n                aggregation_any: \"aggregation_any\",\n                aggregation_overall_all: \"aggregation_overall_all\",\n                aggregation_overall_any: \"aggregation_overall_any\",\n                completion_not_configured: \"completion_not_configured\",\n                configure_completion: \"configure_completion\",\n            },\n            badge: {\n                share_badge: \"share_badge\",\n                dateissued: \"dateissued\",\n                dateexpire: \"dateexpire\",\n                badgeinfo: \"badgeinfo\",\n            },\n\n        });\n\n\n        /*\n        * T-STUDYPLAN-ADVANCED\n        */\n        Vue.component('t-studyplan-advanced', {\n            props: {\n                value: {\n                    type: Object,\n                    default(){ return null;},\n                },\n            },\n            data() {\n                return {\n                    force_scales: {\n                        selected_scale: null,\n                        result: [],\n                    },\n                    text: strings.studyplan_advanced,\n                };\n            },\n            created() {\n            },\n            mounted() {\n            },\n            updated() {\n\n            },\n            computed: {\n                scales(){\n                    return [{\n                        id: null,\n                        disabled: true,\n                        name: this.text.advanced_pick_scale,\n                    }].concat(this.value.advanced.force_scales.scales);\n                },\n            },\n            methods: {\n                disable_autoenddate(){\n                    const self=this;\n                    call([{\n                        methodname: 'local_treestudyplan_disable_autoenddate',\n                        args: {\n                            studyplan_id: this.value.id,\n                        }\n                    }])[0].done(function(response){\n                        self.$bvModal.msgBoxConfirm((response.success?self.text.success$core:self.text.error$core)\n                             + \"\\n\" + response.msg);\n                    }).fail(notification.exception);\n                },\n                force_scales_start(){\n                    // set confirmation box\n                    const self=this;\n                    this.$bvModal.msgBoxConfirm(this.text.advanced_force_scale_confirm,{\n                        title: this.text.advanced_force_scale_confirm,\n                        okVariant: 'danger',\n                        okTitle: this.text.confirm_ok,\n                        cancelTitle: this.text.confirm_cancel,\n                    }).then( value => {\n                        if(value == true){\n                            call([{\n                                methodname: 'local_treestudyplan_force_studyplan_scale',\n                                args: {\n                                    studyplan_id: this.value.id,\n                                    scale_id: this.force_scales.selected_scale,\n                                }\n                            }])[0].done(function(response){\n                                self.force_scales.result = response;\n                            }).fail(notification.exception);\n                        }\n                    });\n                },\n                export_plan(format){\n                    const self = this;\n                    if(format == undefined || ![\"json\",\"csv\"].includes(format)){\n                        format = \"json\";\n                    }\n                    call([{\n                            methodname: 'local_treestudyplan_export_plan',\n                            args: {\n                                studyplan_id: this.value.id,\n                                format: format,\n                            },\n                        }])[0].done(function(response){\n                            \n                            download(self.value.shortname+\".\"+format,response.content,response.format);\n                        }).fail(notification.exception);    \n                },\n                import_studylines(){\n                    //const self = this;\n                    upload((filename,content)=>{\n                        call([{\n                            methodname: 'local_treestudyplan_import_studylines',\n                            args: {\n                                studyplan_id:  this.value.id,\n                                content: content,\n                                format: \"application/json\",\n                            },\n                        }])[0].done(function(response){\n                            if(response.success){\n                                location.reload();\n                            } else {\n                                debug.error(\"Import failed: \",response.msg);\n                            }\n                            \n                        }).fail(notification.exception);  \n                    }, \"application/json\");\n                },\n                purge_studyline(){\n                    call([{\n                        methodname: 'local_treestudyplan_delete_studyplan',\n                        args: {\n                            id:  this.value.id,\n                            force: true,\n                        },\n                    }])[0].done(function(response){\n                        if(response.success){\n                            location.reload();\n                        } else {\n                            debug.error(\"Could not delete plan: \",response.msg);\n                        }\n                        \n                    }).fail(notification.exception);  \n                },\n                cascade_cohortsync(){\n                    const self = this;\n                    call([{\n                        methodname: 'local_treestudyplan_cascade_cohortsync',\n                        args: {\n                            studyplan_id:  this.value.id,\n                        },\n                    }])[0].done(function(response){\n                        self.$bvModal.msgBoxOk(response.success?self.text.success$core:self.text.error$core,\n                            { title: self.text.advanced_cascade_cohortsync});\n                    }).fail(notification.exception);  \n                },\n                modal_close(){\n                    this.force_scales.result = [];\n                }\n            },\n            template: \n            `\n            <span>\n                <a  v-if=\"value.advanced\" \n                    href='#' \n                    @click.prevent='' \n                    class='text-danger' \n                    v-b-modal=\"'t-studyplan-'+value.id+'-advanced'\"\n                    ><i class='fa fa-cog'></i>{{text.advanced_tools}}</a>\n                <b-modal v-if=\"value.advanced\" \n                    :id=\"'t-studyplan-'+value.id+'-advanced'\"\n                    size=\"lg\"\n                    :title=\"text.advanced_tools_heading\"\n                    ok-only\n                    @hide=\"modal_close\"\n                    >\n                    <b-card no-body>\n                    <b-tabs card>\n                        <b-tab :title=\"text.advanced_warning_title\" active>\n                            {{ text.advanced_warning}}\n                        </b-tab>\n                        <b-tab :title=\"text.advanced_course_manipulation_title\" >\n                            <b-container>\n                            <b-row><b-col cols=\"*\">\n                                <h3>{{ text.advanced_cascade_cohortsync_title}}</h3>\n                                    {{ text.advanced_cascade_cohortsync_desc}}\n                            </b-col></b-row>\n                            <b-row><b-col cols=\"*\">\n                                <b-button \n                                    variant=\"info\"\n                                    @click=\"cascade_cohortsync\"\n                                >{{ text.advanced_cascade_cohortsync}}</b-button>\n                            </b-col></b-row>\n                            <b-row class=\"mt-3\"><b-col cols=\"*\">\n                                <h3>{{ text.advanced_force_scale_title}}</h3>\n                                {{ text.advanced_force_scale_desc}}\n                            </b-col></b-row>\n                            <b-row>\n                                <b-col>\n                                    <b-form-select v-model=\"force_scales.selected_scale\" \n                                    :options=\"scales\" text-field=\"name\" value-field=\"id\"\n                                    ></b-form-select>\n                                </b-col>\n                                <b-col cols=\"4\">\n                                    <b-button \n                                        variant=\"danger\"\n                                        :disabled=\"force_scales.selected_scale == null\"\n                                        @click=\"force_scales_start\"\n                                    >{{ text.advanced_force_scale_button}}</b-button>\n                                </b-col>\n\n                            </b-row>\n                            <b-row class=\"mt-3\"><b-col cols=\"*\">\n                                <ul class='t-advanced-scrollable' v-if=\"force_scales.result.length > 0\">\n                                    <li v-for=\"c in force_scales.result\">\n                                        <span class='t-advanced-coursename'>{{c.course.fullname}}</span>\n                                        <ul v-if=\"c.grades.length > 0\">\n                                            <li v-for='g in c.grades'>\n                                                <span class='t-advanced-gradename'>{{g.name}}</span>\n                                                <span v-if=\"g.changed == 'converted'\" class='t-advanced-status changed'\n                                                    >{{text.advanced_converted}}</span\n                                                ><span v-else-if=\"g.changed == 'skipped'\" class='t-advanced-status skipped'\n                                                    >{{text.advanced_skipped}}</span\n                                                >\n                                                <span v-else class='t-advanced-status skipped'\n                                                    >{{text.advanced_error}}</span\n                                                >\n                                            </li>\n                                        </ul>\n                                    </li>\n                                </ul>\n                            </b-col></b-row>\n                            <b-row><b-col cols=\"*\">\n                                <h3>{{ text.advanced_disable_autoenddate_title}}</h3>\n                                {{ text.advanced_disable_autoenddate_desc}}\n                            </b-col></b-row>\n                            <b-row><b-col cols=\"*\">\n                                <b-button \n                                    variant=\"danger\"\n                                    @click=\"disable_autoenddate\"\n                                >{{ text.advanced_disable_autoenddate_button}}</b-button>\n                            </b-col></b-row>\n                            </b-container>\n                        </b-tab>\n                        <b-tab :title='text.advanced_export'>\n                            <b-button   \n                                    variant=\"primary\"\n                                    @click=\"export_plan\"\n                                >{{ text.advanced_export}}</b-button>\n                            <b-button\n                                    variant=\"danger\"\n                                    @click=\"import_studylines\"\n                                >{{ text.advanced_import}}</b-button>\n                            <b-button   \n                                variant=\"primary\"\n                                @click=\"export_plan('csv')\"\n                            >{{ text.advanced_export_csv}}</b-button>\n                    </b-tab>\n                        <b-tab :title='text.advanced_purge'>\n                            <p>{{text.advanced_purge_expl}}</p>\n                            <p><b-button\n                                    variant=\"danger\"\n                                    @click=\"purge_studyline\"\n                                >{{ text.advanced_purge}}</b-button></p>\n                        </b-tab>                    </b-tabs>\n                    </b-card>\n                </b-modal>     \n            </span>           \n            `\n        });\n\n\n        /*\n        * T-STUDYPLAN-EDIT\n        */\n        Vue.component('t-studyplan-edit', {\n            props: {\n                'value' :{\n                    type: Object,\n                    default(){ return null;},\n                },\n                'mode' :{\n                    type: String,\n                    default() { return \"edit\";},\n                },\n                'type' :{\n                    type: String,\n                    default() { return \"link\";},\n                },\n                'variant' : {\n                    type: String,\n                    default() { return \"\";},\n                }\n            },\n            data() {\n                return {\n                    show: false,\n                    config: {\n                        userfields: [ \n                            { key: \"selected\",},\n                            { key: \"firstname\", \"sortable\": true,},\n                            { key: \"lastname\", \"sortable\": true,},\n                        ],\n                        cohortfields:[ \n                            { key: \"selected\",},\n                            { key: \"name\", \"sortable\": true,},\n                            { key: \"context\", \"sortable\": true,},\n                        ]\n                    },\n                    editdata: {   \n                        name: '',\n                        shortname: '',\n                        description: '',\n                        context_id: 1,\n                        periods : 4,\n                        startdate: (new Date()).getFullYear() + '-08-01',\n                        enddate:  ((new Date()).getFullYear()+1) + '-08-01',\n                        aggregation: 'bistate',\n                        aggregation_config: '',\n                    },\n                    aggregation_parsed: {\n\n                    },\n                    aggregators: [],\n                    categories: [ { context_id: 1, category: { path: \"System\"}}], // overwritten during load...\n                    text: strings.studyplan_edit,\n                };\n            },\n            created() {\n                // retrieve aggregator info\n                const self = this;\n                call([{\n                    methodname: 'local_treestudyplan_list_aggregators',\n                    args: [],\n                }])[0].done(function(response){\n                    self.aggregators = response;\n                    for(const ix  in self.aggregators){\n                        const ag = self.aggregators[ix];\n                        \n                        try{\n                            if(ag.defaultconfig && ag.defaultconfig.length > 0){\n                                self.aggregation_parsed[ag.id] = JSON.parse(ag.defaultconfig);\n                            }\n                        }\n                        catch(e){\n                            debug.warn(e);\n                        }\n                    }\n                }).fail(notification.exception);\n                call([{\n                    methodname: 'local_treestudyplan_list_accessible_categories',\n                    args: {operation: \"edit\",}\n                }])[0].done(function(response){\n                    for(const ix in response){\n                        const cat = response[ix];\n                        cat.category.pathname = cat.category.path.join(\" / \");\n                    }\n                    self.categories = response;\n                }).fail(notification.exception);\n            },\n            mounted() {\n            },\n            updated() {\n\n            },\n            computed: {\n            },\n            methods: {\n                editPlanStart(){\n                    if(this.mode != 'create'){\n                        objCopy(this.editdata,this.value.pages[0],STUDYPLAN_EDITOR_PAGE_FIELDS);\n                        objCopy(this.editdata,this.value,STUDYPLAN_EDITOR_FIELDS);\n\n                    }\n                    // decode the aggregation config data that is stored\n                    if(this.editdata.aggregation_config && this.editdata.aggregation_config.length > 0){\n                        try{\n                            this.aggregation_parsed[this.editdata.aggregation] = JSON.parse(this.editdata.aggregation_config);\n                        }\n                        catch(e){\n                            debug.warn(e);\n                        }\n                    }\n                    this.show = true;\n                },\n                editPlanFinish(){\n                    const self = this;\n                    let args = { };\n                    let method =  'local_treestudyplan_edit_studyplan';\n                    if(this.mode == 'create'){\n                        method = 'local_treestudyplan_add_studyplan';\n                    } else {\n                        args['id'] = this.value.id;\n                    }\n\n                    // store the configuration for this aggregation type if it is relevant\n                    if(this.aggregation_parsed[this.editdata.aggregation]){\n                        this.editdata.aggregation_config = JSON.stringify(this.aggregation_parsed[this.editdata.aggregation]);\n                    }\n                    objCopy(args,this.editdata,STUDYPLAN_EDITOR_FIELDS);\n                    objCopy(args,this.editdata,STUDYPLAN_EDITOR_PAGE_FIELDS);\n\n                    call([{\n                        methodname: method,\n                        args: args\n                    }])[0].done(function(response){\n                        if(self.mode == 'create'){\n                            self.$emit(\"created\", response);\n                            // And reset the edit fields to default\n                            self.editdata = {   \n                                name: '',\n                                shortname: '',\n                                description: '',\n                                context_id: 1,\n                                periods : 4,\n                                startdate: (new Date()).getFullYear() + '-08-01',\n                                enddate: ((new Date()).getFullYear()+1) + '-08-01',\n                                aggregation: 'bistate',\n                                aggregation_config: '',\n                            };\n                        }\n                        else {\n                            // determine if the plan moved context...\n                            const moved_from = self.value.context_id;\n                            const moved_to = response.context_id;\n                            const moved = (moved_from != moved_to);\n\n                            objCopy(self.value,response,STUDYPLAN_EDITOR_FIELDS);\n                            self.$emit('input',self.value);\n                            if(moved){\n                                self.$emit('moved',self.value,moved_from, moved_to);\n                            }\n                        }\n                    }).fail(notification.exception);\n                },\n                numberFilter(value){\n                    return value;\n                }\n            }\n            ,\n            template: \n            `\n            <span class='s-studyplan-edit'>\n                <b-button :variant=\"variant\" v-if='type == \"button\"' @click.prevent='editPlanStart()'\n                    ><slot><i class='fa fa-pencil'></i></slot></b-button>\n                <a variant=\"variant\" v-else href='#' @click.prevent='editPlanStart()'\n                    ><slot><i class='fa fa-pencil'></i></slot></a>\n                <b-modal \n                    v-model=\"show\"\n                    size=\"lg\"\n                    ok-variant=\"primary\"\n                    :title=\"text.studyplan_edit\"\n                    @ok=\"editPlanFinish()\"\n                    :ok-disabled=\"Math.min(editdata.name.length,editdata.shortname.length) == 0\"\n                    >\n                    <b-container>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_name}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input v-model=\"editdata.name\" \n                                :state='editdata.name.length>0'\n                                :placeholder=\"text.studyplan_name_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_shortname}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input v-model=\"editdata.shortname\" \n                                :state='editdata.shortname.length>0'\n                                :placeholder=\"text.studyplan_shortname_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_description}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input v-model=\"editdata.description\" \n                                :placeholder=\"text.studyplan_description_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_context}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-select v-model=\"editdata.context_id\" \n                                :options=\"categories\" text-field=\"category.pathname\" value-field=\"context_id\"\n                                ></b-form-select>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_slots}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input type=number v-model=\"editdata.periods\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_startdate}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-datepicker v-model=\"editdata.startdate\"></b-form-datepicker>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_enddate}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-datepicker v-model=\"editdata.enddate\" ></b-form-datepicker>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.choose_aggregation_style}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-select v-model=\"editdata.aggregation\" \n                                :options=\"aggregators\" text-field=\"name\" value-field=\"id\"\n                                ></b-form-select>\n                            </b-col>\n                        </b-row>\n                        <template v-if=\"aggregation_parsed.bistate && editdata.aggregation == 'bistate'\">\n                            <b-row >\n                                <b-col cols=\"4\">{{ text.setting_bistate_thresh_excellent}}</b-col>\n                                <b-col cols=\"8\">\n                                    <b-form-input v-model=\"aggregation_parsed.bistate.thresh_excellent\" \n                                    type=\"number\" number :formatter=\"numberFilter\"\n                                    ></b-form-input>\n                                </b-col>\n                            </b-row>\n                            <b-row >\n                                <b-col cols=\"4\">{{ text.setting_bistate_thresh_good}}</b-col>\n                                <b-col cols=\"8\">\n                                    <b-form-input v-model=\"aggregation_parsed.bistate.thresh_good\" \n                                    type=\"number\" number :formatter=\"numberFilter\"\n                                    ></b-form-input>\n                                </b-col>\n                            </b-row>\n                            <b-row >\n                                <b-col cols=\"4\">{{ text.setting_bistate_thresh_completed}}</b-col>\n                                <b-col cols=\"8\">\n                                    <b-form-input v-model=\"aggregation_parsed.bistate.thresh_completed\" \n                                    type=\"number\" number :formatter=\"numberFilter\"\n                                    ></b-form-input>\n                                </b-col>\n                            </b-row>       \n                            <b-row>\n                                <b-col cols=\"4\">{{ text.setting_bistate_thresh_progress}}</b-col>\n                                <b-col cols=\"8\">\n                                    <b-form-input v-model=\"aggregation_parsed.bistate.thresh_progress\" \n                                    type=\"number\" number :formatter=\"numberFilter\"\n                                    ></b-form-input>\n                                </b-col>\n                            </b-row>          \n                            <b-row><b-col cols=\"*\">&nbsp;</b-col></b-row>\n                            <b-row>\n                                <b-col cols=\"7\">{{ text.setting_bistate_support_failed}}</b-col>\n                                <b-col cols=\"3\">\n                                    <b-form-checkbox v-model=\"aggregation_parsed.bistate.use_failed\" \n                                    ></b-form-checkbox>\n                                </b-col>\n                            </b-row>\n                            <b-row><b-col cols=\"*\">&nbsp;</b-col></b-row>\n                            <b-row >\n                                <b-col cols=\"7\">{{ text.setting_bistate_accept_pending_submitted}}</b-col>\n                                <b-col cols=\"3\">\n                                    <b-form-checkbox v-model=\"aggregation_parsed.bistate.accept_pending_as_submitted\" \n                                    ></b-form-checkbox>\n                                </b-col>\n                            </b-row>       \n                        </template>                  \n                    </b-container>\n                </b-modal>     \n            </span>           \n            `\n        });\n\n        /*\n        * T-STUDYPLAN-ASSOCIATE\n        */\n        Vue.component('t-studyplan-associate', {\n            props: ['value',],\n            data() {\n                return {\n                    show: false,\n                    config: {\n                        userfields: [ \n                            { key: \"selected\",},\n                            { key: \"firstname\", \"sortable\": true,},\n                            { key: \"lastname\", \"sortable\": true,},\n                        ],\n                        cohortfields:[ \n                            { key: \"selected\",},\n                            { key: \"name\", \"sortable\": true,},\n                            { key: \"context\", \"sortable\": true,},\n                        ]\n                    },\n                    association: {\n                        cohorts: [],\n                        users: [],\n                    },\n                    loading: {\n                        cohorts: false,\n                        users: false,\n                    },\n                    search: {users: [], cohorts:[]},\n                    selected: {\n                         search: {users: [] , cohorts:[]}, \n                         associated: {users: [] , cohorts:[]}\n                    },              \n                    text: strings.studyplan_associate,\n                };\n            },\n            created() {\n            \n            },\n            mounted() {\n            },\n            updated() {\n\n            },\n            methods: {\n                showModal(){\n                    this.show = true;\n                    this.loadAssociations();\n                },\n                cohortOptionModel(c){\n                    return {\n                        value: c.id,\n                        text: c.name + ' (' + c.context.path.join(' / ') + ')',\n                    };\n                },\n                userOptionModel(u){\n                    return {\n                        value: u.id,\n                        text: u.firstname + ' ' + u.lastname,\n                    };\n                },\n                loadAssociations(){\n                    const self = this;\n                    self.loading.cohorts = true;\n                    self.loading.users = true;\n                    call([{\n                        methodname: 'local_treestudyplan_associated_users',\n                        args: { studyplan_id: self.value.id,}\n                    }])[0].done(function(response){\n                        self.association.users = response.map(self.userOptionModel);\n                        self.loading.users = false;\n                    }).fail(notification.exception);         \n\n                    call([{\n                        methodname: 'local_treestudyplan_associated_cohorts',\n                        args: { studyplan_id: self.value.id,}\n                    }])[0].done(function(response){\n                        self.association.cohorts = response.map(self.cohortOptionModel);\n                        self.loading.cohorts = false;\n                    }).fail(notification.exception);                             \n                },                \n                searchCohorts(searchtext){\n                    const self = this;\n\n                    if(searchtext.length > 0)\n                    {\n                        call([{\n                            methodname: 'local_treestudyplan_list_cohort',\n                            args: { like: searchtext, exclude_id: self.value.id}\n                        }])[0].done(function(response){\n                            self.search.cohorts = response.map(self.cohortOptionModel);\n                        }).fail(notification.exception);                \n                    }\n                    else {\n                        self.search.cohorts = [];\n                    }\n                },\n                cohortAssociate(){\n                    const self = this;\n                    let requests = [];\n                    const associated = self.association.cohorts;\n                    const search = self.search.cohorts;\n                    const searchselected = self.selected.search.cohorts;\n                    for(const i in searchselected){\n                        const r = searchselected[i];                    \n                        requests.push({\n                            methodname: 'local_treestudyplan_connect_cohort',\n                            args: {studyplan_id: self.value.id, cohort_id: r},\n                            fail: notification.exception,\n                            done: function(response){\n                                if(response.success){\n                                    transportItem(associated,search,r);\n                                }\n                            }\n                        });\n                    }\n                    call(requests);\n                },\n                cohortDisassociate(){\n                    const self = this;\n                    let requests = [];\n                    const associatedselected = self.selected.associated.cohorts;\n                    const associated = self.association.cohorts;\n                    const search =  self.search.cohorts;\n                    for(const i in associatedselected){\n                        const r = associatedselected[i];                    \n                        requests.push({\n                            methodname: 'local_treestudyplan_disconnect_cohort',\n                            args: {studyplan_id: self.value.id, cohort_id: r},\n                            fail: notification.exception,\n                            done: function(response){\n                                if(response.success){\n                                    transportItem(search,associated,r);\n                                }\n                            }\n                        });\n                    }\n                    call(requests);\n                },       \n                searchUsers(searchtext){\n                    const self = this;\n                    if(searchtext.length > 0)\n                    {\n                        call([{\n                            methodname: 'local_treestudyplan_find_user',\n                            args: { like: searchtext, exclude_id: self.value.id}\n                        }])[0].done(function(response){\n                            self.search.users = response.map(self.userOptionModel);\n                        }).fail(notification.exception);                \n                    }\n                    else {\n                        self.search.users = [];\n                    }\n                },\n                userAssociate(){\n                    const self = this;\n                    let requests = [];\n                    const associated = self.association.users;\n                    const search =  self.search.users;\n                    const searchselected =  self.selected.search.users;\n                    for(const i in searchselected){\n                        const r = searchselected[i];                    \n                        \n                        requests.push({\n                            methodname: 'local_treestudyplan_connect_user',\n                            args: {studyplan_id: self.value.id, user_id: r},\n                            fail: notification.exception,\n                            done: function(response){\n                                if(response.success){\n                                    transportItem(associated,search,r);\n                                }\n                            }\n                        });\n                    }\n                    call(requests);\n                },\n                userDisassociate(){\n                    const self = this;\n                    let requests = [];\n                    const associated = self.association.users;\n                    const associatedselected = self.selected.associated.users;\n                    const search = self.search.users;\n                    for(const i in associatedselected){\n                        const r = associatedselected[i];                    \n                        \n                        requests.push({\n                            methodname: 'local_treestudyplan_disconnect_user',\n                            args: {studyplan_id: self.value.id, user_id: r},\n                            fail: notification.exception,\n                            done: function(response){\n                                if(response.success){\n                                    transportItem(search,associated,r);\n                                }\n                            }\n                        });\n                    }\n                    call(requests);\n                },\n            }\n            ,\n            template: \n`\n<span class='s-studyplan-associate'\n    ><a href='#' @click.prevent=\"showModal\" ><slot><i class='fa fa-users'></i></slot></a>\n    <b-modal\n        v-model=\"show\" \n        size=\"lg\" \n        ok-variant=\"primary\"\n        :title=\"text.associations + ' - ' + value.name\"\n        ok-only>\n        <b-tabs class='s-studyplan-associate-window'>\n            <b-tab :title=\"text.cohorts\">\n                <b-container>\n                    <b-row class='mb-2 mt-2'>\n                        <b-col>{{text.associated_cohorts}}</b-col>\n                        <b-col>{{text.associate_cohorts}}</b-col>\n                    </b-row>\n                    <b-row class='mb-2'>\n                        <b-col>\n                        </b-col>\n                        <b-col>\n                            <b-form-input \n                                type=\"text\" @input=\"searchCohorts($event)\" \n                                :placeholder=\"text.search\"></b-form-input>\n                        </b-col>\n                    </b-row>\n                    <b-row>\n                        <b-col>\n                            <b-form-select\n                                multiple\n                                v-model=\"selected.associated.cohorts\"\n                                :options=\"association.cohorts\"\n                                :select-size=\"10\"\n                                ></b-form-select>\n                        </b-col>\n                        <b-col>\n                            <b-form-select\n                                multiple\n                                v-model=\"selected.search.cohorts\"\n                                :options=\"search.cohorts\"\n                                :select-size=\"10\"\n                                ></b-form-select>\n                        </b-col>\n                    </b-row>\n                    <b-row class='mt-2'>\n                        <b-col>\n                            <b-button variant='danger' @click=\"cohortDisassociate()\"\n                                ><i class='fa fa-chain-broken'></i>&nbsp;{{text.delete_association}}</b-button>\n                        </b-col>\n                        <b-col>\n                            <b-button variant='success' @click=\"cohortAssociate()\"\n                                ><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button>                            \n                        </b-col>\n                    </b-row>\n                </b-container>\n            </b-tab>\n            <b-tab :title=\"text.users\">\n                <b-container>\n                    <b-row class='mb-2 mt-2'>\n                        <b-col>{{text.associated_users}}</b-col>\n                        <b-col>{{text.associate_users}}</b-col>\n                    </b-row>\n                    <b-row class='mb-2'>\n                        <b-col>\n                        </b-col>\n                        <b-col>\n                            <b-form-input \n                                type=\"text\" \n                                @input=\"searchUsers($event)\" \n                                placeholder=\"Search users\"></b-form-input>\n                        </b-col>\n                    </b-row>\n                    <b-row>\n                        <b-col>\n                            <b-form-select\n                                multiple\n                                v-model=\"selected.associated.users\"\n                                :options=\"association.users\"\n                                :select-size=\"10\"\n                                ></b-form-select>\n                        </b-col>\n                        <b-col>\n                            <b-form-select\n                                multiple\n                                v-model=\"selected.search.users\"\n                                :options=\"search.users\"\n                                :select-size=\"10\"\n                                ></b-form-select>\n                        </b-col>\n                    </b-row>\n                    <b-row class='mt-2'>\n                        <b-col>\n                                <b-button variant='danger' @click=\"userDisassociate()\"\n                                ><i class='fa fa-chain-broken'></i>&nbsp;{{text.delete_association}}</b-button>\n                        </b-col>\n                        <b-col>\n                            <b-button variant='success' @click=\"userAssociate()\"\n                                ><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button>              \n                        </b-col>\n                    </b-row>                                \n                </b-container>                            \n            </b-tab>\n        </b-tabs>\n    </b-modal>\n</span>               \n`\n        });\n\n        /*******************\n         * \n         * Period editor\n         * \n         *************/\n\n        Vue.component('t-period-edit', {\n            props: {\n                'value' :{\n                    type: Object,\n                    default(){ return null;},\n                },\n                'type' :{\n                    type: String,\n                    default() { return \"link\";},\n                },\n                'variant' : {\n                    type: String,\n                    default() { return \"\";},\n                }\n            },\n            data() {\n                return {\n                    show: false,\n                    editdata: {   \n                        fullname: '',\n                        shortname: '',\n                        startdate: (new Date()).getFullYear() + '-08-01',\n                        enddate:  ((new Date()).getFullYear()+1) + '-08-01',\n                    },\n                    text: strings.period_edit,\n                };\n            },\n            created() {\n            },\n            mounted() {\n            },\n            updated() {\n\n            },\n            computed: {\n            },\n            methods: {\n                editStart(){\n                    objCopy(this.editdata,this.value,PERIOD_EDITOR_FIELDS);\n                    this.show = true;\n                },\n                editFinish(){\n                    const self = this;\n                    let args = { 'id': this.value.id };\n                    let method =  'local_treestudyplan_edit_period';\n\n                    objCopy(args,this.editdata,PERIOD_EDITOR_FIELDS);\n\n                    call([{\n                        methodname: method,\n                        args: args\n                    }])[0].done(function(response){\n                        objCopy(self.value,response,PERIOD_EDITOR_FIELDS);\n                        self.$emit('input',self.value);\n                    }).fail(notification.exception);\n                },\n            }\n            ,\n            template: \n            `\n            <span class='t-period-edit'>\n                <b-button :variant=\"variant\" v-if='type == \"button\"' @click.prevent='editStart()'\n                    ><slot><i class='fa fa-pencil'></i></slot></b-button>\n                <a variant=\"variant\" v-else href='#' @click.prevent='editStart()'\n                    ><slot><i class='fa fa-pencil'></i></slot></a>\n                <b-modal \n                    v-model=\"show\"\n                    size=\"lg\"\n                    ok-variant=\"primary\"\n                    :title=\"text.period_edit\"\n                    @ok=\"editFinish()\"\n                    :ok-disabled=\"Math.min(editdata.fullname.length,editdata.shortname.length) == 0\"\n                    >\n                    <b-container>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.fullname}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input v-model=\"editdata.fullname\" \n                                :state='editdata.fullname.length>0'\n                                ></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.shortname}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-input v-model=\"editdata.shortname\" \n                                :state='editdata.shortname.length>0'\n                                ></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_startdate}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-datepicker v-model=\"editdata.startdate\"></b-form-datepicker>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"4\">{{ text.studyplan_enddate}}</b-col>\n                            <b-col cols=\"8\">\n                                <b-form-datepicker v-model=\"editdata.enddate\" ></b-form-datepicker>\n                            </b-col>\n                        </b-row>\n                    </b-container>\n                </b-modal>     \n            </span>           \n            `\n        });\n\n        /*\n        * T-STUDYPLAN\n        */\n        Vue.component('t-studyplan', {\n            props: ['value', 'index'],\n            data() {\n                return {\n                    config: {\n                        userfields: [ \n                            { key: \"selected\",},\n                            { key: \"firstname\", \"sortable\": true,},\n                            { key: \"lastname\", \"sortable\": true,},\n                        ],\n                        cohortfields:[ \n                            { key: \"selected\",},\n                            { key: \"name\", \"sortable\": true,},\n                            { key: \"context\", \"sortable\": true,},\n                        ]\n                    },\n                    create: {\n                        studyline: {\n                            'name': '',\n                            'shortname': '',\n                            'color': '#DDDDDD',\n                        },\n                    },\n                    edit: {\n                        studyline: {\n                            editmode: false,\n                            data: {   \n                                name: '',\n                                shortname: '',\n                                color: '#DDDDDD',\n                            },\n                            original: {},\n                        },\n                        studyplan: {\n                            data: {   \n                                name: '',\n                                shortname: '',\n                                description: '',\n                                slots : 4,\n                                startdate: '2020-08-01',\n                                enddate: '',\n                                aggregation: '',\n                                aggregation_config: '',\n                                aggregation_info: {\n                                    useRequiredGrades: true,\n                                    useItemCondition: false,\n                                },\n\n                            },\n                            original: {},\n                        }\n                    },\n                    text: strings.studyplan_text,\n                };\n            },\n            created() {\n            \n            },\n            mounted() {\n                if(this.page.studylines.length == 0){\n                    // start in editmode if studylines are empty\n                    this.edit.studyline.editmode = true;\n                }  \n                this.$root.$emit('redrawLines');\n            },\n            updated() {\n                this.$root.$emit('redrawLines');\n                ItemEventBus.$emit('redrawLines');\n            },\n            computed: {\n                columns() {\n                    return 1+ (this.page.periods * 2);\n                },\n                columns_stylerule() {\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)\"; // use css variable here\n                    for(let i=0; i<this.page.periods;i++){\n                        s+= \" var(--studyplan-course-width) var(--studyplan-filter-width)\";\n                    }\n                    return s+\";\";\n                },\n                page(){\n                    // FIXME: Temporary hack until real page management is implemented\n                    return this.value.pages[0];\n                }\n            },\n            methods: {\n                countLineLayers(line){\n                    let maxLayer = -1;\n                    for(let i = 0; i <= this.page.periods; i++){\n                        const slot = line.slots[i];\n                        // Determine the amount of used layers in a studyline slit\n                        for(const ix in line.slots[i].competencies){\n                            const item = line.slots[i].competencies[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+1;\n                },\n                slotsempty(slots) {\n                    if(Array.isArray(slots)){\n                        let count = 0;\n                        for(let i = 0; i < slots.length; i++) {\n                            if(Array.isArray(slots[i].competencies)){\n                                count += slots[i].competencies.length;\n                            }\n                            if(Array.isArray(slots[i].filters)){\n                                count += slots[i].filters.length;\n                            }\n                        }\n                        return (count == 0);\n                    } else {\n                        return false;\n                    }\n                },\n                movedStudyplan(plan,from,to) {\n                    this.$emit('moved',plan,from,to); // Throw the event up....\n                },\n                addStudyLine(page,newlineinfo) {\n                    call([{\n                        methodname: 'local_treestudyplan_add_studyline',\n                        args: {\n                            'page_id': page.id,\n                            'name': newlineinfo.name,\n                            'shortname': newlineinfo.shortname,\n                            'color': newlineinfo.color,\n                            'sequence': page.studylines.length,\n                        }\n                    }])[0].done(function(response){\n                        page.studylines.push(response);\n                        newlineinfo.name = '';\n                        newlineinfo.shortname = '';\n                        newlineinfo.color = \"#dddddd\";\n                    }).fail(notification.exception);\n                },\n                editLineStart(line) {\n                    Object.assign(this.edit.studyline.data,line);\n                    this.edit.studyline.original = line;\n                    this.$bvModal.show('modal-edit-studyline-'+this.value.id);\n                },\n                editLineFinish() {\n                    let editedline = this.edit.studyline.data;\n                    let originalline = this.edit.studyline.original;\n                    call([{\n                        methodname: 'local_treestudyplan_edit_studyline',\n                        args: { 'id': editedline.id,\n                                'name': editedline.name,\n                                'shortname': editedline.shortname,\n                                'color': editedline.color,}\n                    }])[0].done(function(response){\n                        originalline['name'] = response['name'];\n                        originalline['shortname'] = response['shortname'];\n                        originalline['color'] = response['color'];\n                    }).fail(notification.exception);\n                },\n                deleteLine(page,line) {\n                    const self=this;\n                    get_strings([\n                            {key: 'studyline_confirm_remove', param: line.name, component: 'local_treestudyplan' },\n                            {key: 'delete', component: 'core' },\n                        ]).then(function(s){\n                        self.$bvModal.msgBoxConfirm(s[0], {\n                            okTitle: s[1],\n                            okVariant: 'danger',\n                        }).then(function(modalresponse){\n                            if(modalresponse){\n                                call([{\n                                    methodname: 'local_treestudyplan_delete_studyline',\n                                    args: { 'id': line.id, }\n                                }])[0].done(function(response){\n                                    if(response.success == true){\n                                        let index = page.studylines.indexOf(line);\n                                        page.studylines.splice(index, 1);\n                                    }\n                                }).fail(notification.exception);\n                            }\n                        });\n                    });\n                },\n                reorderLines(event,lines){\n\n                    // apply reordering\n                    event.apply(lines);\n                    // send the new sequence to the server\n                    let sequence = [];\n                    for(let idx in lines)\n                    {\n                        sequence.push({'id': lines[idx].id,'sequence': idx});\n                    }\n                    call([{\n                        methodname: 'local_treestudyplan_reorder_studylines',\n                        args: { 'sequence': sequence }\n                    }])[0].done(function(response){\n                    }).fail(notification.exception);\n                },\n                deletePlan(studyplan){\n                    const self=this;\n                    get_strings([\n                        {key: 'studyplan_confirm_remove', param: studyplan.name, component: 'local_treestudyplan' },\n                        {key: 'delete', component: 'core' },\n                    ]).then(function(s){\n                        self.$bvModal.msgBoxConfirm(s[0], {\n                            okTitle: s[1],\n                            okVariant: 'danger',\n                        }).then(function(modalresponse){\n                            if(modalresponse){\n                                call([{\n                                    methodname: 'local_treestudyplan_delete_studyplan',\n                                    args: { 'id': studyplan.id, }\n                                }])[0].done(function(response){\n                                    if(response.success == true){\n                                        self.$root.$emit(\"studyplanRemoved\",studyplan);\n                                    }\n                                }).fail(notification.exception);\n                            }\n                        });\n                    });\n                },\n                deleteStudyItem(event){\n                    //const self = this;\n                    let item = event.data;\n\n                    call([{\n                        methodname: 'local_treestudyplan_delete_studyitem',\n                        args: { 'id': item.id, }\n                    }])[0].done(function(response){\n                        if(response.success == true){\n                            event.source.$emit('cut',event);\n                        }\n                    }).fail(notification.exception);\n\n                },\n                showslot(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 = this.page.periods;\n                    let show = true;\n                    for(let i = 0; i < periods; i++){\n                        if(line.slots[index-i] && line.slots[index-i].competencies){\n                            const list = line.slots[index-i].competencies;\n                            for(const ix in list){ // Really wish that 'for of' would work with the minifier moodle uses\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            }\n            ,\n            template: \n            `\n            <div>\n                <div class='controlbox t-studyplan-controlbox'>\n                    <b-form-checkbox v-model=\"edit.studyline.editmode\" class=\"sw-studyline-editmode\" switch\n                        >{{ text.studyline_editmode }}</b-form-checkbox>\n                    <drop \n                        mode='copy'\n                        class='t-item-deletebox text-danger border-danger'\n                        @drop='deleteStudyItem'\n                        :accepts-type=\"['gradable-item','filter-item']\"\n                        ><i class='fa fa-trash'></i>\n                    </drop>\n                    <span class='control deletable'>\n                        <a v-if='page.studylines.length == 0' href='#' @click='deletePlan(value)'\n                            ><i class='text-danger fa fa-trash'></i></a>\n                    </span>\n                    <span class='control editable'>\n                        <t-studyplan-edit v-model=\"value\" @moved=\"movedStudyplan\"\n                            ><i class='fa fa-pencil'></i> {{text.edit$core}}</t-studyplan-edit>    \n                    </span>\n                    <span class='control editable'>\n                        <t-studyplan-associate \n                            v-model=\"value\"><i class='fa fa-users'></i> {{text.associations}}</t-studyplan-associate>\n                    </span>\n                    <span class='control editable'>\n                        <t-studyplan-advanced v-model=\"value\"></t-studyplan-advanced>\n                    </span>\n                </div>\n                <div class='t-studyplan-content-edit' v-if=\"edit.studyline.editmode\">\n                    <drop-list\n                        :items=\"page.studylines\"\n                        class=\"t-slot-droplist\"\n                        :accepts-type=\"'studyline-'+page.id\"\n                        xreorder=\"$event.apply(page.studylines)\"\n                        @reorder=\"reorderLines($event,page.studylines)\"\n                        mode=\"copy\"\n                        row\n                    >\n                        <template v-slot:item=\"{item}\">\n                            <drag \n                                :key=\"item.id\" \n                                class='t-studyline-drag'\n                                :data=\"item\" \n                                :type=\"'studyline-'+page.id\" \n                                >\n                                <template v-slot:drag-image>\n                                    <i class=\"fa fa-arrows text-primary\"></i>\n                                </template>\n                                <t-studyline-edit \n                                    v-model=\"item\"\n                                    @edit='editLineStart(item)'\n                                    @delete='deleteLine(page,item)'\n                                    >\n                                    <div v-if=\"!slotsempty(item.slots)\"> {{ text.editmode_modules_hidden}} </div>\n                                </t-studyline-edit>\n                            </drag>\n                        </template>\n                    </drop-list>\n                </div>\n                <div class='t-studyplan-content' v-else>\n\n                    <!-- Now paint the headings column -->\n                    <div class='t-studyplan-headings'>\n                        <s-studyline-header-heading></s-studyline-header-heading>\n                        <t-studyline-heading  v-for=\"(line,lineindex) in page.studylines\"\n                            :key=\"line.id\"\n                            @resize=\"headingresized(lineindex,$event)\"\n                            v-model=\"page.studylines[lineindex]\"\n                            :layers='countLineLayers(line)+1'\n                            :class=\" 't-studyline' + ((lineindex%2==0)?' odd ' :' even ' )\n                                    + ((lineindex==0)?' first ':' ') \n                                    + ((lineindex==page.studylines.length-1)?' last ':' ')\"\n                        ></t-studyline-heading>\n                    </div>\n                    <!-- Next, paint all the cells in the scrollable -->\n                    <div class=\"t-studyplan-scrollable\" >\n                        <div class=\"t-studyplan-timeline\" :style=\"columns_stylerule\">\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                                ><t-period-edit v-model=\"page.perioddesc[index-1]\"></t-period-edit\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)+1\"\n                                ><template v-for=\"(n,index) in (page.periods+1)\"\n                                    >\n                                    <t-studyline-slot \n                                        v-if=\"index > 0 && showslot(line, index, layeridx, 'gradable')\"\n                                        type='gradable'\n                                        v-model=\"line.slots[index].competencies\" \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                                        :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                                    ></t-studyline-slot\n                                    ><t-studyline-slot \n                                        type='filter'\n                                        v-if=\"showslot(line, index, layeridx, 'filter')\"\n                                        v-model=\"line.slots[index].filters\" \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                                        >\n                                    </t-studyline-slot\n                                ></template\n                            ></template\n                        ></template\n                        ></div>\n                    </div>\n                </div>\n                <div v-if=\"edit.studyline.editmode\" class='t-studyline-add'>\n                    <a href=\"#\" v-b-modal=\"'modal-add-studyline-'+page.id\" @click=\"false;\"\n                        ><i class='fa fa-plus'></i>{{ text.studyline_add }}</a>\n                </div>\n                <b-modal \n                    :id=\"'modal-add-studyline-'+page.id\" \n                    size=\"lg\" \n                    :ok-title=\"text.add$core\"\n                    ok-variant=\"primary\"\n                    :title=\"text.studyline_add\"\n                    @ok=\"addStudyLine(page,create.studyline)\"\n                    :ok-disabled=\"Math.min(create.studyline.name.length,create.studyline.shortname.length) == 0\"\n                    >\n                    <b-container>\n                        <b-row>\n                            <b-col cols=\"3\">{{text.studyline_name}}</b-col>\n                            <b-col>\n                                <b-form-input v-model=\"create.studyline.name\" :placeholder=\"text.studyline_name_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"3\">{{text.studyline_shortname}}</b-col>\n                            <b-col>\n                            <b-form-input \n                                v-model=\"create.studyline.shortname\" \n                                :placeholder=\"text.studyline_shortname_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"3\">{{text.studyline_color}}</b-col>\n                            <b-col>\n                                <input type=\"color\" v-model=\"create.studyline.color\" />\n                                <!-- hsluv-picker v-model=\"create.studyline.color\" horizontal displaysize=\"175\" ></hsluv-picker -->\n                            </b-col>\n                        </b-row>\n                    </b-container>\n                </b-modal>\n                <b-modal \n                    :id=\"'modal-edit-studyline-'+value.id\" \n                    size=\"lg\" \n                    ok-variant=\"primary\"\n                    :title=\"text.studyline_edit\"\n                    @ok=\"editLineFinish()\"\n                    :ok-disabled=\"Math.min(edit.studyline.data.name.length,edit.studyline.data.shortname.length) == 0\"\n                    >\n                    <b-container>\n                        <b-row>\n                            <b-col cols=\"3\">{{ text.studyline_name}}</b-col>\n                            <b-col>\n                                <b-form-input \n                                    v-model=\"edit.studyline.data.name\" \n                                    :placeholder=\"text.studyline_name_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"3\">{{ text.studyline_shortname}}</b-col>\n                            <b-col>\n                            <b-form-input \n                                v-model=\"edit.studyline.data.shortname\" \n                                :placeholder=\"text.studyline_shortname_ph\"></b-form-input>\n                            </b-col>\n                        </b-row>\n                        <b-row>\n                            <b-col cols=\"3\">{{ text.studyline_color}}</b-col>\n                            <b-col>\n                                <input type=\"color\" v-model=\"edit.studyline.data.color\" />\n                            </b-col>\n                        </b-row>\n                    </b-container>\n                </b-modal>\n            </div>\n            `\n        });\n\n\n       /*\n        * T-STUDYLINE-HEADER\n        */\n       Vue.component('t-studyline-heading', {\n            props: {\n                value : {\n                    type: Object, // Studyline\n                    default: function(){ return {};},\n                },\n                layers: {\n                    type: Number,\n                    default: 1,\n                },\n            },\n            data() {\n                return {\n                    layerHeights: {}\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                \n            },\n            methods: {\n                onLineHeightChange(lineid,layerid,newheight){\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.main && lineid == this.value.id){\n                        const items = document.querySelectorAll(\n                            `.t-studyline-slot-0[data-studyline='${this.value.id}']`);\n                        \n                        // determine the height of all the lines and add them up.\n                        let heightSum = 0;\n                        items.forEach((el) => {\n                            // 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.main.style.height = heightStyle;\n                    }\n                }\n            },\n            template: `\n            <div class=\"t-studyline t-studyline-heading \" \n                :data-studyline=\"value.id\" ref=\"main\"\n                ><div class=\"t-studyline-handle\" :style=\"'background-color: ' + value.color\"></div>\n                <div class=\"t-studyline-title\">\n                    <abbr v-b-tooltip.hover :title=\"value.name\">{{ value.shortname }}</abbr>\n                </div>\n            </div>\n            `,\n        });\n        \n        /*\n        * T-STUDYLINE (Used only for study line edit mode)\n        */\n        Vue.component('t-studyline-edit', {\n            props: {\n                value : {\n                    type: Object, // Studyline\n                    default: function(){ return {};},\n                }          \n           },\n            data() {\n                return {\n                };\n            },\n            computed: {\n                deletable() {\n                    // Check if all the slots are empty\n                    const slots = this.value.slots;\n                    if(Array.isArray(slots)){\n                        let count = 0;\n                        for(let i = 0; i < slots.length; i++) {\n                            if(Array.isArray(slots[i].competencies)){\n                                count += slots[i].competencies.length;\n                            }\n                            if(Array.isArray(slots[i].filters)){\n                                count += slots[i].filters.length;\n                            }\n                        }\n                        return (count == 0);\n                    } else {\n                        return false;\n                    }\n                }\n            },\n            methods: {\n                onEdit() {\n                    this.$emit('edit',this.value);\n                },\n                onDelete() {\n                    this.$emit('delete',this.value);\n                },\n\n            },\n            template: `\n            <div :class=\"'t-studyline '\" > \n                <div class=\"t-studyline-handle\" :style=\"'background-color: ' + value.color\"></div>\n                <div class=\"t-studyline-title\">\n                    <div>\n                        <i class='fa fa-arrows text-primary'></i>\n                        <abbr v-b-tooltip.hover :title=\"value.name\">{{ value.shortname }}</abbr>\n                    </div>\n                </div>\n                <div class='t-studyline-editmode-content'>\n                    <slot></slot>\n                </div>\n                <div class='controlbox'>\n                    <template v-if='editable || deletable'>\n                    <span class='control editable'>\n                        <a href='#' @click='onEdit'><i class='fa fa-pencil'></i></a>\n                    </span>\n                    <span class='control deletable'>\n                        <a v-if='deletable' href='#' @click='onDelete'><i class='text-danger fa fa-trash'></i></a>\n                    </span>\n                    </template>\n                </div>\n            </div>\n            `,\n        });\n\n        /*\n         * During a redisign it was decided to have the studyline still get the entire array as a value,\n         * even though it only shows one drop slot for the layer it is in. This is to make repainting easier, \n         * since we modify the array for the layer we handle. FIXME: Make this less weird\n         */\n        Vue.component('t-studyline-slot', {\n            props: {\n                type : {\n                    type: String,\n                    default: 'gradable',\n                },\n                slotindex : {\n                    type: Number,\n                    default: '',\n                },\n                line : {\n                    type: Object,\n                    default(){ return null;},\n                },\n                layer : {\n                    type: Number,\n                },\n                value: {\n                    type: Array, // dict with layer as index\n                    default(){ return [];},\n                },\n                plan: {\n                    type: Object, // Studyplan data\n                    default(){ return null;},\n                },\n                page: {\n                    type: Object, // Studyplan data\n                    default(){ return null;},\n                },\n                period: {\n                    type: Object, // Studyplan data\n                    default(){ return null;},\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.main){\n                            const size = self.$refs.main.getBoundingClientRect();\n                            \n                            ItemEventBus.$emit('lineHeightChange', self.line.id, self.layer, size.height);\n                        }\n                    }).observe(self.$refs.main);\n                }\n            },\n            unmounted() {\n                if(this.resizeListener) {\n                    this.resizeListener.disconnect();\n                }\n            },\n            computed: {\n                slotkey(){\n                    return `${this.type}'-'${this.line.id}-${this.slotindex}-${this.layer}`;\n                },\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                listtype() {\n                    return this.type;\n                },\n                dragacceptlist(){\n                    if(this.type == \"gradable\"){\n                        return [\"course\", \"gradable-item\"];\n                    } else {\n                        return [\"filter\", \"filter-item\"];\n                    }\n                },\n                courseHoverDummy(){\n                    return {course: this.hover.component};\n                },\n                current(){\n                    if( this.period && this.period.startdate && this.period.enddate){\n                        const now = new Date();\n                        const pstart = new Date(this.period.startdate);\n                        const pend = new Date(this.period.enddate);\n                        return (now >= pstart && now < pend);\n                    }\n                    else {\n                        return false;\n                    }\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            },\n            data() {\n                return {\n                    text: strings.course_timing,\n                    resizeListener: null,\n                    hover: { \n                        component:null,\n                        type: null,\n                    },\n                    datechanger: {\n                        coursespan: null,\n                        periodspan: null,\n                        default: false,\n                        defaultchoice: false,\n                        hidewarn: false,\n                    }\n                };\n            },\n            methods: {\n                onDrop(event) {\n                    this.hover.component = null;\n                    this.hover.type = null;\n\n                    const self = this;\n                    if(event.type.item) {\n                        let item = event.data;\n                        \n                        // To avoid weird visuals with the lines,\n                        // we add the item to the proper place in the front-end first\n                        item.layer = this.layer;\n                        item.slot = this.slotindex;\n                        self.value.push(item);\n                        self.$emit(\"input\",self.value);\n\n                        // then on the next tick, we inform the back end\n                        // Since moving things around has never been unsuccessful, unless you have other problems,\n                        // it's better to have nice visuals.\n                        self.relocateStudyItem(item).done(()=>{\n                            if(this.$refs.timingChecker){\n                                this.$refs.timingChecker.validate_course_period();\n                            }\n                        });\n                    }\n                    else if(event.type.component){\n\n                        if(event.type.type == \"course\"){\n                            call([{\n                                methodname: 'local_treestudyplan_add_studyitem',\n                                args: { \n                                    \"line_id\": self.line.id,\n                                    \"slot\" : self.slotindex,\n                                    \"layer\" : self.layer,\n                                    \"type\": 'course',\n                                    \"details\": {\n                                        \"competency_id\": null,\n                                        'conditions':'',\n                                        'course_id':event.data.id,\n                                        'badge_id':null,\n                                        'continuation_id':null,\n                                    }\n                                }\n                            }])[0].done((response) => {\n                                let item = response;\n                                self.relocateStudyItem(item).done(()=>{\n                                    self.value.push(item);\n                                    self.$emit(\"input\",self.value);\n\n                                    // call the validate period function on next tick,\n                                    // since it paints the item in the slot first\n                                    this.$nextTick(() => {\n                                        if(this.$refs.timingChecker){\n                                            this.$refs.timingChecker.validate_course_period();\n                                        }\n                                    });\n                                });\n                            }).fail(notification.exception);\n                        }                 \n                        else  if(event.type.type == \"filter\") {\n                            call([{\n                                methodname: 'local_treestudyplan_add_studyitem',\n                                args: { \n                                    \"line_id\": self.line.id,\n                                    \"slot\" : self.slotindex,\n                                    \"type\": event.data.type,\n                                    \"details\":{\n                                        \"badge_id\": event.data.badge?event.data.badge.id:undefined,\n                                    }\n                                }\n                            }])[0].done((response) => {\n                                let item = response;\n                                self.relocateStudyItem(item).done(()=>{\n                                    self.value.push(item);\n                                    self.$emit(\"input\",self.value);                    \n                                });\n                            }).fail(notification.exception);\n                        } \n                    }\n                },\n                onCut(event) {\n                    const self=this;\n                    let id = event.data.id;\n                    for(let i = 0; i < self.value.length; i++){ \n                        if(self.value[i].id == id){ \n                            self.value.splice(i, 1); i--; \n                            break; // just remove one\n                        }\n                    }\n                    // Do something to signal that this item has been removed\n                    this.$emit(\"input\",this.value);\n                },\n                relocateStudyItem(item){\n                    const iteminfo = {'id': item.id, 'layer': this.layer, 'slot': this.slotindex, 'line_id': this.line.id};\n                    return call([{\n                        methodname: 'local_treestudyplan_reorder_studyitems',\n                        args: { 'items': [iteminfo] } // function was designed to relocate multiple items at once, hence the array\n                    }])[0].fail(notification.exception);  \n                },\n                onDragEnter(event){\n                    this.hover.component = event.data;\n                    this.hover.type = event.type;\n                },\n                onDragLeave(){\n                    this.hover.component = null;\n                    this.hover.type = null;\n                },\n                maxSpan(){\n                    // Determine the maximum span for components in this slot\n                    // Used for setting the max in the timing adjustment screen (s)\n                    // And for checking the filter types\n\n                    // Assume this slot is first one available\n                    let freeIndex = this.slotindex;\n                    // Determine last free slot following this one in the layer\n                    for(let i = this.slotindex + 1; i <= this.page.periods; i++){\n                        if(this.line.slots && this.line.slots[i] && this.line.slots[i].competencies){\n                            const l = this.line.slots[i].competencies;\n                            const f = this.line.slots[i-1].filters; // next filter is in the same slot\n                            if(l[this.layer] || f[this.layer]) {\n                                // slot is busy in this layer.\n                                break;\n                            } else {\n                                freeIndex = i;\n                            }\n                        } else {\n                            break; // stop processing\n                        }\n                    }\n                    // calculate span from that\n                    return freeIndex - this.slotindex + 1;\n\n                },\n                makeType(item){\n                    return {\n                        item: true,\n                        component: false,\n                        span: item.span,\n                        type: this.type,\n                    };\n                },\n                checkType(type) {\n                    if(type.type == this.type){\n                        if(type == 'filter'){\n                             return true;\n                        } else if(type.span <= this.maxSpan()){\n                            return true;\n                        } else {\n                            return false;\n                        }\n                    } else {\n                        return false;\n                    }\n                }\n            },\n            template: `\n            <div :class=\"'t-studyline-slot '+type + ' t-studyline-slot-'+slotindex + ' ' + ((slotindex==0)?' t-studyline-firstcolumn ':' ') \n                         + (current?'current ':' ')\"\n                :data-studyline=\"line.id\" ref=\"main\"\n                :style='spanCss'\n                ><drag v-if=\"item\"\n                    \n                    :key=\"item.id\" \n                    class=\"t-slot-item\" \n                    :data=\"item\" \n                    :type=\"makeType(item)\" \n                    @cut=\"onCut\"\n                        ><t-item v-model=\"item\" :plan=\"plan\" :page='page' :period='period' :maxspan='maxSpan()'></t-item\n                        ></drag\n                ><drop v-else\n                    :class=\"'t-slot-drop '+type + (layer > 0?' secondary':' primary')\"\n                    :accepts-type=\"checkType\"\n                    @drop=\"onDrop\"\n                    mode=\"cut\"\n                    @dragenter=\"onDragEnter\"\n                    @dragleave=\"onDragLeave\"\n                ><template v-if=\"hover.component\">\n                        <div v-if=\"hover.type.item\" \n                            class=\"t-slot-item feedback\" \n                            :key=\"hover.component.id\"\n                            ><t-item v-model=\"hover.component\" dummy></t-item\n                            ></div\n                        ><div v-else-if=\"hover.type.type == 'gradable'\" \n                            class=\"t-slot-item feedback\" \n                            :key=\"'course-'+hover.component.id\"\n                            ><t-item-course v-model=\"courseHoverDummy\"></t-item-course></div\n                        ><div v-else-if=\"hover.type.type == 'filter'\" \n                            class=\"t-slot-item feedback\" \n                            key=\"tooldrop\"\n                            ><t-item-junction    v-if=\"hover.component.type == 'junction'\" ></t-item-junction\n                            ><t-item-start       v-else-if=\"hover.component.type == 'start'\"    ></t-item-start\n                            ><t-item-finish      v-else-if=\"hover.component.type == 'finish'\"   ></t-item-finish\n                            ><t-item-badge       v-else-if=\"hover.component.type == 'badge'\"    ></t-item-badge\n                        ></div\n                        ><div v-else \n                            class=\"t-slot-item feedback\"\n                            :key=\"hover.type\">--{{ hover.type }}--</div\n                    ></template\n                ></drop>\n                <t-item-timing-checker hidden\n                    v-if=\"item && item.course\"\n                    ref=\"timingChecker\"\n                    :maxspan=\"maxSpan()\"\n                    :page=\"page\"\n                    :period=\"period\"\n                    v-model=\"item\"\n                    ></t-item-timing-checker>\n            </div>\n            `,\n        });\n\n\n        Vue.component('t-item-timing-checker', {\n            props: {\n                value: {\n                    type: Object, // t-item model\n                },\n                page: {\n                    type: Object, // Studyplan data\n                },\n                period: {\n                    type: Object, // Studyplan data\n                },\n                maxspan: {\n                    type: Number,\n                },\n                hidden: {\n                    type: Boolean,\n                    default: false,\n                }\n            },\n            computed: {\n                endperiod() {\n                    const endperiodnr = Math.min(this.page.periods,this.period.period + (this.value.span - 1));\n                    return this.page.perioddesc[endperiodnr-1];\n                },\n                course_period_matches() {\n                    const self=this;\n                    if(self.value && self.value.type == 'course'){\n                        self.datechanger.coursespan = datespaninfo(self.value.course.startdate,self.value.course.enddate);\n                        self.datechanger.periodspan = datespaninfo(self.period.startdate,self.endperiod.enddate);\n                        if( self.datechanger.coursespan.first.getTime() == self.datechanger.periodspan.first.getTime() \n                            && self.datechanger.coursespan.last.getTime() == self.datechanger.periodspan.last.getTime()  ){\n                            return true;\n                        }\n                        else {\n                            return false;\n                        }\n                    } else {\n                        debug.warn(\"Timing thing not proper configured\",self.value,self.period,self.maxspan);\n                        return false;\n                    }\n                },\n            },\n            data() {\n                return {\n                    // Create random id to avoid opening the wrong modals\n                    id: Math.floor(Math.random() * Date.now()).toString(16),\n                    text: strings.course_timing,\n                    datechanger: {\n                        coursespan: null,\n                        periodspan: null,\n                        globals: datechanger_globals,\n                    }\n                };\n            },\n            methods: {\n                \n                validate_course_period(force) {\n                    const self = this;\n                    \n                    debug.info(\"Validating course and period\");\n                    if(!(self.course_period_matches)){\n                        debug.info(\"Course timing does not match period timing\");\n\n                        if(self.value.course.canupdatecourse){\n                            if(!self.hidden || !self.datechanger.globals.default){\n                                // Periods do not match, pop up the date change request \n                                this.$bvModal.show('t-course-timing-matching-'+this.id);\n                            } else if (self.datechanger.globals.defaultvalue){\n                                // go for it without asking\n                                self.change_course_period();\n                            }\n                        }\n                        else {\n                            // user is not able to change course timing - show a warning\n                            if(!self.hidden || !self.datechanger.globals.hidewarn){\n                                this.$bvModal.show('t-course-timing-warning-'+this.id);\n                            }\n                        }\n                    }\n                    else {\n                        debug.info(\"Course timing matches period\",self.datechanger);\n                    }\n                },\n                change_course_period() {\n                    const self=this;\n                    // Save the state\n                    if(self.datechanger.globals.default){\n                        self.datechanger.globals.defaultvalue = true;\n                    }\n                    return call([{\n                        methodname: 'local_treestudyplan_course_period_timing',\n                        args: { period_id: self.period.id, \n                                course_id: this.value.course.id,\n                                span: this.value.span,\n                            }\n                    }])[0].fail(notification.exception).done((response) => {\n                        self.value.course.startdate = response.startdate;\n                        self.value.course.enddate = response.enddate;\n                        self.value.course.timing = response.timing;\n                        self.$emit(\"input\",self.value);\n                    });\n                },\n                change_span(span) {\n                    const self=this;\n                    return call([{\n                        methodname: 'local_treestudyplan_set_studyitem_span',\n                        args: { id: self.value.id,\n                                span: span\n                            }\n                    }])[0].fail(notification.exception).done((response) => {\n                        self.value.span = response.span;\n                        self.$emit('input',self.value);\n                        self.$nextTick(() => {\n                            self.validate_course_period();\n                        });\n                    } );  \n                },\n                format_duration(dsi){\n                    let s = \"\";\n                    if(dsi.years == 1){ s += `1 ${this.text.year}, `;}\n                    else if(dsi.years > 1){ s += `${dsi.years} ${this.text.years}, `;}\n                    if(dsi.weeks == 1){ s += `1 ${this.text.week}, `;}\n                    else if(dsi.weeks > 1){ s += `${dsi.weeks} ${this.text.weeks}, `;}\n                    if(dsi.days == 1){ s += `1 ${this.text.day}, `;}\n                    else if(dsi.days > 1){ s += `${dsi.days} ${this.text.days}, `;}\n\n                    return s.toLocaleLowerCase();\n                },\n            },\n            // To avoid the span creeping in the dom where it shouldn't, set display to none if it is hidden\n            // This does not affect the modals, which are rendered outside of this element when needed\n            template: `\n            <div :class=\"'t-item-timing-checker'\" :style=\"hidden?'display: none ':''\">\n                <template v-if=\"!hidden\" >\n                    <span class=\"mr-1\" v-if=\"course_period_matches\">\n                        <i  class=\"text-success fa fa-calendar-check-o\"\n                            v-b-tooltip.hover.topright :title=\"text.timing_ok\"\n                        ></i\n                        ><i class=\"fa fa-question-circle text-black-50\"\n                            style=\"font-size: 0.8em; top: -0.3em; position: relative;\"\n                            v-b-tooltip.hover.topright :title=\"(course_period_matches)?text.timing_ok:text.timing_off\"\n                        ></i>\n                    </span>\n                    <span class=\"mr-1\" v-else>\n                        <a  href='#' @click=\"validate_course_period()\" class=\"text-warning\"\n                            ><i class=\"fa fa-calendar-times-o\" \n                                v-b-tooltip.hover.topright :title=\"text.timing_off\"\n                            ></i\n                            ><i class=\"fa fa-question-circle text-black-50\"\n                                style=\"font-size: 0.8em; top: -0.3em; position: relative;\"\n                                v-b-tooltip.hover.topright :title=\"text.timing_off\"\n                            ></i\n                        ></a>\n                    </span>\n                    <span class=\"ml-1\"\n                        >{{\n                            text.periodspan\n                        }}<b-form-select \n                            class=\"\"\n                            size=\"sm\" @change=\"change_span\" v-model=\"value.span\">\n                            <b-form-select-option v-for=\"(n,i) in maxspan\" :value='n'\n                            >{{ n }}</b-form-select-option>\n                        </b-form-select\n                        >{{ \n                            (value.span == 1)?text.period.toLowerCase():text.periods.toLowerCase() \n                        }}<i\n                            class=\"fa fa-question-circle text-black-50\" \n                            style=\"font-size: 0.8em; top: -0.3em; position: relative;\"\n                            v-b-tooltip.hover :title=\"text.periodspan_desc\"></i>\n                    </span>\n                </template>\n                <b-modal \n                    :id=\"'t-course-timing-matching-'+this.id\" \n                    size=\"lg\" \n                    :title=\"text.title\"\n                    @ok=\"change_course_period\"\n                    :ok-title=\"text.yes\"\n                    ok-variant=\"danger\"\n                    :cancel-title=\"text.no\"\n                    cancel-variant=\"primary\"                    \n                    >\n                    <b-container v-if=\"datechanger.coursespan && datechanger.periodspan && value && value.course\">\n                        <b-row><b-col cols=\"12\">{{ text.desc }}</b-col></b-row>\n                        <b-row><b-col cols=\"12\"><div class=\"generalbox alert alert-warning\">{{ text.question }}</div></b-col></b-row>\n                        <b-row>\n                            <b-col cols=\"6\">\n                                <h3> {{ text.course }} </h3>\n                                <p><b>{{ value.course.fullname }}</b></p>\n                                <p><b>{{ value.course.shortname }}</b></p>\n                                <p>{{ datechanger.coursespan.formatted.first}} - {{ datechanger.coursespan.formatted.last}}</p>\n                                <p><b>{{ text.duration }}</b><br>\n                                {{ format_duration(datechanger.coursespan)}}</p>\n                            </b-col>\n                            <b-col cols=\"6\">\n                                <h3> {{ text.period }} </h3>\n                                <p><b>{{ period.fullname }}</b><b v-if=\"value.span > 1\"> - {{ endperiod.fullname }}</b></p>\n                                <p><b>{{ period.shortname }}</b><b v-if=\"value.span > 1\"> - {{ endperiod.shortname }}</b></p>\n                                <p>{{ datechanger.periodspan.formatted.first}} - {{ datechanger.periodspan.formatted.last}}</p>\n                                <p><b>{{ text.duration }}</b><br>\n                                {{ format_duration(datechanger.periodspan)}}</p>\n                            </b-col>\n                        </b-row>\n                        <b-row v-if='hidden'><b-col cols=\"12\">\n                            <b-form-checkbox type=\"checkbox\" v-model=\"datechanger.globals.default\">{{ text.rememberchoice }}</b-form-checkbox>\n                        </b-col></b-row>\n                    </b-container>\n                </b-modal>\n                <b-modal \n                    :id=\"'t-course-timing-warning-'+this.id\" \n                    size=\"lg\" \n                    ok-variant=\"primary\"\n                    :title=\"text.title\"\n                    :ok-title=\"text.yes\"\n                    ok-only\n                    >\n                    <b-container v-if=\"datechanger.coursespan && datechanger.periodspan && value && value.course\">\n                        <b-row><b-col cols=\"12\">{{ text.desc }}</b-col></b-row>\n                        <b-row><b-col cols=\"12\"><div class=\"generalbox alert alert-warning\">{{ text.warning }}</div></b-col></b-row>\n                        <b-row>\n                            <b-col cols=\"6\">\n                                <h3> {{ text.course }} </h3>\n                                <p><b>{{ value.course.fullname }}</b></p>\n                                <p><b>{{ value.course.shortname }}</b></p>\n                                <p>{{ datechanger.coursespan.formatted.first}} - {{ datechanger.coursespan.formatted.last}}</p>\n                                <p><b>{{ text.duration }}</b><br>\n                                {{ format_duration(datechanger.coursespan)}}</p>\n                            </b-col>\n                            <b-col cols=>\"6\">\n                                <h3> {{ text.period }} </h3>\n                                <p><b>{{ period.fullname }}</b><b v-if=\"value.span > 1\"> - {{ endperiod.fullname }}</b></p>\n                                <p><b>{{ period.shortname }}</b><b v-if=\"value.span > 1\"> - {{ endperiod.shortname }}</b></p>\n                                <p>{{ datechanger.periodspan.formatted.first}} - {{ datechanger.periodspan.formatted.last}}</p>\n                                <p><b>{{ text.duration }}</b><br>\n                                {{ format_duration(datechanger.periodspan)}}</p>\n                            </b-col>\n                        </b-row>\n                        <b-row v-if='hidden'><b-col cols=\"12\">\n                            <b-form-checkbox type=\"checkbox\" v-model=\"datechanger.globals.hidewarn\">{{ text.hidewarning }}</b-form-checkbox>\n                        </b-col></b-row>\n                    </b-container>\n                </b-modal>\n            </span>\n            `,\n        });\n\n\n        Vue.component('t-item', {\n            props: {\n                value :{\n                    type: Object,\n                    default(){ return null;},\n                },\n                dummy :{\n                    type: Boolean,\n                    default() { return false;},\n                },\n                plan: {\n                    type: Object, // Studyplan page\n                    default() { return null;},\n                },\n                page: {\n                    type: Object, // Studyplan page\n                    default() { return null;},\n                },\n                period: {\n                    type: Object, // Studyplan page\n                    default() { return null;},\n                },\n                maxspan: {\n                    type: Number,\n                    default() { return 0;},\n                },                  \n            },\n            data() {\n                return {\n                    dragLine: null,\n                    dragEventListener: null,\n                    deleteMode: false,\n                    condition_options: string_keys.conditions,\n                    text: strings.item_text,\n                    showContext: false,\n                    lines: [],\n                };\n            },\n            methods: {\n                dragStart(event){\n                    // Add line between start point and drag image\n                    this.deleteMode = false;\n                    let start = document.getElementById('studyitem-'+this.value.id);\n                    let dragelement= document.getElementById('t-item-cdrag-'+this.value.id);\n                    dragelement.style.position = 'fixed';\n                    dragelement.style.left = event.position.x+'px';\n                    dragelement.style.top = event.position.y+'px';\n                    this.dragLine = new SimpleLine(start,dragelement,{\n                            color: \"#777\",\n                            gravity: {\n                                start: LINE_GRAVITY,\n                                end: LINE_GRAVITY,\n                            },\n                        });\n                    // Add separate event listener to reposition mouse move\n                    document.addEventListener(\"mousemove\",this.onMouseMove);\n                },\n                dragEnd(){\n                    if(this.dragLine !== null) {\n                        this.dragLine.remove();\n                    }\n                    let dragelement = document.getElementById('t-item-cdrag-'+this.value.id);\n                    dragelement.style.removeProperty('left');\n                    dragelement.style.removeProperty('top');\n                    dragelement.style.removeProperty('position');\n                    document.removeEventListener(\"mousemove\",this.onMouseMove);\n                },\n                onMouseMove: function(event){\n                    let dragelement = document.getElementById('t-item-cdrag-'+this.value.id);\n                    dragelement.style.position = 'fixed';\n                    dragelement.style.left = event.clientX+'px';\n                    dragelement.style.top = event.clientY+'px';\n                    // line will follow automatically\n                },\n                onDrop(event){\n                    let from_id = event.data.id;\n                    let to_id = this.value.id;\n                    this.redrawLines();\n                    call([{\n                        methodname: 'local_treestudyplan_connect_studyitems',\n                        args: { 'from_id': from_id, 'to_id': to_id }\n                    }])[0].done((response)=>{\n                        let conn = {'id': response.id, 'from_id': response.from_id, 'to_id': response.to_id};\n                        ItemEventBus.$emit(\"createdConnection\",conn);\n                        this.value.connections.in.push(conn);\n                    }).fail(notification.exception);\n                },\n                redrawLine(conn){\n                    const lineColor = \"var(--success)\";\n                    const start = document.getElementById(`studyitem-${conn.from_id}`);\n                    const 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                    // create a new line if the start and finish items are visible\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                        });\n                    }\n\n                },\n                deleteLine(conn){\n                    const self = this;\n                    call([{\n                        methodname: 'local_treestudyplan_disconnect_studyitems',\n                        args: { 'from_id': conn.from_id, 'to_id': conn.to_id }\n                    }])[0].done((response)=>{\n                        if(response.success){\n                            this.removeLine(conn);\n                            // send disconnect event on message bus, so the connection on the other end can delete it too\n                            ItemEventBus.$emit(\"connectionDisconnected\",conn);\n                            // Remove connection from our outgoing list\n                            let index = self.value.connections.out.indexOf(conn);\n                            self.value.connections.out.splice(index, 1);\n                        }\n                    }).fail(notification.exception);\n                },\n                highlight(conn){\n                    if(this.lines[conn.to_id]){\n                        this.lines[conn.to_id].setConfig({color:\"var(--danger)\",});\n                    }\n                },\n                normalize(conn){\n                    if(this.lines[conn.to_id]){\n                        this.lines[conn.to_id].setConfig({color:\"var(--success)\",});\n                    }\n                },\n                updateItem() {\n                    call([{\n                        methodname: 'local_treestudyplan_edit_studyitem',\n                        args: { 'id': this.value.id,\n                                'conditions': this.value.conditions, \n                                'continuation_id': this.value.continuation_id,}\n                    }])[0].fail(notification.exception);\n                },\n                doShowContext(event) {\n                    if(this.hasContext){\n                        this.showContext=true;\n                        event.preventDefault();\n                    }\n                },\n                redrawLines(){\n                    for(let i in this.value.connections.out){\n                        let conn = this.value.connections.out[i];\n                        this.redrawLine(conn);\n                    }\n                },\n\n                // EVENT LISTENERS\n                onCreatedConnection(conn){\n                    if(conn.from_id == this.value.id){\n                        this.value.connections.out.push(conn);\n                        this.redrawLine(conn);\n                    }\n                },\n                // Listener for the signal that a connection was removed by the outgoing item\n                onRemovedConnection(conn){\n                    for(let i in this.value.connections.in){\n                        let c_in = this.value.connections.in[i];\n                        if(conn.id == c_in.id){\n                            self.value.connections.out.splice(i, 1);\n                        }\n                    }\n                },\n                // Listener for reposition events\n                // When an item in the list is repositioned, all lines need to be redrawn\n                onRePositioned(){\n                    for(let i in this.value.connections.out){\n                        let conn = this.value.connections.out[i];\n                        this.redrawLine(conn);\n                    }\n                },\n                // When an item is disPositioned - (temporarily) removed from the list,\n                // all connections need to be deleted.\n                onDisPositioned(re_id){\n                    for(let i in this.value.connections.out){\n                        let conn = this.value.connections.out[i];\n                        if(conn.to_id == re_id){\n                            this.removeLine(conn);\n                        } \n                    }\n                },\n\n                // When an item is deleted \n                // all connections to/from that item need to be cleaned up\n                onItemDeleted(item_id){\n                    const self = this;\n                    for(const i in this.value.connections.out){\n                        let conn = this.value.connections.out[i];\n                        if(conn.to_id == item_id){\n                            self.removeLine(conn);\n                            self.value.connections.out.splice(i, 1);                        \n                        } \n                    }\n                    for(const i in this.value.connections.in){\n                        let conn = this.value.connections.in[i];\n                        if(conn.from_id == item_id){\n                            self.value.connections.out.splice(i, 1);                        \n                        } \n                    }                \n                },\n\n                onRedrawLines(){\n                    this.redrawLines();\n                },\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 ['junction','finish'].includes(this.value.type);\n                }\n            },\n            created(){\n                // Add event listeners on the message bus\n                // But only if not in \"dummy\" mode - mode which is used for droplist placeholders\n                // Since an item is \"fully made\" with all references, not specifying dummy mode really messes things up\n                if(!this.dummy){\n\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('createdConnection', this.onCreatedConnection);\n                    // Listener for the signal that a connection was removed by the outgoing item\n                    ItemEventBus.$on('removedConnection', this.onRemovedConnection);\n                    // Listener for reposition events\n                    // When an item in the list is repositioned, all lines need to be redrawn\n                    ItemEventBus.$on('rePositioned', this.onRePositioned);\n                    // When an item is disPositioned - (temporarily) removed from the list,\n                    // all connections need to be deleted.\n                    ItemEventBus.$on('disPositioned', this.onDisPositioned);\n                    // When an item is deleted \n                    // all connections to/from that item need to be cleaned up\n                    ItemEventBus.$on('itemDeleted', this.onItemDeleted);\n                    ItemEventBus.$on('redrawLines', this.onRedrawLines);\n\n\n                }\n            },\n            mounted(){\n                // Initialize connection lines when mounting\n                // But only if not in \"dummy\" mode - mode which is used for droplist placeholders\n                // Since an item is \"fully made\" with all references, not specifying dummy mode really messes things up\n\n                if(!this.dummy)\n                {\n                    this.redrawLines();\n                    setTimeout(()=>{\n                        ItemEventBus.$emit(\"rePositioned\",this.value.id);\n                    },10);\n                }\n            },\n            beforeDestroy(){\n                if(!this.dummy) {\n                    for(let i in this.value.connections.out){\n                        let conn = this.value.connections.out[i];\n                        this.removeLine(conn);\n                    }\n                    ItemEventBus.$emit(\"disPositioned\",this.value.id);\n\n                    // Remove event listeners\n                    ItemEventBus.$off('createdConnection', this.onCreatedConnection);\n                    ItemEventBus.$off('removedConnection', this.onRemovedConnection);\n                    ItemEventBus.$off('rePositioned', this.onRePositioned);\n                    ItemEventBus.$off('disPositioned', this.onDisPositioned);\n                    ItemEventBus.$off('itemDeleted', this.onItemDeleted);\n                    ItemEventBus.$off('redrawLines', this.onRedrawLines);\n                }\n            },\n            beforeUpdate(){\n            },\n            updated(){\n                if(!this.dummy) {\n                    this.redrawLines();\n                }\n            },\n            template: `\n            <div class=\"t-item-base\" :id=\"'studyitem-'+value.id\">\n                <t-item-course      v-model=\"value\"  v-if=\"value.type == 'course'\"\n                    :plan='plan' :page='page' :period='period' :maxspan='maxspan'></t-item-course>\n                <t-item-junction    v-model=\"value\"  v-if=\"value.type == 'junction'\"     ></t-item-junction>\n                <t-item-start       v-model=\"value\"  v-if=\"value.type == 'start'\"        ></t-item-start>\n                <t-item-finish      v-model=\"value\"  v-if=\"value.type == 'finish'\"       ></t-item-finish>\n                <t-item-badge       v-model=\"value\"  v-if=\"value.type == 'badge'\"        ></t-item-badge>\n                <t-item-invalid     v-model=\"value\"  v-if=\"value.type == 'invalid'\"      ></t-item-invalid>\n                <drop v-if='!dummy && hasConnectionsIn' accepts-type=\"linestart\"\n                    :id=\"'t-item-cend-'+value.id\"\n                    class=\"t-item-connector-end\"\n                    mode=\"copy\"\n                    @drop=\"onDrop\"\n                    ><svg width='5px' height='10px'><rect ry=\"1px\" rx=\"1px\" y=\"0px\" x=\"0px\" height=\"10px\" width=\"5px\"/></svg></drop>\n                <drag v-if='!dummy && hasConnectionsOut' type=\"linestart\"\n                    :id=\"'t-item-cstart-'+value.id\"\n                    :class=\"'t-item-connector-start ' + ((deleteMode&&value.connections.out.length)?'deleteMode':'')\"\n                    :data=\"value\"\n                    @dragstart=\"dragStart\"\n                    @dragend=\"dragEnd\"\n                    @click=\"deleteMode = (value.connections.out.length)?(!deleteMode):false\"\n                    >\n                    <svg  width='5px' height='10px'><rect ry=\"1px\" rx=\"1px\" y=\"0px\" x=\"0px\" height=\"10px\" width=\"5px\"/></svg>\n                    <template v-slot:drag-image=\"{data}\"> <i :id=\"'t-item-cdrag-'+value.id\" class=\"fa\"></i>\n                    </template>\n                </drag>\n                <div class=\"deletebox\" v-if=\"deleteMode && value.connections.out.length > 0\"\n                    >\n                    <a v-for=\"conn in value.connections.out\"\n                        @click=\"deleteLine(conn)\"\n                        @mouseenter=\"highlight(conn)\"\n                        @mouseleave=\"normalize(conn)\"\n                        class=\"t-connection-delete text-danger\"\n                        :title=\"conn.id\">\n                        <i class=\"fa fa-trash\"></i>\n                    </a>\n                </div>\n                <a  v-if=\"hasContext\" class=\"t-item-config\"\n                    v-b-modal=\"'t-item-config-'+value.id\" href=\"#\" @click.prevent=\"\"><i  class=\"fa fa-gear\"></i></a>\n                <b-modal no-body class='t-item-contextview'\n                    :id=\"'t-item-config-'+value.id\"\n                    :title=\"text['item_configuration']\"\n                    scrollable\n                    ok-only\n                >\n                    <b-form-group\n                        :label=\"text.select_conditions\"\n                    >\n                        <b-form-select size=\"sm\" \n                            @input=\"updateItem\" \n                            v-model=\"value.conditions\" \n                            :options=\"condition_options\"\n                        ></b-form-select>\n                    </b-form-group>\n                </b-modal>\n            </div>\n            `,\n        });\n\n        Vue.component('t-item-invalid', {\n            props: {\n                'value' :{\n                    type: Object,\n                    default: function(){ return null;},\n                },\n            },\n            data() {\n                return {\n                    text: strings.invalid,\n                };\n            },\n            methods: {\n            },\n            template: `\n            <b-card no-body class=\"t-item-invalid\">\n                <b-row no-gutters>\n                    <b-col md=\"1\">\n                        <span class=\"t-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            `,\n        });\n\n        Vue.component('t-item-course', {\n            props: {\n                value:{\n                    type: Object,\n                    default(){ return null;},\n                },\n                plan:{\n                    type: Object,\n                    default(){ return null;},\n                },\n                page: {\n                    type: Object, // PAge data\n                    default() { return null;}\n                },\n                period: {\n                    type: Object, // Period data\n                    default() { return null;}\n                },\n                maxspan: {\n                    type: Number,\n                    default() { return 0;}\n                },                \n            },\n            data() {\n                return {\n                    condition_options: string_keys.conditions,\n                    text: strings.item_course_text,\n                };\n            },\n            computed: {\n                useItemConditions() {\n                    if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useItemConditions !== undefined){\n                        return this.plan.aggregation_info.useItemConditions;\n                    }\n                    else {\n                        return false;\n                    }\n                },\n\n                configurationState(){\n                    if(this.hasGrades() || this.hasCompletions()) {\n                        return \"t-configured-ok\";\n                    } else {\n                        return \"t-configured-alert\";\n                    }\n                },\n\n                configurationIcon(){\n                    if(this.hasGrades() || this.hasCompletions()) {\n                        return \"check\";\n                    } else {\n                        return \"exclamation-circle\";\n                    }\n                },\n                startdate(){\n                    return format_date(this.value.course.startdate);\n                },\n                enddate(){\n                    if(this.value.course.enddate){\n                        return format_date(this.value.course.enddate);\n                    } \n                    else {\n                        return this.text.noenddate;\n                    }\n                }\n\n            },\n            methods: {\n                hasGrades() {\n                    if(this.value.course.grades && this.value.course.grades.length > 0){\n                        for(const g of this.value.course.grades){\n                            if(g.selected){\n                                return true;\n                            }\n                        }\n                    } \n                    return false;\n                },\n                hasCompletions() {\n                    if(this.value.course.completion && this.value.course.completion.conditions) {\n                        for(const cgroup of this.value.course.completion.conditions){\n                            if(cgroup.items && cgroup.items.length > 0){\n                                return true;\n                            }\n                        }\n                    }\n                    return false;\n                },\n                includeChanged(newValue,g){\n                    call([{\n                        methodname: 'local_treestudyplan_include_grade',\n                        args: { 'grade_id': g.id,\n                                'item_id': this.value.id, \n                                'include': newValue,\n                                'required': g.required,\n                                }\n                    }])[0].fail(notification.exception);\n                },\n                requiredChanged(newValue,g){\n                    call([{\n                        methodname: 'local_treestudyplan_include_grade',\n                        args: { 'grade_id': g.id,\n                                'item_id': this.value.id, \n                                'include': g.selected,\n                                'required': newValue,\n                                }\n                    }])[0].fail(notification.exception);\n                },                \n                updateConditions() {\n                    call([{\n                        methodname: 'local_treestudyplan_edit_studyitem',\n                        args: { 'id': this.value.id,\n                                'conditions': this.value.conditions, \n                                }\n                    }])[0].fail(notification.exception);\n                },\n            },\n            created() {\n\n            },\n            template: `\n            <b-card no-body class=\"t-item-course\">\n                <div class='d-flex flex-wrap mr-0 ml-0'>\n                    <div>\n                        <span \n                            :title=\"text['coursetiming_'+value.course.timing]\" \n                            v-b-popover.hover.top=\"startdate+' - '+enddate\" \n                            :class=\"'t-timing-indicator timing-'+value.course.timing\"></span>\n                    </div>\n                    <div class=\"flex-fill\">\n                        <b-card-body class=\"align-items-center\">\n                            <a  class=\"t-item-course-config\"\n                                v-b-modal=\"'t-item-course-config-'+value.id\" \n                                href=\"#\" @click.prevent=\"\"\n                                ><i :class=\"'fa fa-'+configurationIcon+' ' + configurationState\"></i></a>\n                            <a  v-b-modal=\"'t-item-course-config-'+value.id\"\n                                :id=\"'t-item-course-details-'+value.id\" \n                                :href=\"'/course/view.php?id='+value.course.id\"\n                                @click.prevent.stop=\"\">{{ value.course.displayname }}</a>\n                        </b-card-body>\n                    </div>\n                </div>\n                <b-modal\n                    :id=\"'t-item-course-config-'+value.id\" \n                    :title=\"value.course.displayname + ' - ' + value.course.fullname\" \n                    ok-only\n                    size=\"lg\"\n                    scrollable\n                    >\n                    <template #modal-header>\n                        <div>\n                            <h1><a :href=\"'/course/view.php?id='+value.course.id\" target=\"_blank\"\n                                ><i class=\"fa fa-graduation-cap\"></i> {{ value.course.fullname }}</a>\n                                <a v-if='!!value.course.completion' \n                                    :href=\"'/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(\" / \")}} / {{value.course.shortname}}\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                            <t-item-timing-checker\n                                class=\"mt-1\"\n                                :maxspan=\"maxspan\"\n                                :page=\"page\"\n                                :period=\"period\"\n                                v-model=\"value\"\n                             ></t-item-timing-checker>\n                        </div>\n                    </template>\n                    \n                    <t-item-course-grades \n                        v-if='!!value.course.grades && value.course.grades.length > 0' \n                        v-model='value' :plan=\"plan\"\n                        ></t-item-course-grades>\n                    <t-item-course-completion\n                        v-if='!!value.course.completion' \n                        v-model='value.course.completion'\n                        :course='value.course'\n                        ></t-item-course-completion>\n                </b-modal>\n            </b-card>\n            `,\n        });\n\n\n        Vue.component('t-item-course-grades', {\n            props: {\n                'value' :{\n                    type: Object,\n                    default(){ return null;},\n                },\n                'plan' :{\n                    type: Object,\n                    default(){ return null;},\n                },\n            },\n            data() {\n                return {\n                    condition_options: string_keys.conditions,\n                    text: strings.item_course_text,\n                };\n            },\n            computed: {\n                useRequiredGrades() {\n                    if(this.plan && this.plan.aggregation_info && this.plan.aggregation_info.useRequiredGrades !== undefined){\n                        return this.plan.aggregation_info.useRequiredGrades;\n                    }\n                    else {\n                        return false;\n                    }\n                },\n                selectedgrades(){\n                    let list = [];\n                    for(let ix in this.value.course.grades){\n                        let g = this.value.course.grades[ix];\n                        if(g.selected){\n                            list.push(g);\n                        }\n                    }\n                    return list;\n                },                \n            },\n            methods: {\n                includeChanged(newValue,g){\n                    call([{\n                        methodname: 'local_treestudyplan_include_grade',\n                        args: { 'grade_id': g.id,\n                                'item_id': this.value.id, \n                                'include': newValue,\n                                'required': g.required,\n                                }\n                    }])[0].fail(notification.exception);\n                },\n                requiredChanged(newValue,g){\n                    call([{\n                        methodname: 'local_treestudyplan_include_grade',\n                        args: { 'grade_id': g.id,\n                                'item_id': this.value.id, \n                                'include': g.selected,\n                                'required': newValue,\n                                }\n                    }])[0].fail(notification.exception);\n                },                \n            },\n            created() {\n\n            },\n            template: `\n            <div>\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>\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>{{g.name}}</s-edit-mod>\n                        </li>\n                    </ul>\n                </b-form-group>\n            </div>\n            `,\n        });\n\n        Vue.component('t-item-course-completion',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n                guestmode: {\n                    type: Boolean,\n                    default: false,\n                },\n                course: {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                    text: strings.completion,\n                };\n            },\n            created(){\n                const self = this;\n                // Get text strings for condition settings\n                let stringkeys = [];\n                for(const key in  this.text){\n                    stringkeys.push({ key: key, component: 'local_treestudyplan'});\n                }\n                get_strings(stringkeys).then(function(strings){\n                    let i = 0;\n                    for(const key in  self.text){\n                        self.text[key] = strings[i];\n                        i++;\n                    }\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            },\n            methods: {\n                completion_icon(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    \n                completion_tag(cgroup){\n                    return cgroup.completion?'completed':'incomplete';\n                }\n            },\n            template: `\n            <table class=\"r-item-course-grade-details\">\n                <tr v-if=\"hasCompletions\">\n                    <td colspan='2'><span v-if=\"value.aggregation == 'all'\">{{ text.aggregation_overall_all}}</span\n                    ><span v-else>{{ text.aggregation_overall_any}}</span></td>\n                </tr>\n                <tr v-else>\n                    <td colspan='2'>{{text.completion_not_configured}}!\n                    <br/><a :href=\"'/course/completion.php?id='+course.id\" target='_blank'>{{text.configure_completion}}</a>\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                        {{cgroup.title}}</th>\n                    </tr>\n                    <tr v-for='ci in cgroup.items'>\n                        <td><span v-html='ci.details.criteria'></span>\n                        </td>\n                        <td v-if=\"ci.details.requirement\" class=\"font-italic\">\n                            {{ci.details.requirement}}\n                        </td>\n                    </tr>\n                </template>\n            </table>\n            `,\n        });\n\n\n        /************************************\n        *                                  *\n        * Toolbox list components          *\n        *                                  *\n        ************************************/\n        Vue.component('t-item-junction',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                    condition_options: string_keys.conditions,\n                };\n            },\n            methods: {\n\n            },\n            template: `\n            <div class='t-item-junction  t-item-filter'> \n                <i class=\"fa fa-check-circle\"></i>\n            </div>\n            `,\n        });\n\n        Vue.component('t-item-finish',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                };\n            },\n            methods: {\n            },\n            template: `\n            <div class='t-item-finish t-item-filter'> \n                <i class=\"fa fa-stop-circle\"></i>\n            </div>    \n            `,\n        });\n\n        Vue.component('t-item-start',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                };\n            },\n            created(){\n        \n            },\n            methods: {\n            },\n            template: `\n            <div class='t-item-start t-item-filter'> \n                <i class=\"fa fa-play-circle\"></i>\n            </div>    \n            `,\n        });\n\n        Vue.component('t-item-badge',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return { badge: {}};},\n                },\n            },\n            data() {\n                return {\n                    txt: strings,\n                };\n            },\n            methods: {\n            },\n            template: `\n            <div class='t-item-badge t-item-filter' v-b-tooltip.hover :title=\"value.badge.name\"> \n                <svg class=\"t-badge-backdrop \" width='50px' height='50px' viewBox=\"0 0 100 100\">\n                    <title>{{value.badge.name}}</title>\n                    <circle cx=\"50\" cy=\"50\" r=\"46\" \n                        style=\"stroke: currentcolor; stroke-width: 4; fill: currentcolor; fill-opacity: 0.5;\"/>\n                    <image class=\"badge-image\" clip-path=\"circle() fill-box\"\n                        :href=\"value.badge.imageurl\" x=\"12\" y=\"12\" width=\"76\" height=\"76\"/>\n                </svg>\n                <a class=\"t-item-config badge\"\n                v-b-modal=\"'t-item-badge-details-'+value.id\" href=\"#\" @click.prevent=\"\"><i  class=\"fa fa-gear\"></i></a>\n                <b-modal\n                    :id=\"'t-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=\"value.badge.infolink\" target=\"_blank\"\n                                >{{ value.badge.name }}</a\n                            ></h1>\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 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><strong><i class=\"fa fa-link\"></i>\n                                <a :href=\"value.badge.infolink\">{{ txt.badge.badgeinfo }}</a></strong></p>\n                        </b-col></b-row>\n                    </b-container>\n                </b-modal>\n\n            </div>    \n            `,\n        });\n\n        Vue.component('t-coursecat-list',{\n            props: {\n                value : {\n                    type: Array,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                };\n            },\n            methods: {\n            },\n            template: `\n            <ul class=\"t-coursecat-list\">\n                <t-coursecat-list-item \n                    v-for=\"coursecat,idx in value\" \n                    v-model=\"value[idx]\" \n                    :key=\"coursecat.id\"></t-coursecat-list-item>\n            </ul>    \n            `,\n        });\n\n        Vue.component('t-coursecat-list-item',{\n            props: {\n                value : {\n                    type: Object,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                    loading: false,\n\n                };\n            },\n            computed: {\n                showSpinner() {\n                    return this.canLoadMore();\n                },\n                hasDetails() {\n                    return (this.value.haschildren || this.value.hascourses);\n                }\n\n            },\n            methods: {\n                canLoadMore() {\n                    return (this.value.haschildren && (!this.value.children || this.value.children.length == 0)) ||\n                        (this.value.hascourses && (!this.value.courses || this.value.courses.length == 0));\n                },\n                onShowDetails(){\n                    const self = this;\n                    if(this.canLoadMore()) {\n                        call([{\n                            methodname: 'local_treestudyplan_get_category',\n                            args: { \"id\": this.value.id}\n                        }])[0].done(function(response){\n                            self.$emit('input', response);\n                        }).fail(notification.exception);\n                    }\n                }\n            },\n            template: `\n            <li class=\"t-coursecat-list-item\">\n                <span v-if=\"hasDetails\" v-b-toggle=\"'coursecat-'+value.id\">\n                    <i class=\"when-closed fa fa-caret-right\"></i>\n                    <i class=\"when-open fa fa-caret-down\"></i>\n                    <span class=\"t-coursecat-heading\">\n                        <i class=\"t-coursecat-list-item fa fa-tasks\"></i>\n                        {{ value.category.name }}\n                    </span>\n                </span>\n                <span v-else>\n                    <span class=\"t-coursecat-heading\">\n                        <i class=\"t-coursecat-list-item fa fa-tasks\"></i>\n                        {{ value.category.name }}\n                    </span>\n                </span>\n                <b-collapse v-if=\"hasDetails\" :id=\"'coursecat-'+value.id\" \n                    @show=\"onShowDetails\" :visible=\"!!(value.children) || !!(value.courses)\">\n                    <b-spinner class=\"ml-4\" v-if=\"showSpinner\" small variant=\"primary\"></b-spinner>\n                    <t-coursecat-list v-if=\"value.children\" v-model=\"value.children\"></t-coursecat-list>\n                    <t-course-list v-if=\"value.courses\" v-model=\"value.courses\"></t-course-list>\n                </b-collapse>\n            </li>\n            `,\n        });\n\n        Vue.component('t-course-list',{\n            props: {\n                value : {\n                    type: Array,\n                    default: function(){ return {};},\n                },\n            },\n            data() {\n                return {\n                };\n            },\n            methods: {\n                makeType(){\n                    return {\n                        item: false,\n                        component: true,\n                        span: 1, //TODO: Detect longer courses and give them an appropriate span\n                        type: 'gradable',\n                    };\n                },\n            },\n            template: `\n            <ul class=\"t-course-list\">\n                <li class=\"t-course-list-item\" v-for=\"course in value\" :key=\"course.id\">\n                    <drag \n                        class=\"draggable-course\" \n                        :data=\"course\" \n                        :type=\"makeType()\"\n                        @cut=\"\"\n                    >\n                    <i class=\"t-course-list-item fa fa-book\"></i> {{ course.shortname }} - {{ course.fullname }}\n                    </drag>\n                </li>\n            </ul>    \n            `,\n        });\n        \n    },\n};\n"],"names":["STUDYPLAN_EDITOR_FIELDS","STUDYPLAN_EDITOR_PAGE_FIELDS","PERIOD_EDITOR_FIELDS","datechanger_globals","default","defaultchoice","hidewarn","install","Vue","debug","Debugger","isVisible","elem","offsetWidth","offsetHeight","getClientRects","length","enable","ItemEventBus","string_keys","conditions","value","textkey","strings","studyplan_text","studyline_editmode","editmode_modules_hidden","studyline_add","add$core","edit$core","studyline_name","studyline_name_ph","studyline_shortname","studyline_shortname_ph","studyline_color","associations","associated_cohorts","associated_users","studyline_edit","studyplan_name","studyplan_name_ph","studyplan_shortname","studyplan_shortname_ph","studyplan_description","studyplan_description_ph","studyplan_slots","studyplan_startdate","studyplan_enddate","studyplan_advanced","advanced_tools","confirm_cancel","confirm_ok","success$core","error$core","advanced_converted","advanced_skipped","advanced_failed","advanced_locked","advanced_multiple","advanced_error","advanced_tools_heading","advanced_warning_title","advanced_warning","advanced_pick_scale","advanced_course_manipulation_title","advanced_force_scale_title","advanced_force_scale_desc","advanced_force_scale_button","advanced_disable_autoenddate_title","advanced_disable_autoenddate_desc","advanced_disable_autoenddate_button","advanced_confirm_header","advanced_force_scale_confirm","advanced_import","advanced_export","advanced_export_csv","advanced_import_from_file","advanced_purge","advanced_purge_expl","advanced_cascade_cohortsync_title","advanced_cascade_cohortsync_desc","advanced_cascade_cohortsync","studyplan_edit","studyplan_context","choose_aggregation_style","setting_bistate_thresh_excellent","settingdesc_bistate_thresh_excellent","setting_bistate_thresh_good","settingdesc_bistate_thresh_good","setting_bistate_thresh_completed","settingdesc_bistate_thresh_completed","setting_bistate_support_failed","settingdesc_bistate_support_failed","setting_bistate_thresh_progress","settingdesc_bistate_thresh_progress","setting_bistate_accept_pending_submitted","settingdesc_bistate_accept_pending_submitted","period_edit","edit","fullname","shortname","startdate","enddate","course_timing","title","desc","question","warning","timing_ok","timing_off","course","period","yes","no","duration","years","year","weeks","week","days","day","rememberchoice","hidewarning","periodspan","periods","periodspan_desc","studyplan_associate","associate_cohorts","associate_users","add_association","delete_association","associations_empty","associations_search","cohorts","users","selected","name","context","item_text","select_conditions","item_configuration","item_course_text","select_grades","coursetiming_past","coursetiming_present","coursetiming_future","grade_include","grade_require","ok","invalid","error","completion","completion_completed","completion_incomplete","aggregation_all","aggregation_any","aggregation_overall_all","aggregation_overall_any","completion_not_configured","configure_completion","badge","share_badge","dateissued","dateexpire","badgeinfo","component","props","type","Object","data","force_scales","selected_scale","result","text","created","mounted","updated","computed","scales","id","disabled","this","concat","advanced","methods","disable_autoenddate","self","methodname","args","studyplan_id","done","response","$bvModal","msgBoxConfirm","success","msg","fail","notification","exception","force_scales_start","okVariant","okTitle","cancelTitle","then","_this","scale_id","export_plan","format","undefined","includes","content","import_studylines","filename","_this2","location","reload","purge_studyline","force","cascade_cohortsync","msgBoxOk","modal_close","template","String","show","config","userfields","key","cohortfields","editdata","description","context_id","Date","getFullYear","aggregation","aggregation_config","aggregation_parsed","aggregators","categories","category","path","ix","ag","defaultconfig","JSON","parse","e","warn","operation","cat","pathname","join","editPlanStart","mode","pages","editPlanFinish","method","stringify","$emit","moved_from","moved_to","moved","numberFilter","association","loading","search","associated","showModal","loadAssociations","cohortOptionModel","c","userOptionModel","u","firstname","lastname","map","searchCohorts","searchtext","like","exclude_id","cohortAssociate","requests","searchselected","i","r","push","cohort_id","cohortDisassociate","associatedselected","searchUsers","userAssociate","user_id","userDisassociate","editStart","editFinish","create","studyline","editmode","color","original","studyplan","slots","aggregation_info","useRequiredGrades","useItemCondition","page","studylines","$root","columns","columns_stylerule","s","countLineLayers","line","maxLayer","competencies","item","layer","filters","slotsempty","Array","isArray","count","movedStudyplan","plan","from","to","addStudyLine","newlineinfo","editLineStart","assign","editLineFinish","editedline","originalline","deleteLine","param","modalresponse","index","indexOf","splice","reorderLines","event","lines","apply","sequence","idx","deletePlan","deleteStudyItem","source","showslot","layeridx","forGradable","list","span","layers","Number","layerHeights","$on","onLineHeightChange","lineid","layerid","newheight","$refs","main","items","document","querySelectorAll","heightSum","forEach","el","height","getBoundingClientRect","heightStyle","style","deletable","onEdit","onDelete","slotindex","resizeListener","ResizeObserver","size","observe","unmounted","disconnect","slotkey","itm","listtype","dragacceptlist","courseHoverDummy","hover","current","now","pstart","pend","spanCss","datechanger","coursespan","onDrop","slot","relocateStudyItem","_this3","timingChecker","validate_course_period","$nextTick","onCut","iteminfo","onDragEnter","onDragLeave","maxSpan","freeIndex","l","f","makeType","checkType","maxspan","hidden","Boolean","endperiod","endperiodnr","Math","min","perioddesc","course_period_matches","first","getTime","last","floor","random","toString","globals","info","canupdatecourse","defaultvalue","change_course_period","period_id","course_id","timing","change_span","format_duration","dsi","toLocaleLowerCase","dummy","dragLine","dragEventListener","deleteMode","condition_options","showContext","dragStart","start","getElementById","dragelement","position","left","x","top","y","SimpleLine","gravity","end","addEventListener","onMouseMove","dragEnd","remove","removeProperty","removeEventListener","clientX","clientY","from_id","to_id","redrawLines","conn","_this4","connections","in","redrawLine","_this5","removeLine","out","highlight","setConfig","normalize","updateItem","continuation_id","doShowContext","hasContext","preventDefault","onCreatedConnection","onRemovedConnection","c_in","onRePositioned","onDisPositioned","re_id","onItemDeleted","item_id","onRedrawLines","hasConnectionsOut","hasConnectionsIn","setTimeout","_this6","beforeDestroy","$off","beforeUpdate","useItemConditions","configurationState","hasGrades","hasCompletions","configurationIcon","noenddate","grades","cgroup","includeChanged","newValue","g","required","requiredChanged","updateConditions","selectedgrades","guestmode","stringkeys","completion_icon","completion_tag","txt","showSpinner","canLoadMore","hasDetails","haschildren","hascourses","children","courses","onShowDetails"],"mappings":"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"}