Current period highlight

This commit is contained in:
PMKuipers 2023-08-03 18:44:57 +02:00
parent 21306c0bc3
commit 0a994d82bb
6 changed files with 164 additions and 26 deletions

View file

@ -322,6 +322,7 @@ export default {
:line="line" :line="line"
:plan="value" :plan="value"
:page="page" :page="page"
:period="page.perioddesc[index-1]"
:guestmode='guestmode' :guestmode='guestmode'
:teachermode='teachermode' :teachermode='teachermode'
:layer="layeridx-1" :layer="layeridx-1"
@ -446,6 +447,10 @@ export default {
teachermode: { teachermode: {
type: Boolean, type: Boolean,
default: false, default: false,
},
period: {
type: Object,
default(){ return null;},
} }
}, },
mounted() { mounted() {
@ -469,6 +474,17 @@ export default {
} }
return null; return null;
}, },
current(){
if( this.period && this.period.startdate && this.period.enddate){
const now = new Date();
const pstart = new Date(this.period.startdate);
const pend = new Date(this.period.enddate);
return (now >= pstart && now < pend);
}
else {
return false;
}
}
}, },
data() { data() {
return { return {
@ -478,7 +494,7 @@ export default {
}, },
template: ` template: `
<div :class=" 'r-studyline-slot ' + type + ' ' <div :class=" 'r-studyline-slot ' + type + ' ' + (current?'current ':' ')
+ 'r-studyline-slot-' + slotindex + ' ' + 'r-studyline-slot-' + slotindex + ' '
+ ((slotindex==0)?'r-studyline-firstcolumn ':' ')" + ((slotindex==0)?'r-studyline-firstcolumn ':' ')"
:data-studyline="line.id" ref="sizeElement" :data-studyline="line.id" ref="sizeElement"

View file

@ -15,9 +15,12 @@ import {objCopy,transportItem} from './studyplan-processor';
import Debugger from './debugger'; import Debugger from './debugger';
import {download,upload} from './downloader'; import {download,upload} from './downloader';
const STUDYPLAN_EDITOR_FIELDS = ['name','shortname','description','context_id', const STUDYPLAN_EDITOR_FIELDS =
'slots','startdate','enddate','aggregation','aggregation_config']; ['name','shortname','description','context_id', 'aggregation','aggregation_config'];
const PERIOD_EDITOR_FIELDS = ['fullname','shortname','startdate','enddate']; const STUDYPLAN_EDITOR_PAGE_FIELDS = //TODO: Add 'fullname', 'shortname' and 'description' when implementing proper page management
['context_id', 'periods','startdate','enddate'];
const PERIOD_EDITOR_FIELDS =
['fullname','shortname','startdate','enddate'];
export default { export default {
STUDYPLAN_EDITOR_FIELDS: STUDYPLAN_EDITOR_FIELDS, // make copy available in plugin STUDYPLAN_EDITOR_FIELDS: STUDYPLAN_EDITOR_FIELDS, // make copy available in plugin
@ -512,7 +515,7 @@ export default {
shortname: '', shortname: '',
description: '', description: '',
context_id: 1, context_id: 1,
slots : 4, periods : 4,
startdate: (new Date()).getFullYear() + '-08-01', startdate: (new Date()).getFullYear() + '-08-01',
enddate: ((new Date()).getFullYear()+1) + '-08-01', enddate: ((new Date()).getFullYear()+1) + '-08-01',
aggregation: 'bistate', aggregation: 'bistate',
@ -568,7 +571,9 @@ export default {
methods: { methods: {
editPlanStart(){ editPlanStart(){
if(this.mode != 'create'){ if(this.mode != 'create'){
objCopy(this.editdata,this.value.pages[0],STUDYPLAN_EDITOR_PAGE_FIELDS);
objCopy(this.editdata,this.value,STUDYPLAN_EDITOR_FIELDS); objCopy(this.editdata,this.value,STUDYPLAN_EDITOR_FIELDS);
} }
// decode the aggregation config data that is stored // decode the aggregation config data that is stored
if(this.editdata.aggregation_config && this.editdata.aggregation_config.length > 0){ if(this.editdata.aggregation_config && this.editdata.aggregation_config.length > 0){
@ -596,6 +601,7 @@ export default {
this.editdata.aggregation_config = JSON.stringify(this.aggregation_parsed[this.editdata.aggregation]); this.editdata.aggregation_config = JSON.stringify(this.aggregation_parsed[this.editdata.aggregation]);
} }
objCopy(args,this.editdata,STUDYPLAN_EDITOR_FIELDS); objCopy(args,this.editdata,STUDYPLAN_EDITOR_FIELDS);
objCopy(args,this.editdata,STUDYPLAN_EDITOR_PAGE_FIELDS);
call([{ call([{
methodname: method, methodname: method,
@ -609,7 +615,7 @@ export default {
shortname: '', shortname: '',
description: '', description: '',
context_id: 1, context_id: 1,
slots : 4, periods : 4,
startdate: (new Date()).getFullYear() + '-08-01', startdate: (new Date()).getFullYear() + '-08-01',
enddate: ((new Date()).getFullYear()+1) + '-08-01', enddate: ((new Date()).getFullYear()+1) + '-08-01',
aggregation: 'bistate', aggregation: 'bistate',
@ -685,7 +691,7 @@ export default {
<b-row> <b-row>
<b-col cols="4">{{ text.studyplan_slots}}</b-col> <b-col cols="4">{{ text.studyplan_slots}}</b-col>
<b-col cols="8"> <b-col cols="8">
<b-form-input type=number v-model="editdata.slots"></b-form-input> <b-form-input type=number v-model="editdata.periods"></b-form-input>
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row>
@ -1859,6 +1865,17 @@ export default {
}, },
courseHoverDummy(){ courseHoverDummy(){
return {course: this.hover.component}; return {course: this.hover.component};
},
current(){
if( this.period && this.period.startdate && this.period.enddate){
const now = new Date();
const pstart = new Date(this.period.startdate);
const pend = new Date(this.period.enddate);
return (now >= pstart && now < pend);
}
else {
return false;
}
} }
}, },
data() { data() {
@ -2041,7 +2058,8 @@ export default {
} }
}, },
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 ':' ')"
:data-studyline="line.id" ref="main" :data-studyline="line.id" ref="main"
><drag v-if="item" ><drag v-if="item"

View file

@ -161,14 +161,26 @@ export default {
}, },
enddate(){ enddate(){
return format_date(this.value.enddate); return format_date(this.value.enddate);
},
current(){
if( this.value && this.value.startdate && this.value.enddate){
const now = new Date();
const pstart = new Date(this.value.startdate);
const pend = new Date(this.value.enddate);
return (now >= pstart && now < pend);
} }
else {
return false;
}
}
}, },
data() { data() {
return { return {
}; };
}, },
template: ` template: `
<div class="s-studyline-header-period" ref="main" <div :class="'s-studyline-header-period ' + (current?'current ':' ')" ref="main"
><p><abbr :id="'s-period-'+value.id" :title="value.fullname">{{ value.shortname }}</abbr> ><p><abbr :id="'s-period-'+value.id" :title="value.fullname">{{ value.shortname }}</abbr>
<b-tooltip <b-tooltip
:target="'s-period-'+value.id" triggers="hover" :target="'s-period-'+value.id" triggers="hover"

View file

@ -177,7 +177,7 @@ class studyplan {
public static function add($fields){ public static function add($fields){
global $CFG, $DB; global $CFG, $DB;
$addable = ['name','shortname','description','context_id','slots','startdate','enddate','aggregation','aggregation_config']; $addable = ['name','shortname','description','context_id','periods','startdate','enddate','aggregation','aggregation_config'];
$info = ['enddate' => null ]; $info = ['enddate' => null ];
foreach($addable as $f){ foreach($addable as $f){
if(array_key_exists($f,$fields)){ if(array_key_exists($f,$fields)){
@ -192,15 +192,13 @@ class studyplan {
// Add a single page and copy the names.This keeps the data sane until the upgrade to // Add a single page and copy the names.This keeps the data sane until the upgrade to
// real page management is done // real page management is done
// TODO: Remove this when proper page management is implemented // TODO: Remove this when proper page management is implemented
$pageaddable = ['name','shortname','description','slots','startdate','enddate']; $pageaddable = ['name','shortname','description','periods','startdate','enddate'];
$pageinfo = ['studyplan_id' => $id]; $pageinfo = ['studyplan_id' => $id];
foreach($pageaddable as $f){ foreach($pageaddable as $f){
if(array_key_exists($f,$fields)){ if(array_key_exists($f,$fields)){
if($f == "name"){ if($f == "name"){
$pageinfo["fullname"] = $fields[$f]; $pageinfo["fullname"] = $fields[$f];
} else if ($f == "slots") { } else {
$pageinfo["periods"] = $fields[$f];
}else {
$pageinfo[$f] = $fields[$f]; $pageinfo[$f] = $fields[$f];
} }
} }
@ -214,7 +212,7 @@ class studyplan {
public function edit($fields){ public function edit($fields){
global $DB; global $DB;
$editable = ['name','shortname','description','context_id','slots','startdate','enddate','aggregation','aggregation_config']; $editable = ['name','shortname','description','context_id','periods','startdate','enddate','aggregation','aggregation_config'];
$info = ['id' => $this->id,]; $info = ['id' => $this->id,];
foreach($editable as $f){ foreach($editable as $f){
if(array_key_exists($f,$fields)){ if(array_key_exists($f,$fields)){
@ -237,14 +235,12 @@ class studyplan {
if(count($this->pages()) == 1){ if(count($this->pages()) == 1){
// update the info to the page as well // update the info to the page as well
$page = $this->pages()[0]; $page = $this->pages()[0];
$pageeditable = ['name','shortname','description','slots','startdate','enddate']; $pageeditable = ['name','shortname','description','periods','startdate','enddate'];
$pageinfo = []; $pageinfo = [];
foreach($pageeditable as $f){ foreach($pageeditable as $f){
if(array_key_exists($f,$fields)){ if(array_key_exists($f,$fields)){
if($f == "name"){ if($f == "name"){
$pageinfo["fullname"] = $fields[$f]; $pageinfo["fullname"] = $fields[$f];
} else if ($f == "slots") {
$pageinfo["periods"] = $fields[$f];
}else { }else {
$pageinfo[$f] = $fields[$f]; $pageinfo[$f] = $fields[$f];
} }

View file

@ -120,7 +120,7 @@ class studyplanservice extends \external_api
"name" => new \external_value(PARAM_TEXT, 'name of studyplan'), "name" => new \external_value(PARAM_TEXT, 'name of studyplan'),
"shortname"=> new \external_value(PARAM_TEXT, 'shortname of studyplan'), "shortname"=> new \external_value(PARAM_TEXT, 'shortname of studyplan'),
"description"=> new \external_value(PARAM_TEXT, 'description of studyplan'), "description"=> new \external_value(PARAM_TEXT, 'description of studyplan'),
"slots" => new \external_value(PARAM_INT, 'number of slots in studyplan'), "periods" => new \external_value(PARAM_INT, 'number of periods in studyplan'),
"startdate" => new \external_value(PARAM_TEXT, 'start date of studyplan'), "startdate" => new \external_value(PARAM_TEXT, 'start date of studyplan'),
"enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'), "enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'),
"aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator',VALUE_DEFAULT), "aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator',VALUE_DEFAULT),
@ -134,7 +134,7 @@ class studyplanservice extends \external_api
return studyplan::simple_structure(); return studyplan::simple_structure();
} }
public static function add_studyplan($name, $shortname,$description, $slots, $startdate, $enddate, $aggregation="bistate", $aggregation_config='',$context_id=0) public static function add_studyplan($name, $shortname,$description, $periods, $startdate, $enddate, $aggregation="bistate", $aggregation_config='',$context_id=0)
{ {
// Check if we have the proper rights for the requested context // Check if we have the proper rights for the requested context
$context = webservicehelper::find_context($context_id); $context = webservicehelper::find_context($context_id);
@ -144,7 +144,7 @@ class studyplanservice extends \external_api
'name' => $name, 'name' => $name,
'shortname' => $shortname, 'shortname' => $shortname,
'description' => $description, 'description' => $description,
'slots' => $slots, 'periods' => $periods,
'startdate' => $startdate, 'startdate' => $startdate,
'enddate' => empty($enddate)?null:$enddate, 'enddate' => empty($enddate)?null:$enddate,
'aggregation' => $aggregation, 'aggregation' => $aggregation,
@ -167,7 +167,7 @@ class studyplanservice extends \external_api
"name" => new \external_value(PARAM_TEXT, 'name of studyplan'), "name" => new \external_value(PARAM_TEXT, 'name of studyplan'),
"shortname"=> new \external_value(PARAM_TEXT, 'shortname of studyplan'), "shortname"=> new \external_value(PARAM_TEXT, 'shortname of studyplan'),
"description"=> new \external_value(PARAM_TEXT, 'description of studyplan'), "description"=> new \external_value(PARAM_TEXT, 'description of studyplan'),
"slots" => new \external_value(PARAM_INT, 'number of slots in studyplan'), "periods" => new \external_value(PARAM_INT, 'number of periods in studyplan'),
"startdate" => new \external_value(PARAM_TEXT, 'start date of studyplan'), "startdate" => new \external_value(PARAM_TEXT, 'start date of studyplan'),
"enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'), "enddate" => new \external_value(PARAM_TEXT, 'end date of studyplan'),
"aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator',VALUE_DEFAULT), "aggregation" => new \external_value(PARAM_TEXT, 'selected aggregator',VALUE_DEFAULT),
@ -181,7 +181,7 @@ class studyplanservice extends \external_api
return studyplan::simple_structure(); return studyplan::simple_structure();
} }
public static function edit_studyplan($id, $name, $shortname, $description, $slots, $startdate, $enddate, $aggregation="bistate", $aggregation_config='',$context_id=0) public static function edit_studyplan($id, $name, $shortname, $description, $periods, $startdate, $enddate, $aggregation="bistate", $aggregation_config='',$context_id=0)
{ {
// Validate access in the intended context // Validate access in the intended context
$context = webservicehelper::find_context($context_id); $context = webservicehelper::find_context($context_id);
@ -194,7 +194,7 @@ class studyplanservice extends \external_api
'name' => $name, 'name' => $name,
'shortname' => $shortname, 'shortname' => $shortname,
'description' => $description, 'description' => $description,
'slots' => $slots, 'periods' => $periods,
'startdate' => $startdate, 'startdate' => $startdate,
'enddate' => $enddate, 'enddate' => $enddate,
'aggregation' => $aggregation, 'aggregation' => $aggregation,
@ -1053,6 +1053,7 @@ class studyplanservice extends \external_api
webservicehelper::require_capabilities(self::CAP_EDIT,$plan->context()); webservicehelper::require_capabilities(self::CAP_EDIT,$plan->context());
// FIXME: Make sure this gets called for the page instead of the studyplan // FIXME: Make sure this gets called for the page instead of the studyplan
// Once proper page management is implemented
$result = $plan->pages()[0]->import_studylines($content,$format); $result = $plan->pages()[0]->import_studylines($content,$format);
return ($result?success::success():success::fail())->model(); return ($result?success::success():success::fail())->model();
} }
@ -1102,7 +1103,7 @@ class studyplanservice extends \external_api
if (file_exists($modmoodleform)) { if (file_exists($modmoodleform)) {
require_once($modmoodleform); require_once($modmoodleform);
} else { } else {
print_error('noformdesc'); throw new \moodle_exception('noformdesc', 'error');
} }
$mformclassname = 'mod_'.$module->name.'_mod_form'; $mformclassname = 'mod_'.$module->name.'_mod_form';

View file

@ -1,4 +1,10 @@
/* 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 */
html { /* not :root, so we can override these colors in the :root field if needed */
--less-light: color-mix(in srgb, var(--light) 80%, #ccc);
--highlight: var(--info);
--highlight-mix: 10%;
}
.t-toolbox-preface { .t-toolbox-preface {
margin: 10px; margin: 10px;
@ -263,6 +269,85 @@ ul.t-competency-list li {
margin-left: 10px; margin-left: 10px;
} }
.t-studyline-slot.gradable.current.odd,
.r-studyline-slot.gradable.current.odd {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix));
background-color: var(--hlcol);
position: relative;
}
.t-studyline-slot.gradable.current.odd:before,
.r-studyline-slot.gradable.current.odd:before {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix));
box-shadow: -20px 0 10px -7px var(--hlcol) inset;
content: " ";
height: 100%;
left: -20px;
position: absolute;
top: 0;
width: 20px;
}
.t-studyline-slot.gradable.current.odd:after,
.r-studyline-slot.gradable.current.odd:after {
--hlcol: color-mix(in srgb, var(--less-light) , var(--highlight) var(--highlight-mix));
box-shadow: 20px 0 10px -7px var(--hlcol) inset;
content: " ";
height: 100%;
right: -20px;
position: absolute;
top: 0;
width: 20px;
}
.s-studyline-header-period.current {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix));
box-shadow: 0 0 10px 10px var(--hlcol);
background-color: var(--hlcol);
margin-top: 16px;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
.s-studyline-header-heading {
margin-top: 16px;
}
.t-studyline-slot.gradable.current.even,
.r-studyline-slot.gradable.current.even {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix));
background-color: var(--hlcol);
position: relative;
}
.t-studyline-slot.gradable.current.even:before,
.r-studyline-slot.gradable.current.even:before {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix));
box-shadow: -20px 0 10px -7px var(--hlcol) inset;
content: " ";
height: 100%;
left: -20px;
position: absolute;
top: 0;
width: 20px;
}
.simpleline {
z-index: 20;
}
.t-studyline-slot.gradable.current.even:after,
.r-studyline-slot.gradable.current.even:after {
--hlcol: color-mix(in srgb, var(--white) , var(--highlight) var(--highlight-mix));
box-shadow: 20px 0 10px -7px var(--hlcol) inset;
content: " ";
height: 100%;
right: -20px;
position: absolute;
top: 0;
width: 20px;
}
.t-slot-drop { .t-slot-drop {
min-height: 32px; min-height: 32px;
height: 100%; height: 100%;
@ -564,7 +649,15 @@ a.t-item-course-config {
.r-studyline-heading.odd, .r-studyline-heading.odd,
.t-studyline-slot.odd, .t-studyline-slot.odd,
.r-studyline-slot.odd { .r-studyline-slot.odd {
background-color: #f0f0f0; background-color: var(--less-light);
}
.t-studyline-drag:nth-child(even) .t-studyline div,
.t-studyline-heading.even,
.r-studyline-heading.even,
.t-studyline-slot.even,
.r-studyline-slot.even {
background-color: var(--white);
} }
.t-studyline-drag:first-child, .t-studyline-drag:first-child,
@ -585,6 +678,7 @@ a.t-item-course-config {
.s-studyline-header-period { .s-studyline-header-period {
text-align: center; text-align: center;
padding-top: 5px;
} }
.s-studyline-header-period p { .s-studyline-header-period p {
margin-bottom: 0; margin-bottom: 0;
@ -603,6 +697,7 @@ a.t-item-course-config {
} }
.t-studyline-slot.rightmost, .t-studyline-slot.rightmost,
.r-studyline-slot.rightmost { .r-studyline-slot.rightmost {
border-right-style: solid; border-right-style: solid;