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');
},
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: {
slotsempty(slots) {
@ -1295,8 +1306,8 @@ export default {
<t-studyplan-advanced v-model="value"></t-studyplan-advanced>
</span>
</div>
<div class='t-studyplan-content'>
<drop-list v-if="edit.studyline.editmode"
<div class='t-studyplan-content-edit' v-if="edit.studyline.editmode">
<drop-list
:items="value.studylines"
class="t-slot-droplist"
:accepts-type="'studyline-'+value.id"
@ -1315,56 +1326,57 @@ export default {
<template v-slot:drag-image>
<i class="fa fa-arrows text-primary"></i>
</template>
<t-studyline
:color='item.color'
:name='item.name'
:code='item.shortname'
:editable='true'
:deletable='slotsempty(item.slots)'
:sequence='item.sequence'
<t-studyline-edit
v-model="item"
:numlines='value.studylines.length'
@edit='editLineStart(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>
</t-studyline>
</t-studyline-edit>
</drag>
</template>
</drop-list>
<template v-else>
<t-studyline v-for="(item,lineindex) in value.studylines"
:key="item.id"
:color='item.color'
:name='item.name'
:code='item.shortname'
:sequence='lineindex'
</div>
<div class='t-studyplan-content' v-else>
<!-- First paint the headings-->
<div class='t-studyplan-headings'>
<t-studyline-heading v-for="(line,lineindex) in value.studylines"
:key="line.id"
v-model="value.studylines[lineindex]"
:numlines='value.studylines.length'
@edit='editLineStart(item)'
>
<template v-for="(n,index) in (value.slots+1)">
<t-studyline-slot
></t-studyline-heading>
</div>
<!-- Next, paint all the cells in the scrollable -->
<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"
type='gradable'
v-model="item.slots[index].competencies"
:key="'c-'+index"
v-model="line.slots[index].competencies"
:key="'c-'+lineindex+'-'+index"
:slotindex="index"
:lineid="item.id"
:line="line"
:plan="value">
</t-studyline-slot>
<t-studyline-slot
</t-studyline-slot
><t-studyline-slot
type='filter'
v-model="item.slots[index].filters"
:key="'f-'+index"
v-model="line.slots[index].filters"
:key="'f-'+lineindex+'-'+index"
:slotindex="index"
:lineid="item.id"
:line="line"
:plan="value"
>
</t-studyline-slot>
</template>
</t-studyline>
</template>
</t-studyline-slot
></template
></template>
</div>
<div class='t-studyplan-content-timeline'>
</div>
<div :id="'studyplan-linewrapper-'+value.id" class='l-leaderline-linewrapper'></div>
</div>
<div v-if="edit.studyline.editmode" class='t-studyline-add'>
@ -1448,8 +1460,17 @@ export default {
/*
* T-STUDYLINE-HEADER
*/
Vue.component('t-studyline-header', {
props: ['color','name','code', 'slots','sequence','numlines',],
Vue.component('t-studyline-heading', {
props: {
value : {
type: Object,
default: function(){ return {};},
},
numlines: {
type: Number,
default: 1,
},
},
data() {
return {
};
@ -1460,11 +1481,12 @@ export default {
methods: {
},
template: `
<div :class="'t-studyline ' + (sequence%2)?'odd':'even' +
(sequence==0?' first':'') + (sequence==numlines-1?' last':'')" >
<div class="t-studyline-handle" :style="'background-color: ' + color"></div>
<div :class="'t-studyline t-studyline-heading' + ((value.sequence%2)?' odd':' even') +
(value.sequence==0?' first':'') + (value.sequence==numlines?' last':'')"
: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">
<abbr v-b-tooltip.hover :title="name">{{ code }}</abbr>
<abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
</div>
</div>
`,
@ -1473,14 +1495,47 @@ export default {
/*
* T-STUDYLINE (Used only for study line edit mode)
*/
Vue.component('t-studyline', {
props: ['color','name','code', 'slots','deletable','editable','sequence','numlines'],
Vue.component('t-studyline-edit', {
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() {
return {
};
},
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: {
onEdit() {
@ -1492,22 +1547,19 @@ export default {
},
template: `
<div :class="'t-studyline ' + (!editable?((sequence%2)?'odd':'even'):'') +
(sequence==0?' first':'') + (sequence==numlines-1?' last':'')" >
<div class="t-studyline-handle" :style="'background-color: ' + color"></div>
<div :class="'t-studyline ' + (value.sequence==0?' first':'') + (value.sequence==numlines-1?' last':'')" >
<div class="t-studyline-handle" :style="'background-color: ' + value.color"></div>
<div class="t-studyline-title">
<div>
<slot name='movebox'>
</slot>
<abbr v-b-tooltip.hover :title="name">{{ code }}</abbr>
<i class='fa fa-arrows text-primary'></i>
<abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
</div>
</div>
<div v-if="editable" class='t-studyline-editmode-content'>
<div class='t-studyline-editmode-content'>
<slot></slot>
</div>
<slot v-else></slot>
<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>
</span>
<span class='control deletable'>
@ -1528,9 +1580,9 @@ export default {
type: Number,
default: '',
},
lineid : {
type: Number,
default: '',
line : {
type: Object,
default(){ return null;},
},
value: {
type: Array,
@ -1539,7 +1591,12 @@ export default {
plan: {
type: Object,
default(){ return null;},
}
},
active: {
type: Boolean,
default: false,
},
},
computed: {
listtype() {
@ -1586,7 +1643,7 @@ export default {
call([{
methodname: 'local_treestudyplan_add_studyitem',
args: {
"line_id": self.lineid,
"line_id": self.line.id,
"slot" : self.slotindex,
"type": 'competency',
"details": {
@ -1610,7 +1667,7 @@ export default {
call([{
methodname: 'local_treestudyplan_add_studyitem',
args: {
"line_id": self.lineid,
"line_id": self.line.id,
"slot" : self.slotindex,
"type": 'course',
"details": {
@ -1634,7 +1691,7 @@ export default {
call([{
methodname: 'local_treestudyplan_add_studyitem',
args: {
"line_id": self.lineid,
"line_id": self.line.id,
"slot" : self.slotindex,
"type": event.data.type,
"details":{
@ -1678,7 +1735,7 @@ export default {
for(let idx in self.value)
{
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([{
methodname: 'local_treestudyplan_reorder_studyitems',
@ -1692,7 +1749,10 @@ export default {
}
},
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
:items="value"
: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 */
:root {
}
.t-toolbox-preface {
margin: 10px;
}
@ -8,11 +13,35 @@
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 {
background-color: white;
}
.t-studyline {
width: min-content;
display: grid;