Reworked resizing a course to shift collisions down a layer instead of blocking
This commit is contained in:
parent
d9bcb71a46
commit
546bff0659
3 changed files with 112 additions and 46 deletions
2
amd/build/studyplan-editor-components.min.js
vendored
2
amd/build/studyplan-editor-components.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -2186,44 +2186,7 @@ export default {
|
||||||
},
|
},
|
||||||
maxSpan(){
|
maxSpan(){
|
||||||
// Determine the maximum span for components in this slot
|
// Determine the maximum span for components in this slot
|
||||||
// Used for setting the max in the timing adjustment screen(s)
|
return this.page.periods - this.slotindex + 1;
|
||||||
// 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].courses){
|
|
||||||
const clist = this.line.slots[i].courses;
|
|
||||||
const flist = this.line.slots[i-1].filters; // next filter is in the same slot
|
|
||||||
let busy = false;
|
|
||||||
for(const ix in clist) {
|
|
||||||
if( clist[ix].layer == this.layer) {
|
|
||||||
busy = true; // slot is busy in this layer.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(const ix in flist) {
|
|
||||||
if( flist[ix].layer == this.layer) {
|
|
||||||
busy = true; // slot is busy in this layer.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(! busy) {
|
|
||||||
// slot is free in this layer
|
|
||||||
freeIndex = i;
|
|
||||||
} else {
|
|
||||||
break; // stop checking next slots
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
break; // stop processing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// calculate span from that
|
|
||||||
return freeIndex - this.slotindex + 1;
|
|
||||||
|
|
||||||
},
|
},
|
||||||
makeType(item){
|
makeType(item){
|
||||||
return {
|
return {
|
||||||
|
@ -2303,6 +2266,7 @@ export default {
|
||||||
ref="timingChecker"
|
ref="timingChecker"
|
||||||
:maxspan="maxSpan()"
|
:maxspan="maxSpan()"
|
||||||
:page="page"
|
:page="page"
|
||||||
|
:line="line"
|
||||||
:period="period"
|
:period="period"
|
||||||
v-model="value[itemidx]"
|
v-model="value[itemidx]"
|
||||||
></t-item-timing-checker>
|
></t-item-timing-checker>
|
||||||
|
@ -2317,7 +2281,10 @@ export default {
|
||||||
type: Object, // t-item model
|
type: Object, // t-item model
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
type: Object, // Studyplan data
|
type: Object, // Studyplanpage
|
||||||
|
},
|
||||||
|
line: {
|
||||||
|
type: Object, // Studyline
|
||||||
},
|
},
|
||||||
period: {
|
period: {
|
||||||
type: Object, // Studyplan data
|
type: Object, // Studyplan data
|
||||||
|
@ -2348,7 +2315,7 @@ export default {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug.warn("Timing thing not proper configured",self.value,self.period,self.maxspan);
|
debug.warn("Timing thing not properly configured",self.value,self.period,self.maxspan);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2366,8 +2333,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
validate_course_period() {
|
||||||
validate_course_period(force) {
|
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
debug.info("Validating course and period");
|
debug.info("Validating course and period");
|
||||||
|
@ -2394,6 +2360,9 @@ export default {
|
||||||
debug.info("Course timing matches period",self.datechanger);
|
debug.info("Course timing matches period",self.datechanger);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
has_filter() {
|
||||||
|
const slots = this.page.slots;
|
||||||
|
},
|
||||||
change_course_period() {
|
change_course_period() {
|
||||||
const self=this;
|
const self=this;
|
||||||
// Save the state
|
// Save the state
|
||||||
|
@ -2413,8 +2382,99 @@ export default {
|
||||||
self.$emit("input",self.value);
|
self.$emit("input",self.value);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
checkFilterSlotBusy(slotindex) {
|
||||||
|
debug.info("checking filter",this.line.slots, slotindex,this.value.layer);
|
||||||
|
if (this.line.slots[slotindex]) {
|
||||||
|
const list = this.line.slots[slotindex].filters;
|
||||||
|
for(const ix in list) {
|
||||||
|
if( list[ix].layer == this.value.layer) {
|
||||||
|
debug.info("Busy:",list[ix]);
|
||||||
|
return list[ix];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
nextFreeFilterLayer(slotindex) {
|
||||||
|
const layer = this.value.layer;
|
||||||
|
const list = this.line.slots[slotindex].filters;
|
||||||
|
const usedLayers = [];
|
||||||
|
for(const ix in list) {
|
||||||
|
usedLayers.push(list[ix].layer);
|
||||||
|
}
|
||||||
|
let nextlyr = layer+1;
|
||||||
|
while (usedLayers.includes(nextlyr)) {
|
||||||
|
nextlyr++;
|
||||||
|
}
|
||||||
|
return nextlyr;
|
||||||
|
},
|
||||||
|
checkCourseSlotBusy(slotindex) {
|
||||||
|
debug.info("checking ",this.line.slots, slotindex,this.value.layer);
|
||||||
|
if (this.line.slots[slotindex]) {
|
||||||
|
const list = this.line.slots[slotindex].courses;
|
||||||
|
for(const ix in list) {
|
||||||
|
if( list[ix].layer == this.value.layer) {
|
||||||
|
debug.info("Busy:",list[ix]);
|
||||||
|
return list[ix];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
nextFreeCourseLayer(slotindex) {
|
||||||
|
const layer = this.value.layer;
|
||||||
|
const list = this.line.slots[slotindex].courses;
|
||||||
|
const usedLayers = [];
|
||||||
|
for(const ix in list) {
|
||||||
|
usedLayers.push(list[ix].layer);
|
||||||
|
}
|
||||||
|
let nextlyr = layer+1;
|
||||||
|
while (usedLayers.includes(nextlyr)) {
|
||||||
|
nextlyr++;
|
||||||
|
}
|
||||||
|
return nextlyr;
|
||||||
|
},
|
||||||
|
shift_collisions(span) {
|
||||||
|
// Check all periods for collision
|
||||||
|
const shiftfilters = [];
|
||||||
|
const shiftcourses = [];
|
||||||
|
const items = [];
|
||||||
|
for(let i = this.value.slot; i < this.value.slot + span; i++) {
|
||||||
|
const busyFilter = this.checkFilterSlotBusy(i);
|
||||||
|
if (busyFilter) {
|
||||||
|
const nextlyr = this.nextFreeFilterLayer(i);
|
||||||
|
items.push({
|
||||||
|
id: busyFilter.id,
|
||||||
|
layer: nextlyr,
|
||||||
|
line_id: this.line.id,
|
||||||
|
slot: busyFilter.slot,
|
||||||
|
});
|
||||||
|
busyFilter.layer = nextlyr;
|
||||||
|
}
|
||||||
|
const busyCourse = this.checkCourseSlotBusy(i);
|
||||||
|
if (busyCourse && busyCourse.id != this.value.id) {
|
||||||
|
const nextlyr = this.nextFreeCourseLayer(i);
|
||||||
|
items.push({
|
||||||
|
id: busyCourse.id,
|
||||||
|
layer: nextlyr,
|
||||||
|
line_id: this.line.id,
|
||||||
|
slot: busyCourse.slot,
|
||||||
|
});
|
||||||
|
busyCourse.layer = nextlyr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (items.length > 0){
|
||||||
|
call([{
|
||||||
|
methodname: 'local_treestudyplan_reorder_studyitems',
|
||||||
|
args: { items: items }
|
||||||
|
}])[0].catch(notification.exception).done((response) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
change_span(span) {
|
change_span(span) {
|
||||||
const self=this;
|
const self=this;
|
||||||
|
this.shift_collisions(span);
|
||||||
return call([{
|
return call([{
|
||||||
methodname: 'local_treestudyplan_set_studyitem_span',
|
methodname: 'local_treestudyplan_set_studyitem_span',
|
||||||
args: { id: self.value.id,
|
args: { id: self.value.id,
|
||||||
|
@ -2463,13 +2523,13 @@ export default {
|
||||||
</span>
|
</span>
|
||||||
<span class="ml-1" v-b-tooltip.hover.bottomleft :title="text.periodspan_desc"
|
<span class="ml-1" v-b-tooltip.hover.bottomleft :title="text.periodspan_desc"
|
||||||
>{{ text.periodspan
|
>{{ text.periodspan
|
||||||
}} <b-form-select
|
}} <b-form-select v-if="maxspan > 1"
|
||||||
class=""
|
class=""
|
||||||
size="sm" @change="change_span" v-model="value.span">
|
size="sm" @change="change_span" v-model="value.span">
|
||||||
<b-form-select-option v-for="(n,i) in maxspan" :value='n' :key='i'
|
<b-form-select-option v-for="(n,i) in maxspan" :value='n' :key='i'
|
||||||
>{{ n }}</b-form-select-option>
|
>{{ n }}</b-form-select-option>
|
||||||
</b-form-select
|
</b-form-select
|
||||||
> {{
|
><span v-else>{{value.span}}</span> {{
|
||||||
(value.span == 1)?text.period.toLowerCase():text.periods.toLowerCase()
|
(value.span == 1)?text.period.toLowerCase():text.periods.toLowerCase()
|
||||||
}}<i
|
}}<i
|
||||||
class="fa fa-question-circle text-black-50"
|
class="fa fa-question-circle text-black-50"
|
||||||
|
@ -2895,6 +2955,7 @@ export default {
|
||||||
@deleterq="deleteItem"
|
@deleterq="deleteItem"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
:plan='plan'
|
:plan='plan'
|
||||||
|
:line='line'
|
||||||
:page='page'
|
:page='page'
|
||||||
:period='period'
|
:period='period'
|
||||||
:maxspan='maxspan'
|
:maxspan='maxspan'
|
||||||
|
@ -3033,6 +3094,10 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
default(){ return null;},
|
default(){ return null;},
|
||||||
},
|
},
|
||||||
|
line:{
|
||||||
|
type: Object,
|
||||||
|
default(){ return null;},
|
||||||
|
},
|
||||||
page: {
|
page: {
|
||||||
type: Object, // PAge data
|
type: Object, // PAge data
|
||||||
default() { return null;}
|
default() { return null;}
|
||||||
|
@ -3199,6 +3264,7 @@ export default {
|
||||||
class="mt-1"
|
class="mt-1"
|
||||||
:maxspan="maxspan"
|
:maxspan="maxspan"
|
||||||
:page="page"
|
:page="page"
|
||||||
|
:line="line"
|
||||||
:period="period"
|
:period="period"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
></t-item-timing-checker>
|
></t-item-timing-checker>
|
||||||
|
|
Loading…
Reference in a new issue