MDL-81559 calendar: adjust end date automatically
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -34,6 +34,11 @@ import * as Repository from 'core_calendar/repository';
|
||||
const SELECTORS = {
|
||||
SAVE_BUTTON: '[data-action="save"]',
|
||||
LOADING_ICON_CONTAINER: '[data-region="loading-icon-container"]',
|
||||
START_DATE_FIELDS: 'select[name^="timestart"]',
|
||||
END_DATE_FIELDS: 'select[name^="timedurationuntil"]',
|
||||
START_DATE_DATE_PICKER: '#id_timestart_calendar',
|
||||
END_DATE_DATE_PICKER: '#id_timedurationuntil_calendar',
|
||||
DURATION_FIELD: '#id_timedurationminutes',
|
||||
};
|
||||
|
||||
export default class ModalEventForm extends Modal {
|
||||
@@ -56,6 +61,8 @@ export default class ModalEventForm extends Modal {
|
||||
this.reloadingBody = false;
|
||||
this.reloadingTitle = false;
|
||||
this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);
|
||||
this.eventTimeDuration = 0;
|
||||
this.lastUsedDatePickerId = null;
|
||||
}
|
||||
|
||||
configure(modalConfig) {
|
||||
@@ -231,6 +238,79 @@ export default class ModalEventForm extends Modal {
|
||||
this.saveButton.prop('disabled', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a date object from the fields in the form.
|
||||
*
|
||||
* @method getDateFromFields
|
||||
* @param {string} selector The selector that is used to build the id of the start/end date fields.
|
||||
* @return {Date} The date object created from the fields
|
||||
*/
|
||||
getDateFromFields(selector) {
|
||||
const identifier = selector.match(/"([^"]+)"/)[1];
|
||||
const d = new Date();
|
||||
d.setFullYear(document.getElementById(`id_${identifier}_year`).value);
|
||||
d.setMonth(document.getElementById(`id_${identifier}_month`).value - 1);
|
||||
d.setDate(document.getElementById(`id_${identifier}_day`).value);
|
||||
d.setHours(document.getElementById(`id_${identifier}_hour`).value);
|
||||
d.setMinutes(document.getElementById(`id_${identifier}_minute`).value);
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the end time value based on the duration of the event.
|
||||
*
|
||||
* If the event ends in 1 hour and 15 minutes, then updating the
|
||||
* start time will respect this duration and push the end time forward
|
||||
* and retain the 1 hour and 15 minute duration. This behaviour matches
|
||||
* those of Google and iOS calendars in 2026.
|
||||
*
|
||||
* @method updateEndTime
|
||||
*/
|
||||
updateEndTime() {
|
||||
const startDate = this.getDateFromFields(SELECTORS.START_DATE_FIELDS);
|
||||
const endDate = new Date(startDate.getTime() + this.eventTimeDuration);
|
||||
const identifier = SELECTORS.END_DATE_FIELDS.match(/"([^"]+)"/)[1];
|
||||
document.getElementById(`id_${identifier}_year`).value = endDate.getFullYear();
|
||||
document.getElementById(`id_${identifier}_month`).value = endDate.getMonth() + 1;
|
||||
document.getElementById(`id_${identifier}_day`).value = endDate.getDate();
|
||||
document.getElementById(`id_${identifier}_hour`).value = endDate.getHours();
|
||||
document.getElementById(`id_${identifier}_minute`).value = endDate.getMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the duration of the event by comparing the start and end dates.
|
||||
*
|
||||
* @method calculateDuration
|
||||
* @return {Number} Millisecond difference.
|
||||
*/
|
||||
calculateDuration() {
|
||||
const startDate = this.getDateFromFields(SELECTORS.START_DATE_FIELDS);
|
||||
const endDate = this.getDateFromFields(SELECTORS.END_DATE_FIELDS);
|
||||
return (endDate - startDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the YUI calendar events.
|
||||
*
|
||||
* These events need to be registered after the elements have been rendered.
|
||||
*
|
||||
* @method registerCalendarEvents
|
||||
*/
|
||||
registerCalendarEvents() {
|
||||
const calendar = M?.form?.dateselector?.calendar;
|
||||
if (calendar) {
|
||||
calendar.on('dateClick', () => {
|
||||
// The YUI date pickers share the same elements.
|
||||
// Determine which ones was last used and perform the required method.
|
||||
if (this.lastUsedDatePickerId === SELECTORS.START_DATE_DATE_PICKER) {
|
||||
this.updateEndTime();
|
||||
} else if (this.lastUsedDatePickerId === SELECTORS.END_DATE_DATE_PICKER) {
|
||||
this.eventTimeDuration = this.calculateDuration();
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the title for the modal to the appropriate value
|
||||
* depending on whether we are creating a new event or
|
||||
@@ -314,6 +394,9 @@ export default class ModalEventForm extends Modal {
|
||||
|
||||
this.bodyPromise.then(() => {
|
||||
this.enableButtons();
|
||||
this.updateEndTime();
|
||||
this.eventTimeDuration = this.calculateDuration();
|
||||
this.registerCalendarEvents();
|
||||
return;
|
||||
})
|
||||
.catch(Notification.exception)
|
||||
@@ -478,6 +561,31 @@ export default class ModalEventForm extends Modal {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
this.getModal().on('change', SELECTORS.START_DATE_FIELDS, () => {
|
||||
this.updateEndTime();
|
||||
});
|
||||
|
||||
this.getModal().on('change', SELECTORS.END_DATE_FIELDS, () => {
|
||||
this.eventTimeDuration = this.calculateDuration();
|
||||
});
|
||||
|
||||
this.getModal().on('click', SELECTORS.START_DATE_DATE_PICKER, () => {
|
||||
this.lastUsedDatePickerId = SELECTORS.START_DATE_DATE_PICKER;
|
||||
});
|
||||
|
||||
this.getModal().on('click', SELECTORS.END_DATE_DATE_PICKER, () => {
|
||||
this.lastUsedDatePickerId = SELECTORS.END_DATE_DATE_PICKER;
|
||||
});
|
||||
|
||||
this.getModal().on('focusout', SELECTORS.DURATION_FIELD, (e) => {
|
||||
const duration = parseInt(e.target.value);
|
||||
if (isNaN(duration)) {
|
||||
return;
|
||||
}
|
||||
this.eventTimeDuration = duration * 60 * 1000;
|
||||
this.updateEndTime();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,11 +87,14 @@ class create extends \moodleform {
|
||||
$mform->addRule('name', get_string('required'), 'required', null, 'client');
|
||||
$mform->setType('name', PARAM_TEXT);
|
||||
|
||||
// Add the select elements for the available event types.
|
||||
$this->add_event_type_elements($mform, $eventtypes);
|
||||
|
||||
// Event time start field.
|
||||
$mform->addElement('date_time_selector', 'timestart', get_string('date'), ['defaulttime' => $starttime]);
|
||||
|
||||
// Add the select elements for the available event types.
|
||||
$this->add_event_type_elements($mform, $eventtypes);
|
||||
// Add the variety of elements allowed for selecting event duration.
|
||||
$this->add_event_duration_elements($mform);
|
||||
|
||||
// Start of advanced elements.
|
||||
// Advanced elements are not visible to the user by default.
|
||||
@@ -104,9 +107,6 @@ class create extends \moodleform {
|
||||
$mform->setType('location', PARAM_RAW_TRIMMED);
|
||||
$mform->setAdvanced('location');
|
||||
|
||||
// Add the variety of elements allowed for selecting event duration.
|
||||
$this->add_event_duration_elements($mform);
|
||||
|
||||
// Add the form elements for repeating events.
|
||||
$this->add_event_repeat_elements($mform);
|
||||
|
||||
@@ -217,7 +217,6 @@ class create extends \moodleform {
|
||||
get_string('durationminutes', 'calendar'), 'maxlength="7" size="7"');
|
||||
|
||||
$mform->addGroup($group, 'durationgroup', get_string('eventduration', 'calendar'), '<br />', false);
|
||||
$mform->setAdvanced('durationgroup');
|
||||
|
||||
$mform->disabledIf('timedurationuntil', 'duration', 'noteq', 1);
|
||||
$mform->disabledIf('timedurationuntil[day]', 'duration', 'noteq', 1);
|
||||
|
||||
@@ -468,3 +468,17 @@ Feature: Perform basic calendar functionality
|
||||
And I press "Save"
|
||||
And I click on "type change test event" "link"
|
||||
And I should see "Category event"
|
||||
|
||||
@javascript
|
||||
Scenario: Move a date in the event form should update the event end date
|
||||
Given I log in as "admin"
|
||||
And the following "events" exist:
|
||||
| name | eventtype | timestart | timeduration |
|
||||
| Change date test event | user | ##today midnight +1 seconds## | 86400 |
|
||||
When I am on "Course 1" course homepage
|
||||
And I follow "Course calendar"
|
||||
And I click on "Change date test event" "link"
|
||||
And I click on "Edit" "button" in the "Change date test event" "dialogue"
|
||||
And I set the following fields to these values:
|
||||
| Date | ##today midnight +2 days## |
|
||||
Then the field "Until" matches value "##today midnight +3 days##"
|
||||
|
||||
Reference in New Issue
Block a user