Stage 1 of reworking studyplan base to grid layout

This commit is contained in:
PMKuipers 2023-07-07 23:17:21 +02:00
parent 48e4203761
commit 1932883880
2 changed files with 152 additions and 63 deletions

View File

@ -1118,6 +1118,17 @@ export default {
ItemEventBus.$emit('redrawLines'); ItemEventBus.$emit('redrawLines');
}, },
computed: { computed: {
columns() {
return 1+ (this.value.slots * 2);
},
columns_stylerule() {
// Uses css variables, so width for slots and filters can be configured in css
let s = "grid-template-columns: var(--studyplan-filter-width)"; // use css variable here
for(let i=0; i<this.value.slots;i++){
s+= " var(--studyplan-course-width) var(--studyplan-filter-width)";
}
return s+";";
}
}, },
methods: { methods: {
slotsempty(slots) { slotsempty(slots) {
@ -1295,8 +1306,8 @@ export default {
<t-studyplan-advanced v-model="value"></t-studyplan-advanced> <t-studyplan-advanced v-model="value"></t-studyplan-advanced>
</span> </span>
</div> </div>
<div class='t-studyplan-content'> <div class='t-studyplan-content-edit' v-if="edit.studyline.editmode">
<drop-list v-if="edit.studyline.editmode" <drop-list
:items="value.studylines" :items="value.studylines"
class="t-slot-droplist" class="t-slot-droplist"
:accepts-type="'studyline-'+value.id" :accepts-type="'studyline-'+value.id"
@ -1315,56 +1326,57 @@ export default {
<template v-slot:drag-image> <template v-slot:drag-image>
<i class="fa fa-arrows text-primary"></i> <i class="fa fa-arrows text-primary"></i>
</template> </template>
<t-studyline <t-studyline-edit
:color='item.color' v-model="item"
:name='item.name'
:code='item.shortname'
:editable='true'
:deletable='slotsempty(item.slots)'
:sequence='item.sequence'
:numlines='value.studylines.length' :numlines='value.studylines.length'
@edit='editLineStart(item)' @edit='editLineStart(item)'
@delete='deleteLine(value,item)' @delete='deleteLine(value,item)'
> >
<template v-slot:movebox><i class='fa fa-arrows text-primary'></i></template>
<div v-if="!slotsempty(item.slots)"> {{ text.editmode_modules_hidden}} </div> <div v-if="!slotsempty(item.slots)"> {{ text.editmode_modules_hidden}} </div>
</t-studyline> </t-studyline-edit>
</drag> </drag>
</template> </template>
</drop-list> </drop-list>
<template v-else> </div>
<t-studyline v-for="(item,lineindex) in value.studylines" <div class='t-studyplan-content' v-else>
:key="item.id" <!-- First paint the headings-->
:color='item.color' <div class='t-studyplan-headings'>
:name='item.name' <t-studyline-heading v-for="(line,lineindex) in value.studylines"
:code='item.shortname' :key="line.id"
:sequence='lineindex' v-model="value.studylines[lineindex]"
:numlines='value.studylines.length' :numlines='value.studylines.length'
@edit='editLineStart(item)' ></t-studyline-heading>
> </div>
<template v-for="(n,index) in (value.slots+1)"> <!-- Next, paint all the cells in the scrollable -->
<t-studyline-slot <div class="t-studyplan-scrollable" :style="columns_stylerule">
<!-- Line by line add the items -->
<!-- The grid layout handles putting it in rows and columns -->
<template v-for="(line,lineindex) in value.studylines"
><template v-for="(n,index) in (value.slots+1)"
><t-studyline-slot
v-if="index > 0" v-if="index > 0"
type='gradable' type='gradable'
v-model="item.slots[index].competencies" v-model="line.slots[index].competencies"
:key="'c-'+index" :key="'c-'+lineindex+'-'+index"
:slotindex="index" :slotindex="index"
:lineid="item.id" :line="line"
:plan="value"> :plan="value">
</t-studyline-slot> </t-studyline-slot
<t-studyline-slot ><t-studyline-slot
type='filter' type='filter'
v-model="item.slots[index].filters" v-model="line.slots[index].filters"
:key="'f-'+index" :key="'f-'+lineindex+'-'+index"
:slotindex="index" :slotindex="index"
:lineid="item.id" :line="line"
:plan="value" :plan="value"
> >
</t-studyline-slot> </t-studyline-slot
</template> ></template
</t-studyline> ></template>
</template> </div>
<div class='t-studyplan-content-timeline'>
</div>
<div :id="'studyplan-linewrapper-'+value.id" class='l-leaderline-linewrapper'></div> <div :id="'studyplan-linewrapper-'+value.id" class='l-leaderline-linewrapper'></div>
</div> </div>
<div v-if="edit.studyline.editmode" class='t-studyline-add'> <div v-if="edit.studyline.editmode" class='t-studyline-add'>
@ -1448,8 +1460,17 @@ export default {
/* /*
* T-STUDYLINE-HEADER * T-STUDYLINE-HEADER
*/ */
Vue.component('t-studyline-header', { Vue.component('t-studyline-heading', {
props: ['color','name','code', 'slots','sequence','numlines',], props: {
value : {
type: Object,
default: function(){ return {};},
},
numlines: {
type: Number,
default: 1,
},
},
data() { data() {
return { return {
}; };
@ -1460,11 +1481,12 @@ export default {
methods: { methods: {
}, },
template: ` template: `
<div :class="'t-studyline ' + (sequence%2)?'odd':'even' + <div :class="'t-studyline t-studyline-heading' + ((value.sequence%2)?' odd':' even') +
(sequence==0?' first':'') + (sequence==numlines-1?' last':'')" > (value.sequence==0?' first':'') + (value.sequence==numlines?' last':'')"
<div class="t-studyline-handle" :style="'background-color: ' + color"></div> :data-studyline="value.id" :data-sequence="value.sequence" :data-numlines="numlines"
><div class="t-studyline-handle" :style="'background-color: ' + value.color"></div>
<div class="t-studyline-title"> <div class="t-studyline-title">
<abbr v-b-tooltip.hover :title="name">{{ code }}</abbr> <abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
</div> </div>
</div> </div>
`, `,
@ -1473,14 +1495,47 @@ export default {
/* /*
* T-STUDYLINE (Used only for study line edit mode) * T-STUDYLINE (Used only for study line edit mode)
*/ */
Vue.component('t-studyline', { Vue.component('t-studyline-edit', {
props: ['color','name','code', 'slots','deletable','editable','sequence','numlines'], props: {
value : {
type: Object,
default: function(){ return {};},
},
numlines: {
type: Number,
default: 1,
},
/*
:color='value.color'
:name='value.name'
:code='value.shortname'
:sequence='value.sequence'
*/
},
data() { data() {
return { return {
}; };
}, },
computed: { computed: {
deletable() {
// Check if all the slots are empty
const slots = this.value.slots;
if(Array.isArray(slots)){
let count = 0;
for(let i = 0; i < slots.length; i++) {
if(Array.isArray(slots[i].competencies)){
count += slots[i].competencies.length;
}
if(Array.isArray(slots[i].filters)){
count += slots[i].filters.length;
}
}
return (count == 0);
} else {
return false;
}
}
}, },
methods: { methods: {
onEdit() { onEdit() {
@ -1492,22 +1547,19 @@ export default {
}, },
template: ` template: `
<div :class="'t-studyline ' + (!editable?((sequence%2)?'odd':'even'):'') + <div :class="'t-studyline ' + (value.sequence==0?' first':'') + (value.sequence==numlines-1?' last':'')" >
(sequence==0?' first':'') + (sequence==numlines-1?' last':'')" > <div class="t-studyline-handle" :style="'background-color: ' + value.color"></div>
<div class="t-studyline-handle" :style="'background-color: ' + color"></div>
<div class="t-studyline-title"> <div class="t-studyline-title">
<div> <div>
<slot name='movebox'> <i class='fa fa-arrows text-primary'></i>
</slot> <abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
<abbr v-b-tooltip.hover :title="name">{{ code }}</abbr>
</div> </div>
</div> </div>
<div v-if="editable" class='t-studyline-editmode-content'> <div class='t-studyline-editmode-content'>
<slot></slot> <slot></slot>
</div> </div>
<slot v-else></slot>
<div class='controlbox' v-if='editable || deletable'> <div class='controlbox' v-if='editable || deletable'>
<span class='control editable' v-if='editable'> <span class='control editable'>
<a href='#' @click='onEdit'><i class='fa fa-pencil'></i></a> <a href='#' @click='onEdit'><i class='fa fa-pencil'></i></a>
</span> </span>
<span class='control deletable'> <span class='control deletable'>
@ -1528,9 +1580,9 @@ export default {
type: Number, type: Number,
default: '', default: '',
}, },
lineid : { line : {
type: Number, type: Object,
default: '', default(){ return null;},
}, },
value: { value: {
type: Array, type: Array,
@ -1539,7 +1591,12 @@ export default {
plan: { plan: {
type: Object, type: Object,
default(){ return null;}, default(){ return null;},
} },
active: {
type: Boolean,
default: false,
},
}, },
computed: { computed: {
listtype() { listtype() {
@ -1586,7 +1643,7 @@ export default {
call([{ call([{
methodname: 'local_treestudyplan_add_studyitem', methodname: 'local_treestudyplan_add_studyitem',
args: { args: {
"line_id": self.lineid, "line_id": self.line.id,
"slot" : self.slotindex, "slot" : self.slotindex,
"type": 'competency', "type": 'competency',
"details": { "details": {
@ -1610,7 +1667,7 @@ export default {
call([{ call([{
methodname: 'local_treestudyplan_add_studyitem', methodname: 'local_treestudyplan_add_studyitem',
args: { args: {
"line_id": self.lineid, "line_id": self.line.id,
"slot" : self.slotindex, "slot" : self.slotindex,
"type": 'course', "type": 'course',
"details": { "details": {
@ -1634,7 +1691,7 @@ export default {
call([{ call([{
methodname: 'local_treestudyplan_add_studyitem', methodname: 'local_treestudyplan_add_studyitem',
args: { args: {
"line_id": self.lineid, "line_id": self.line.id,
"slot" : self.slotindex, "slot" : self.slotindex,
"type": event.data.type, "type": event.data.type,
"details":{ "details":{
@ -1678,7 +1735,7 @@ export default {
for(let idx in self.value) for(let idx in self.value)
{ {
self.value[idx].layer = idx; self.value[idx].layer = idx;
items.push({'id': self.value[idx].id,'layer': idx, 'slot': this.slotindex, 'line_id': this.lineid}); items.push({'id': self.value[idx].id,'layer': idx, 'slot': this.slotindex, 'line_id': this.line.id});
} }
return call([{ return call([{
methodname: 'local_treestudyplan_reorder_studyitems', methodname: 'local_treestudyplan_reorder_studyitems',
@ -1692,7 +1749,10 @@ export default {
} }
}, },
template: ` template: `
<div :class="'t-studyline-slot '+type + ' t-studyline-slot-'+slotindex"> <div :class="'t-studyline-slot '+type + ' t-studyline-slot-'+slotindex + ((slotindex==0)?'t-studyline-firstcolumn':'')
+ ((line.sequence%2)?' odd':' even') "
:data-studyline="line.id"
>
<drop-list <drop-list
:items="value" :items="value"
:class="'t-slot-droplist '+type" :class="'t-slot-droplist '+type"

View File

@ -1,4 +1,9 @@
/* stylelint-disable length-zero-no-unit, color-hex-case, color-hex-length, no-eol-whitespace, unit-blacklist, block-no-empty */ /* stylelint-disable length-zero-no-unit, color-hex-case, color-hex-length, no-eol-whitespace, unit-blacklist, block-no-empty */
:root {
}
.t-toolbox-preface { .t-toolbox-preface {
margin: 10px; margin: 10px;
} }
@ -8,11 +13,35 @@
min-height: 500px; min-height: 500px;
} }
.t-studyplan-content {
display: flex;
}
.t-studyplan-headings {
display: block;
}
.t-studyplan-wrapper {
display: block;
}
.t-studyplan-scrollable {
display: grid;
overflow-x: scroll;
/* grid-template-columns will be set in the style attribute */
/* Use the variables below to specify width for filter spots and course spots */
--studyplan-filter-width: auto; /* better leave this at auto for now*/
--studyplan-course-width: auto; /* better leave this at auto for now*/
}
.t-studyplan-column-heading {
color: inherit; /* placeholder */
}
ul.dropdown-menu.show { ul.dropdown-menu.show {
background-color: white; background-color: white;
} }
.t-studyline { .t-studyline {
width: min-content; width: min-content;
display: grid; display: grid;