Fixed period overlapping

This commit is contained in:
PMKuipers 2023-09-03 15:21:30 +02:00
parent d432f77494
commit db8b9c9a02
7 changed files with 124 additions and 18 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1069,7 +1069,7 @@ export default {
</b-col> </b-col>
<b-col> <b-col>
<b-button variant='success' @click="cohortAssociate()" <b-button variant='success' @click="cohortAssociate()"
><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button> ><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button>
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>
@ -1115,14 +1115,14 @@ export default {
</b-col> </b-col>
<b-col> <b-col>
<b-button variant='success' @click="userAssociate()" <b-button variant='success' @click="userAssociate()"
><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button> ><i class='fa fa-link'></i>&nbsp;{{text.add_association}}</b-button>
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>
</b-tab> </b-tab>
</b-tabs> </b-tabs>
</b-modal> </b-modal>
</span> </span>
` `
}); });
@ -1145,6 +1145,14 @@ export default {
'variant' : { 'variant' : {
type: String, type: String,
default() { return "";}, default() { return "";},
},
'minstart' : {
type: String,
default() { return null;},
},
'maxend' : {
type: String,
default() { return null;},
} }
}, },
data() { data() {
@ -1176,18 +1184,29 @@ export default {
editFinish(){ editFinish(){
const self = this; const self = this;
let args = { 'id': this.value.id }; let args = { 'id': this.value.id };
let method = 'local_treestudyplan_edit_period';
objCopy(args,this.editdata,PERIOD_EDITOR_FIELDS); objCopy(args,this.editdata,PERIOD_EDITOR_FIELDS);
call([{ call([{
methodname: method, methodname: 'local_treestudyplan_edit_period',
args: args args: args
}])[0].done(function(response){
objCopy(self.value,response,PERIOD_EDITOR_FIELDS);
self.$emit('input',self.value);
self.$emit('edited',self.value);
}).fail(notification.exception);
},
refresh(){
const self = this;
call([{
methodname: 'local_treestudyplan_get_period',
args: { 'id': this.value.id },
}])[0].done(function(response){ }])[0].done(function(response){
objCopy(self.value,response,PERIOD_EDITOR_FIELDS); objCopy(self.value,response,PERIOD_EDITOR_FIELDS);
self.$emit('input',self.value); self.$emit('input',self.value);
}).fail(notification.exception); }).fail(notification.exception);
}, },
} }
, ,
template: template:
@ -1225,13 +1244,21 @@ export default {
<b-row> <b-row>
<b-col cols="4">{{ text.studyplan_startdate}}</b-col> <b-col cols="4">{{ text.studyplan_startdate}}</b-col>
<b-col cols="8"> <b-col cols="8">
<b-form-datepicker v-model="editdata.startdate"></b-form-datepicker> <b-form-datepicker
v-model="editdata.startdate"
:min="(minstart ? minstart : '')"
:max="value.enddate"
></b-form-datepicker>
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row>
<b-col cols="4">{{ text.studyplan_enddate}}</b-col> <b-col cols="4">{{ text.studyplan_enddate}}</b-col>
<b-col cols="8"> <b-col cols="8">
<b-form-datepicker v-model="editdata.enddate" ></b-form-datepicker> <b-form-datepicker
v-model="editdata.enddate"
:min="value.startdate"
:max="(maxend ? maxend : '')"
></b-form-datepicker>
</b-col> </b-col>
</b-row> </b-row>
</b-container> </b-container>
@ -1537,7 +1564,17 @@ export default {
} }
return show; return show;
} },
periodEdited(pi) {
const prev = this.$refs["periodeditor-" + (pi.period - 1)][0];
if(prev) {
prev.refresh();
}
const next = this.$refs["periodeditor-" + (pi.period + 1)][0];
if(next) {
next.refresh();
}
},
} }
, ,
template: template:
@ -1623,7 +1660,13 @@ export default {
<s-studyline-header-period <s-studyline-header-period
v-if="index > 0" v-if="index > 0"
v-model="page.perioddesc[index-1]" v-model="page.perioddesc[index-1]"
><t-period-edit v-model="page.perioddesc[index-1]"></t-period-edit ><t-period-edit
:ref="'periodeditor-'+index"
@edited="periodEdited"
v-model="page.perioddesc[index-1]"
:minstart="(index > 1) ? page.perioddesc[index-2].startdate : null"
:maxend="(index < page.periods) ? page.perioddesc[index].enddate : null"
></t-period-edit
></s-studyline-header-period> ></s-studyline-header-period>
<div class="s-studyline-header-filter"></div> <div class="s-studyline-header-filter"></div>
</template> </template>

View File

@ -21,6 +21,9 @@
*/ */
namespace local_treestudyplan; namespace local_treestudyplan;
use DateInterval;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/externallib.php'); require_once($CFG->libdir.'/externallib.php');
@ -221,8 +224,8 @@ class period {
if ($this->r->enddate && strlen($this->r->enddate) > 0) { if ($this->r->enddate && strlen($this->r->enddate) > 0) {
return new \DateTime($this->r->enddate); return new \DateTime($this->r->enddate);
} else { } else {
// Return a date 100 years into the future. // Return a date 2 months into the future if not set.... Yes, it needs to be set.
return (new \DateTime($this->r->startdate))->add(new \DateInterval("P100Y")); return (new \DateTime($this->r->startdate))->add(new \DateInterval("P2M"));
} }
} }
@ -293,6 +296,11 @@ class period {
*/ */
public function edit($fields) : self { public function edit($fields) : self {
global $DB; global $DB;
$pages = self::find_for_page($this->page());
$prev = (count($pages) > 2 && $this->period() >= 1) ? $pages[$this->period() - 1] : null;
$next = (count($pages) > $this->period()) ? $pages[$this->period() + 1] : null;
$editable = ['fullname', 'shortname', 'startdate', 'enddate']; $editable = ['fullname', 'shortname', 'startdate', 'enddate'];
$info = ['id' => $this->id, ]; $info = ['id' => $this->id, ];
foreach ($editable as $f) { foreach ($editable as $f) {
@ -301,8 +309,27 @@ class period {
} }
} }
$DB->update_record(self::TABLE, $info); $DB->update_record(self::TABLE, $info);
// Reload record after edit. // Reload record after edit and ensure end dates of previous period are adjusted if needed.
$this->r = $DB->get_record(self::TABLE, ['id' => $this->id], "*", MUST_EXIST); $this->r = $DB->get_record(self::TABLE, ['id' => $this->id], "*", MUST_EXIST);
// Adjust end date of previous period if needed
if (isset($prev) && !empty($fields['startdate'])) {
$maxdate = $this->startdate()->sub(new DateInterval("P1D")); // Subtract 1 day, since periods include the end day.
$rqdate = $prev->enddate();
if ($maxdate < $rqdate) {
$prev->edit(["enddate" => $maxdate->format("Y-m-d")]);
}
}
// Adjust start date of previous period if needed
if (isset($next) && !empty($fields['enddate'])) {
$mindate = $this->enddate()->add(new DateInterval("P1D")); // Subtract 1 day, since periods include the end day.
$rqdate = $next->startdate();
if ($mindate > $rqdate) {
$next->edit(["startdate" => $mindate->format("Y-m-d")]);
}
}
unset(self::$pagecache[$this->r->page_id]); // Invalidate the cache for this page. unset(self::$pagecache[$this->r->page_id]); // Invalidate the cache for this page.
return $this; return $this;
} }

View File

@ -1448,6 +1448,34 @@ class studyplanservice extends \external_api {
* * * *
************************/ ************************/
/**
* Parameter description for webservice function get_period
*/
public static function get_period_parameters() : \external_function_parameters {
return new \external_function_parameters( [
"id" => new \external_value(PARAM_INT, 'id of study item'),
]);
}
/**
* Return value description for webservice function get_period
*/
public static function get_period_returns() : \external_description {
return period::structure();
}
/**
* Get period information
* @param mixed $id Id of period to retrieve
* @return array
*/
public static function get_period($id) {
$p = period::find_by_id($id);
// Public data - no rights check needed
\external_api::validate_context($p->page()->studyplan()->context());
return $p->model();
}
/** /**
* Parameter description for webservice function edit_period * Parameter description for webservice function edit_period
*/ */
@ -1489,7 +1517,6 @@ class studyplanservice extends \external_api {
'enddate' => $enddate, 'enddate' => $enddate,
]); ]);
return $p->model(); return $p->model();
} }
/************************ /************************

View File

@ -484,6 +484,15 @@ $functions = [
'capabilities' => 'local/treestudyplan:editstudyplan', 'capabilities' => 'local/treestudyplan:editstudyplan',
'loginrequired' => true, 'loginrequired' => true,
], ],
'local_treestudyplan_get_period' => [ // Web service function name.
'classname' => '\local_treestudyplan\studyplanservice', // Class containing the external function.
'methodname' => 'get_period', // External function name.
'description' => 'Get period name and timing',
'type' => 'read', // Database rights of the web service function (read, write).
'ajax' => true,
'capabilities' => 'local/treestudyplan:viewstudyplan',
'loginrequired' => true,
],
'local_treestudyplan_edit_period' => [ // Web service function name. 'local_treestudyplan_edit_period' => [ // Web service function name.
'classname' => '\local_treestudyplan\studyplanservice', // Class containing the external function. 'classname' => '\local_treestudyplan\studyplanservice', // Class containing the external function.
'methodname' => 'edit_period', // External function name. 'methodname' => 'edit_period', // External function name.

View File

@ -22,7 +22,7 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494). $plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494).
$plugin->version = 2023083100; // YYYYMMDDHH (year, month, day, iteration). $plugin->version = 2023090300; // YYYYMMDDHH (year, month, day, iteration).
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11). $plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11).
$plugin->release = "1.0.0"; $plugin->release = "1.0.0";