Multi-period courses drag and drop
This commit is contained in:
parent
f97c4cb2ef
commit
235972e2f4
6 changed files with 151 additions and 155 deletions
|
@ -171,7 +171,15 @@ export function init(contextid,categoryid) {
|
||||||
},
|
},
|
||||||
contextid(){
|
contextid(){
|
||||||
return contextid;
|
return contextid;
|
||||||
}
|
},
|
||||||
|
filterComponentType(){
|
||||||
|
return {
|
||||||
|
item: true,
|
||||||
|
component: false,
|
||||||
|
span: 1,
|
||||||
|
type: 'filter',
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeStudyplan() {
|
closeStudyplan() {
|
||||||
|
@ -250,7 +258,6 @@ export function init(contextid,categoryid) {
|
||||||
download(plan.shortname+".json",response.content,response.format);
|
download(plan.shortname+".json",response.content,response.format);
|
||||||
}).fail(notification.exception);
|
}).fail(notification.exception);
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,6 @@ export default {
|
||||||
day: 'day$core',
|
day: 'day$core',
|
||||||
rememberchoice: 'course_timing_rememberchoice',
|
rememberchoice: 'course_timing_rememberchoice',
|
||||||
hidewarning: 'course_timing_hidewarning,'
|
hidewarning: 'course_timing_hidewarning,'
|
||||||
|
|
||||||
},
|
},
|
||||||
studyplan_associate: {
|
studyplan_associate: {
|
||||||
associations: 'associations',
|
associations: 'associations',
|
||||||
|
@ -1285,7 +1284,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
countLineLayers(line){
|
countLineLayers(line){
|
||||||
let maxLayer = -1;
|
let maxLayer = -1;
|
||||||
for(let i = 0; i <= this.value.slots; i++){
|
for(let i = 0; i <= this.page.periods; i++){
|
||||||
const slot = line.slots[i];
|
const slot = line.slots[i];
|
||||||
// Determine the amount of used layers in a studyline slit
|
// Determine the amount of used layers in a studyline slit
|
||||||
for(const ix in line.slots[i].competencies){
|
for(const ix in line.slots[i].competencies){
|
||||||
|
@ -1447,6 +1446,34 @@ export default {
|
||||||
}).fail(notification.exception);
|
}).fail(notification.exception);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
showslot(line,index, layeridx, type){
|
||||||
|
// check if the slot should be hidden because a previous slot has an item with a span
|
||||||
|
// so big that it hides this slot
|
||||||
|
const forGradable = (type == 'gradable')?true:false;
|
||||||
|
const periods = this.page.periods;
|
||||||
|
let show = true;
|
||||||
|
for(let i = 0; i < periods; i++){
|
||||||
|
if(line.slots[index-i] && line.slots[index-i].competencies){
|
||||||
|
const list = line.slots[index-i].competencies;
|
||||||
|
for(const ix in list){ // Really wish that for ( .. of .. ) would work with the minifier
|
||||||
|
const item = list[ix];
|
||||||
|
if(item.layer == layeridx){
|
||||||
|
if(forGradable){
|
||||||
|
if(i > 0 && (item.span - i) > 0){
|
||||||
|
show = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if((item.span - i) > 1){
|
||||||
|
show = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return show;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
template:
|
template:
|
||||||
|
@ -1540,35 +1567,36 @@ export default {
|
||||||
<!-- Line by line add the items -->
|
<!-- Line by line add the items -->
|
||||||
<!-- The grid layout handles putting it in rows and columns -->
|
<!-- The grid layout handles putting it in rows and columns -->
|
||||||
<template v-for="(line,lineindex) in page.studylines"
|
<template v-for="(line,lineindex) in page.studylines"
|
||||||
><template v-for="layeridx in countLineLayers(line)+1"
|
><template v-for="(layernr,layeridx) in countLineLayers(line)+1"
|
||||||
><template v-for="(n,index) in (page.periods+1)"
|
><template v-for="(n,index) in (page.periods+1)"
|
||||||
>
|
>
|
||||||
<t-studyline-slot
|
<t-studyline-slot
|
||||||
v-if="index > 0"
|
v-if="index > 0 && showslot(line, index, layeridx, 'gradable')"
|
||||||
type='gradable'
|
type='gradable'
|
||||||
v-model="line.slots[index].competencies"
|
v-model="line.slots[index].competencies"
|
||||||
:key="'c-'+lineindex+'-'+index+'-'+layeridx"
|
:key="'c-'+lineindex+'-'+index+'-'+layernr"
|
||||||
:slotindex="index"
|
:slotindex="index"
|
||||||
:line="line"
|
:line="line"
|
||||||
:plan="value"
|
:plan="value"
|
||||||
:page="page"
|
:page="page"
|
||||||
:period="page.perioddesc[index-1]"
|
:period="page.perioddesc[index-1]"
|
||||||
:layer="layeridx-1"
|
:layer="layeridx"
|
||||||
:class="'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')
|
:class="'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')
|
||||||
+ ((lineindex==0 && layeridx==1)?' first ':' ')
|
+ ((lineindex==0 && layernr==1)?' first ':' ')
|
||||||
+ ((lineindex==page.studylines.length-1)?' last ':' ')"
|
+ ((lineindex==page.studylines.length-1)?' last ':' ')"
|
||||||
></t-studyline-slot
|
></t-studyline-slot
|
||||||
><t-studyline-slot
|
><t-studyline-slot
|
||||||
type='filter'
|
type='filter'
|
||||||
|
v-if="showslot(line, index, layeridx, 'filter')"
|
||||||
v-model="line.slots[index].filters"
|
v-model="line.slots[index].filters"
|
||||||
:key="'f-'+lineindex+'-'+index+'-'+layeridx"
|
:key="'f-'+lineindex+'-'+index+'-'+layernr"
|
||||||
:slotindex="index"
|
:slotindex="index"
|
||||||
:line="line"
|
:line="line"
|
||||||
:plan="value"
|
:plan="value"
|
||||||
:page="page"
|
:page="page"
|
||||||
:layer="layeridx-1"
|
:layer="layeridx"
|
||||||
:class="'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')
|
:class="'t-studyline ' + ((lineindex%2==0)?' odd ':' even ')
|
||||||
+ ((lineindex==0 && layeridx==1)?' first ':'')
|
+ ((lineindex==0 && layernr==1)?' first ':'')
|
||||||
+ ((lineindex==page.studylines.length-1)?' last ':' ')
|
+ ((lineindex==page.studylines.length-1)?' last ':' ')
|
||||||
+ ((index==page.periods)?' rightmost':'')"
|
+ ((index==page.periods)?' rightmost':'')"
|
||||||
>
|
>
|
||||||
|
@ -1876,6 +1904,14 @@ export default {
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
spanCss(){
|
||||||
|
if(this.item && this.item.span > 1){
|
||||||
|
const span = (2 * this.item.span) - 1;
|
||||||
|
return `width: 100%; grid-column: span ${span};`;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -1896,40 +1932,33 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
dragacceptitem(){
|
|
||||||
if(this.type == "gradable"){
|
|
||||||
return ["gradable-item"];
|
|
||||||
} else {
|
|
||||||
return ["filter-item"];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dragacceptcomponent(){
|
|
||||||
if(this.type == "gradable"){
|
|
||||||
return ["course",];
|
|
||||||
} else {
|
|
||||||
return ["filter",];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDrop(event) {
|
onDrop(event) {
|
||||||
this.hover.component = null;
|
this.hover.component = null;
|
||||||
this.hover.type = null;
|
this.hover.type = null;
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
if(self.dragacceptitem().includes(event.type)) {
|
if(event.type.item) {
|
||||||
let item = event.data;
|
let item = event.data;
|
||||||
|
|
||||||
// Perform layer update - set this slot and layer here
|
// To avoid weird visuals with the lines,
|
||||||
self.relocateStudyItem(item).done(()=>{
|
// we add the item to the proper place in the front-end first
|
||||||
item.layer = this.layer;
|
item.layer = this.layer;
|
||||||
item.slot = this.slotindex;
|
item.slot = this.slotindex;
|
||||||
self.value.push(item);
|
self.value.push(item);
|
||||||
self.$emit("input",self.value);
|
self.$emit("input",self.value);
|
||||||
|
|
||||||
|
// then on the next tick, we inform the back end
|
||||||
|
// Since moving things around has never been unsuccessful, unless you have other problems,
|
||||||
|
// it's better to have nice visuals.
|
||||||
|
this.$nextTick(() => {
|
||||||
|
self.relocateStudyItem(item).done(()=>{
|
||||||
self.validate_course_period();
|
self.validate_course_period();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if(self.dragacceptcomponent().includes(event.type) ){
|
else if(event.type.component){
|
||||||
|
|
||||||
if(event.type == "course"){
|
if(event.type.type == "course"){
|
||||||
call([{
|
call([{
|
||||||
methodname: 'local_treestudyplan_add_studyitem',
|
methodname: 'local_treestudyplan_add_studyitem',
|
||||||
args: {
|
args: {
|
||||||
|
@ -1951,11 +1980,13 @@ export default {
|
||||||
self.relocateStudyItem(item).done(()=>{
|
self.relocateStudyItem(item).done(()=>{
|
||||||
self.value.push(item);
|
self.value.push(item);
|
||||||
self.$emit("input",self.value);
|
self.$emit("input",self.value);
|
||||||
self.validate_course_period();
|
// call the validate period function on next tick,
|
||||||
|
// since it paints the item in the slot first
|
||||||
|
this.$nextTick(self.validate_course_period);
|
||||||
});
|
});
|
||||||
}).fail(notification.exception);
|
}).fail(notification.exception);
|
||||||
}
|
}
|
||||||
else if(event.type == "filter") {
|
else if(event.type.type == "filter") {
|
||||||
call([{
|
call([{
|
||||||
methodname: 'local_treestudyplan_add_studyitem',
|
methodname: 'local_treestudyplan_add_studyitem',
|
||||||
args: {
|
args: {
|
||||||
|
@ -2055,39 +2086,86 @@ export default {
|
||||||
else if(dsi.days > 1){ s += `${dsi.days} ${this.text.days}, `;}
|
else if(dsi.days > 1){ s += `${dsi.days} ${this.text.days}, `;}
|
||||||
|
|
||||||
return s.toLocaleLowerCase();
|
return s.toLocaleLowerCase();
|
||||||
|
},
|
||||||
|
maxSpan(){
|
||||||
|
// Determine the maximum span for components in this slot
|
||||||
|
// Used for setting the max in the timing adjustment screen (s)
|
||||||
|
// And for checking the filter types
|
||||||
|
|
||||||
|
// Assume this slot is first one available
|
||||||
|
let freeIndex = this.slotindex;
|
||||||
|
// Determine last free slot following this one in the layer
|
||||||
|
for(let i = this.slotindex + 1; i <= this.page.periods; i++){
|
||||||
|
if(this.line.slots && this.line.slots[i] && this.line.slots[i].competencies){
|
||||||
|
const l = this.line.slots[i].competencies;
|
||||||
|
if(l[this.layer]) {
|
||||||
|
// slot is busy in this layer.
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
freeIndex = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break; // stop processing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// calculate span from that
|
||||||
|
return freeIndex - this.slotindex + 1;
|
||||||
|
|
||||||
|
},
|
||||||
|
makeType(item){
|
||||||
|
return {
|
||||||
|
item: true,
|
||||||
|
component: false,
|
||||||
|
span: item.span,
|
||||||
|
type: this.type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
checkType(type) {
|
||||||
|
if(type.type == this.type){
|
||||||
|
if(type == 'filter'){
|
||||||
|
return true;
|
||||||
|
} else if(type.span <= this.maxSpan()){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<div :class="'t-studyline-slot '+type + ' t-studyline-slot-'+slotindex + ' ' + ((slotindex==0)?' t-studyline-firstcolumn ':' ')
|
<div :class="'t-studyline-slot '+type + ' t-studyline-slot-'+slotindex + ' ' + ((slotindex==0)?' t-studyline-firstcolumn ':' ')
|
||||||
+ (current?'current ':' ')"
|
+ (current?'current ':' ')"
|
||||||
:data-studyline="line.id" ref="main"
|
:data-studyline="line.id" ref="main"
|
||||||
|
:style='spanCss'
|
||||||
><drag v-if="item"
|
><drag v-if="item"
|
||||||
|
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="t-slot-item"
|
class="t-slot-item"
|
||||||
:data="item"
|
:data="item"
|
||||||
:type="type+'-item'"
|
:type="makeType(item)"
|
||||||
@cut="onCut"
|
@cut="onCut"
|
||||||
><t-item v-model="item" :plan="plan"></t-item
|
><t-item v-model="item" :plan="plan"></t-item
|
||||||
></drag
|
></drag
|
||||||
><drop v-else
|
><drop v-else
|
||||||
:class="'t-slot-drop '+type + (layer > 0?' secondary':' primary')"
|
:class="'t-slot-drop '+type + (layer > 0?' secondary':' primary')"
|
||||||
:accepts-type="dragacceptlist"
|
:accepts-type="checkType"
|
||||||
@drop="onDrop"
|
@drop="onDrop"
|
||||||
mode="cut"
|
mode="cut"
|
||||||
@dragenter="onDragEnter"
|
@dragenter="onDragEnter"
|
||||||
@dragleave="onDragLeave"
|
@dragleave="onDragLeave"
|
||||||
><template v-if="hover.component">
|
><template v-if="hover.component">
|
||||||
<div v-if="hover.type == listtype+'-item'"
|
<div v-if="hover.type.item"
|
||||||
class="t-slot-item feedback"
|
class="t-slot-item feedback"
|
||||||
:key="hover.component.id"
|
:key="hover.component.id"
|
||||||
><t-item v-model="hover.component" dummy></t-item
|
><t-item v-model="hover.component" dummy></t-item
|
||||||
></div
|
></div
|
||||||
><div v-else-if="hover.type == 'course'"
|
><div v-else-if="hover.type.type == 'gradable'"
|
||||||
class="t-slot-item feedback"
|
class="t-slot-item feedback"
|
||||||
:key="'course-'+hover.component.id"
|
:key="'course-'+hover.component.id"
|
||||||
><t-item-course v-model="courseHoverDummy"></t-item-course></div
|
><t-item-course v-model="courseHoverDummy"></t-item-course></div
|
||||||
><div v-else-if="hover.type == 'filter'"
|
><div v-else-if="hover.type.type == 'filter'"
|
||||||
class="t-slot-item feedback"
|
class="t-slot-item feedback"
|
||||||
key="tooldrop"
|
key="tooldrop"
|
||||||
><t-item-junction v-if="hover.component.type == 'junction'" ></t-item-junction
|
><t-item-junction v-if="hover.component.type == 'junction'" ></t-item-junction
|
||||||
|
@ -2941,110 +3019,9 @@ export default {
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
* *
|
* *
|
||||||
* Competency map Vue components *
|
* Toolbox list components *
|
||||||
* *
|
* *
|
||||||
************************************/
|
************************************/
|
||||||
Vue.component('t-competency-heading', {
|
|
||||||
props: {
|
|
||||||
value : {
|
|
||||||
type: Object,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
inuse() {
|
|
||||||
return (this.value.inuse !== undefined && !!this.value.inuse);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onCut(){
|
|
||||||
// console.info('cutevent-competency',event);
|
|
||||||
this.value.inuse=true;
|
|
||||||
this.$emit('input',this.value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<span class="t-competency-heading">
|
|
||||||
<i :class="'t-'+value.type+' fa fa-puzzle-piece'" v-if="value.type == 'module'"></i>
|
|
||||||
<i :class="'t-'+value.type+' fa fa-map'" v-else-if="value.type == 'category'"></i>
|
|
||||||
<i :class="'t-'+value.type+' fa fa-check-square'" v-else-if="value.type == 'goal'"></i>
|
|
||||||
<i :class="'t-'+value.type+' fa fa-circle'" v-else ></i>
|
|
||||||
<drag
|
|
||||||
class="draggable-competency"
|
|
||||||
v-if="value.type == 'module' && !inuse"
|
|
||||||
:data="value"
|
|
||||||
type="competency"
|
|
||||||
@cut="onCut">
|
|
||||||
{{ value.shortname }}
|
|
||||||
</drag>
|
|
||||||
<span v-else-if="value.type == 'module'" class="disabled-competency">{{ value.shortname }}</span>
|
|
||||||
<span v-else class="competency-info">{{ value.shortname }}</span>
|
|
||||||
</span>
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
Vue.component('t-competency-display', {
|
|
||||||
props: {
|
|
||||||
value : {
|
|
||||||
type: Object,
|
|
||||||
default: function(){ return {};},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dragLine: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
haschildren() {
|
|
||||||
return this.value.children && this.value.children.length > 0;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<li>
|
|
||||||
<span v-if="haschildren" v-b-toggle="'cmp-'+value.id">
|
|
||||||
<i class="when-closed fa fa-caret-right"></i>
|
|
||||||
<i class="when-open fa fa-caret-down"></i>
|
|
||||||
<t-competency-heading v-model="value"></t-competency-heading>
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
<t-competency-heading v-model="value"></t-competency-heading>
|
|
||||||
</span>
|
|
||||||
<b-collapse v-if="haschildren" :id="'cmp-'+value.id">
|
|
||||||
<t-competency-list v-model="value.children"></t-competency-list>
|
|
||||||
</b-collapse>
|
|
||||||
</li>
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
Vue.component('t-competency-list', {
|
|
||||||
props: {
|
|
||||||
value : {
|
|
||||||
type: Array,
|
|
||||||
default: function(){ return [];},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
},
|
|
||||||
template: `
|
|
||||||
<ul class='t-competency-list'>
|
|
||||||
<t-competency-display
|
|
||||||
v-for="(child, index) in value"
|
|
||||||
:key='child.idnumber'
|
|
||||||
v-model="value[index]"
|
|
||||||
></t-competency-display>
|
|
||||||
</ul>
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
|
|
||||||
Vue.component('t-item-junction',{
|
Vue.component('t-item-junction',{
|
||||||
props: {
|
props: {
|
||||||
value : {
|
value : {
|
||||||
|
@ -3270,6 +3247,14 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
makeType(){
|
||||||
|
return {
|
||||||
|
item: false,
|
||||||
|
component: true,
|
||||||
|
span: 1, //TODO: Detect longer courses and give them an appropriate span
|
||||||
|
type: 'gradable',
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<ul class="t-course-list">
|
<ul class="t-course-list">
|
||||||
|
@ -3277,7 +3262,7 @@ export default {
|
||||||
<drag
|
<drag
|
||||||
class="draggable-course"
|
class="draggable-course"
|
||||||
:data="course"
|
:data="course"
|
||||||
type="course"
|
:type="makeType()"
|
||||||
@cut=""
|
@cut=""
|
||||||
>
|
>
|
||||||
<i class="t-course-list-item fa fa-book"></i> {{ course.shortname }} - {{ course.fullname }}
|
<i class="t-course-list-item fa fa-book"></i> {{ course.shortname }} - {{ course.fullname }}
|
||||||
|
|
|
@ -124,7 +124,7 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onHeaderHeightChange(newheight){
|
onHeaderHeightChange(newheight){
|
||||||
console.info("Height change event to",newheight);
|
//console.info("Height change event to",newheight);
|
||||||
this.$refs.main.style.height = `${newheight}px`;
|
this.$refs.main.style.height = `${newheight}px`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -84,6 +84,7 @@ class studyitem {
|
||||||
"conditions"=> new \external_value(PARAM_TEXT, 'conditions for completion'),
|
"conditions"=> new \external_value(PARAM_TEXT, 'conditions for completion'),
|
||||||
"slot" => new \external_value(PARAM_INT, 'slot in the study plan'),
|
"slot" => new \external_value(PARAM_INT, 'slot in the study plan'),
|
||||||
"layer" => new \external_value(PARAM_INT, 'layer in the slot'),
|
"layer" => new \external_value(PARAM_INT, 'layer in the slot'),
|
||||||
|
"span" => new \external_value(PARAM_INT, 'how many periods the item spans'),
|
||||||
"course" => courseinfo::editor_structure(VALUE_OPTIONAL),
|
"course" => courseinfo::editor_structure(VALUE_OPTIONAL),
|
||||||
"badge" => badgeinfo::editor_structure(VALUE_OPTIONAL),
|
"badge" => badgeinfo::editor_structure(VALUE_OPTIONAL),
|
||||||
"continuation_id" => new \external_value(PARAM_INT, 'id of continued item'),
|
"continuation_id" => new \external_value(PARAM_INT, 'id of continued item'),
|
||||||
|
@ -110,6 +111,7 @@ class studyitem {
|
||||||
'conditions' => $this->r->conditions,
|
'conditions' => $this->r->conditions,
|
||||||
'slot' => $this->r->slot,
|
'slot' => $this->r->slot,
|
||||||
'layer' => $this->r->layer,
|
'layer' => $this->r->layer,
|
||||||
|
'span' => $this->r->span,
|
||||||
'continuation_id' => $this->r->continuation_id,
|
'continuation_id' => $this->r->continuation_id,
|
||||||
'connections' => [
|
'connections' => [
|
||||||
"in" => [],
|
"in" => [],
|
||||||
|
@ -332,6 +334,7 @@ class studyitem {
|
||||||
"completion" => new \external_value(PARAM_TEXT, 'completion state (incomplete|progress|completed|excellent)'),
|
"completion" => new \external_value(PARAM_TEXT, 'completion state (incomplete|progress|completed|excellent)'),
|
||||||
"slot" => new \external_value(PARAM_INT, 'slot in the study plan'),
|
"slot" => new \external_value(PARAM_INT, 'slot in the study plan'),
|
||||||
"layer" => new \external_value(PARAM_INT, 'layer in the slot'),
|
"layer" => new \external_value(PARAM_INT, 'layer in the slot'),
|
||||||
|
"span" => new \external_value(PARAM_INT, 'how many periods the item spans'),
|
||||||
"course" => courseinfo::user_structure(VALUE_OPTIONAL),
|
"course" => courseinfo::user_structure(VALUE_OPTIONAL),
|
||||||
"badge" => badgeinfo::user_structure(VALUE_OPTIONAL),
|
"badge" => badgeinfo::user_structure(VALUE_OPTIONAL),
|
||||||
"continuation" => self::link_structure(VALUE_OPTIONAL),
|
"continuation" => self::link_structure(VALUE_OPTIONAL),
|
||||||
|
@ -352,6 +355,7 @@ class studyitem {
|
||||||
'completion' => completion::label($this->completion($userid)),
|
'completion' => completion::label($this->completion($userid)),
|
||||||
'slot' => $this->r->slot,
|
'slot' => $this->r->slot,
|
||||||
'layer' => $this->r->layer,
|
'layer' => $this->r->layer,
|
||||||
|
'span' => $this->r->span,
|
||||||
'connections' => [
|
'connections' => [
|
||||||
"in" => [],
|
"in" => [],
|
||||||
"out" => [],
|
"out" => [],
|
||||||
|
|
|
@ -366,11 +366,11 @@ ul.t-competency-list li {
|
||||||
}
|
}
|
||||||
|
|
||||||
.t-slot-drop.secondary {
|
.t-slot-drop.secondary {
|
||||||
min-height: 0px;
|
min-height: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.t-slot-drop.secondary.drop-allowed {
|
.t-slot-drop.secondary.drop-allowed {
|
||||||
min-height: 12px;
|
min-height: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.t-slot-item.feedback {
|
.t-slot-item.feedback {
|
||||||
|
|
|
@ -147,21 +147,21 @@ print $OUTPUT->header();
|
||||||
<b-tab title="<?php t('toolbox')?>">
|
<b-tab title="<?php t('toolbox')?>">
|
||||||
<ul class="t-toolbox">
|
<ul class="t-toolbox">
|
||||||
<li><drag
|
<li><drag
|
||||||
type="filter"
|
:type="filterComponentType"
|
||||||
:data="{type: 'junction'}"
|
:data="{type: 'junction'}"
|
||||||
@cut=""
|
@cut=""
|
||||||
><t-item-junction></t-item-junction><?php t("tool-junction") ?>
|
><t-item-junction></t-item-junction><?php t("tool-junction") ?>
|
||||||
<template v-slot:drag-image="{data}"><t-item-junction></t-item-junction></template>
|
<template v-slot:drag-image="{data}"><t-item-junction></t-item-junction></template>
|
||||||
</drag></li>
|
</drag></li>
|
||||||
<li><drag
|
<li><drag
|
||||||
type="filter"
|
:type="filterComponentType"
|
||||||
:data="{type: 'finish'}"
|
:data="{type: 'finish'}"
|
||||||
@cut=""
|
@cut=""
|
||||||
><t-item-finish></t-item-finish><?php t("tool-finish") ?>
|
><t-item-finish></t-item-finish><?php t("tool-finish") ?>
|
||||||
<template v-slot:drag-image="{data}"><t-item-finish></t-item-finish></template>
|
<template v-slot:drag-image="{data}"><t-item-finish></t-item-finish></template>
|
||||||
</drag></li>
|
</drag></li>
|
||||||
<li><drag
|
<li><drag
|
||||||
type="filter"
|
:type="filterComponentType"
|
||||||
:data="{type: 'start'}"
|
:data="{type: 'start'}"
|
||||||
@cut=""
|
@cut=""
|
||||||
><t-item-start></t-item-start><?php t("tool-start") ?>
|
><t-item-start></t-item-start><?php t("tool-start") ?>
|
||||||
|
@ -173,7 +173,7 @@ print $OUTPUT->header();
|
||||||
<ul class="t-badges">
|
<ul class="t-badges">
|
||||||
<li v-for="b in badges"><img :src="b.imageurl" :alt="b.name"><drag
|
<li v-for="b in badges"><img :src="b.imageurl" :alt="b.name"><drag
|
||||||
class="t-badge-drag"
|
class="t-badge-drag"
|
||||||
type="filter"
|
:type="filterComponentType"
|
||||||
:data="{type: 'badge', badge: b}"
|
:data="{type: 'badge', badge: b}"
|
||||||
@cut=""
|
@cut=""
|
||||||
>{{b.name}}
|
>{{b.name}}
|
||||||
|
|
Loading…
Reference in a new issue