[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX][UX] Calendar: fix prefilled new-event date, save and calendar selector regressions
"Victor Emanouilov \(@kroky\) via TikiWiki-cvs" <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <69ca1daddca34_3b18fb2897644@gitlab-sidekiq-low-urgency-cpu-bound-v2-5c9f55b86f-7zg9k.mail> |
Victor Emanouilov pushed to branch master at Tiki Wiki CMS Groupware / Tiki
Commits:
ffb4d26a by MAGENE Sem Joel at 2026-03-30T06:45:18+00:00
[FIX][UX] Calendar: fix prefilled new-event date, save and calendar selector regressions
---
* [FIX][UX] Calendar: fix prefilled new-event date, save and calendar selector regressions
See merge request tikiwiki/tiki!9826
- - - - -
3 changed files:
- lib/core/Services/Calendar/Controller.php
- src/js/jquery-tiki/tiki-calendar.js
- templates/calendar/edit_item.tpl
Changes:
=====================================
lib/core/Services/Calendar/Controller.php
=====================================
@@ -413,25 +413,34 @@ class Services_Calendar_Controller extends Services_Calendar_BaseController
// set up default start and end
$dateNow->setTZbyID($displayTimezone);
if ($input->prefill_start->text()) {
- $prefillStart = $input->prefill_start->text();
- $prefillEnd = $input->prefill_end->text();
-
- $tikidate = new TikiDate();
- $tikidate->setTZbyID($displayTimezone);
-
- $tikidate->setDate($prefillStart, $displayTimezone);
- $start = $tikidate->getTime();
- if ($prefillEnd && strtotime($prefillEnd) !== false) {
- $tikidate->setDate($prefillEnd, $displayTimezone);
- $end = $tikidate->getTime();
- // subtract 1 sec to make it inclusive
- if (strlen($prefillEnd) <= 10 || strpos($prefillEnd, '00:00:00') !== false) {
- $end -= 1;
+ $prefillStart = trim($input->prefill_start->text());
+ $prefillEnd = trim((string) $input->prefill_end->text());
+ $prefillTimezoneRequested = trim((string) $input->prefill_tz->text());
+ $prefillTimezone = $this->resolvePrefillTimezone($prefillTimezoneRequested, $displayTimezone);
+
+ $start = $this->parsePrefillDateTime($prefillStart, $prefillTimezone);
+ if (! is_null($start) && $prefillEnd !== '') {
+ $end = $this->parsePrefillDateTime($prefillEnd, $prefillTimezone);
+ if (! is_null($end)) {
+ // convert exclusive all-day selection end to inclusive end
+ if ($this->isPrefillStartOfDay($prefillEnd, $prefillTimezone)) {
+ $end -= 1;
+ }
+ if ($end <= $start) {
+ $duration = 60 * 60;
+ $end = $start + $duration;
+ } else {
+ $duration = $end - $start;
+ }
+ } else {
+ $duration = 60 * 60;
+ $end = $start + $duration;
}
- $duration = $end - $start;
- } else {
+ } elseif (! is_null($start)) {
$duration = 60 * 60;
$end = $start + $duration;
+ } else {
+ [$start, $end, $duration] = $this->getDefaultStartEndDurationFromDateNow($dateNow, $displayTimezone);
}
if ($input->target_user->text()) {
if ($user) {
@@ -445,26 +454,12 @@ class Services_Calendar_Controller extends Services_Calendar_BaseController
];
}
} else {
- $hour = $dateNow->date->format('H');
if ($input->offsetExists('todate')) {
// set the correct day clicked on
$dateNow->setTZbyID($displayTimezone);
$dateNow->setDate($input->todate->text(), $displayTimezone);
- $hour = $dateNow->date->format('H');
}
- $tz = date_default_timezone_get();
- date_default_timezone_set($displayTimezone);
- $start = mktime(
- $hour,
- $dateNow->date->format('i'),
- $dateNow->date->format('s'),
- $dateNow->date->format('m'),
- $dateNow->date->format('d'),
- $dateNow->date->format('Y')
- );
- date_default_timezone_set($tz);
- $duration = 60 * 60;
- $end = $start + $duration;
+ [$start, $end, $duration] = $this->getDefaultStartEndDurationFromDateNow($dateNow, $displayTimezone);
}
$calitem = [
@@ -622,6 +617,8 @@ class Services_Calendar_Controller extends Services_Calendar_BaseController
'displayTimezone' => $displayTimezone,
'timezones' => $timezones,
'prefilled' => $input->prefill_start->text() ? true : false,
+ 'requireParticipant' => $input->target_user->text() !== '',
+ 'hideCalendarSelector' => $input->prefill_start->text() !== '' && $input->target_user->text() !== '',
// related tracker items
'trackerItems' => ! empty($trackerItems) ? $trackerItems : [],
];
@@ -943,6 +940,89 @@ class Services_Calendar_Controller extends Services_Calendar_BaseController
return $recurrence;
}
+ /**
+ * Build default start/end in the display timezone from current date/time context.
+ *
+ * @return array{0:int,1:int,2:int}
+ */
+ private function getDefaultStartEndDurationFromDateNow(TikiDate $dateNow, string $displayTimezone): array
+ {
+ $hour = $dateNow->date->format('H');
+ $tz = date_default_timezone_get();
+ date_default_timezone_set($displayTimezone);
+ $start = mktime(
+ $hour,
+ $dateNow->date->format('i'),
+ $dateNow->date->format('s'),
+ $dateNow->date->format('m'),
+ $dateNow->date->format('d'),
+ $dateNow->date->format('Y')
+ );
+ date_default_timezone_set($tz);
+
+ $duration = 60 * 60;
+ $end = $start + $duration;
+
+ return [$start, $end, $duration];
+ }
+
+ /**
+ * Resolve prefill timezone from request, falling back to display timezone when missing or invalid.
+ */
+ private function resolvePrefillTimezone(string $requestedTimezone, string $displayTimezone): string
+ {
+ if ($requestedTimezone === '') {
+ return $displayTimezone;
+ }
+
+ try {
+ new DateTimeZone($requestedTimezone);
+ return $requestedTimezone;
+ } catch (\Exception $e) {
+ return $displayTimezone;
+ }
+ }
+
+ /**
+ * Parse prefilled date string from calendar click/drag.
+ * Accepts timezone-aware ISO strings and falls back to display timezone when no offset is present.
+ */
+ private function parsePrefillDateTime(string $value, string $displayTimezone): ?int
+ {
+ if ($value === '') {
+ return null;
+ }
+
+ try {
+ if (preg_match('/^-?\\d+$/', $value) === 1) {
+ return (int) $value;
+ }
+
+ $date = new DateTimeImmutable($value, new DateTimeZone($displayTimezone));
+ return $date->getTimestamp();
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+
+ /**
+ * Detects whether a prefill value points to local start-of-day.
+ */
+ private function isPrefillStartOfDay(string $value, string $displayTimezone): bool
+ {
+ try {
+ if (preg_match('/^-?\\d+$/', $value) === 1) {
+ $date = new DateTimeImmutable('@' . $value);
+ $date = $date->setTimezone(new DateTimeZone($displayTimezone));
+ } else {
+ $date = new DateTimeImmutable($value, new DateTimeZone($displayTimezone));
+ }
+ return $date->format('H:i:s') === '00:00:00';
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
/**
* Convert submitted start/end times to UTC
*/
=====================================
src/js/jquery-tiki/tiki-calendar.js
=====================================
@@ -16,20 +16,56 @@ $.fn.setupEventCalendar = function (
this.each(function () {
const calendarEl = document.getElementById(targetId);
$(calendarEl).tikiModal(tr("Loading..."));
- const openNewEventModal = (startStr, endStr = null) => {
+ const toTimezoneStableIso = (dateValue) => moment(dateValue).format("YYYY-MM-DD[T]HH:mm:ssZ");
+ const browserTimezone = (() => {
+ try {
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || null;
+ } catch (e) {
+ return null;
+ }
+ })();
+ const toPrefillParamValue = (value) => {
+ if (value === null || typeof value === "undefined") {
+ return null;
+ }
+ if (typeof value === "string") {
+ return value;
+ }
+ if (value instanceof Date && !isNaN(value.getTime())) {
+ return toTimezoneStableIso(value);
+ }
+ return String(value);
+ };
+
+ const openNewEventModal = (startValue, endValue = null) => {
if (isOpeningModal) return;
const countCals = $(".filtercal ul li").length;
if (countCals >= 1 || targetId != "calendar") {
isOpeningModal = true;
$(calendarEl).tikiModal(" "); // Use the container for the loading overlay
+ const prefillStart = toPrefillParamValue(startValue);
+ if (!prefillStart) {
+ isOpeningModal = false;
+ return;
+ }
+
const params = {
- prefill_start: startStr,
+ prefill_start: prefillStart,
modal: 1,
return_url: returnUrl,
};
- if (endStr) {
- params.prefill_end = endStr;
+
+ if (browserTimezone) {
+ params.prefill_tz = browserTimezone;
+ }
+
+ if (endValue !== null && typeof endValue !== "undefined") {
+ const prefillEnd = toPrefillParamValue(endValue);
+ if (prefillEnd) {
+ params.prefill_end = prefillEnd;
+ }
}
+
$.openModal({
title: tr("New event"),
size: "modal-lg",
@@ -67,7 +103,7 @@ $.fn.setupEventCalendar = function (
eventSources: [{ url: urlEventSource }],
select: function (info) {
// Handle Drag Selection
- openNewEventModal(info.startStr, info.endStr);
+ openNewEventModal(info.startStr ?? info.start, info.endStr ?? info.end);
},
slotMinTime: eventCalendarParams.minHourOfDay,
slotMaxTime: eventCalendarParams.maxHourOfDay,
@@ -266,7 +302,7 @@ $.fn.setupEventCalendar = function (
calendarContainer[0].unselect();
} else {
// Handle Single Click
- openNewEventModal(info.dateStr);
+ openNewEventModal(info.dateStr ?? info.date);
}
},
eventResize: function (info) {
=====================================
templates/calendar/edit_item.tpl
=====================================
@@ -32,7 +32,7 @@
{if $prefs.calendar_addtogooglecal == 'y'}
{wikiplugin _name="addtogooglecal" calitemid=$calitemId}{/wikiplugin}
{/if}
- {if $prefilled}
+ {if $hideCalendarSelector}
<input type="hidden" name="calitem[calendarId]" value="{$calitem.calendarId}">
{else}
<div class="mb-3 row">
@@ -442,7 +442,7 @@
<div class="submit">
<input type="hidden" id="act" name="act" value="">
<input type="submit" class="btn btn-secondary cleanable-false" name="preview" value="{tr}Preview{/tr}" onclick="needToConfirm=false">
- <input type="submit" class="btn btn-primary cleanable-false {if $prefilled}need-participant{/if}" name="saveitem" value="{tr}Save{/tr}" onclick="needToConfirm=false">
+ <input type="submit" class="btn btn-primary cleanable-false {if $requireParticipant}need-participant{/if}" name="saveitem" value="{tr}Save{/tr}" onclick="needToConfirm=false">
{if $calitemId && ! $recurrence.id}
<input type="submit" name="delete" data-alt_controller="calendar" data-alt_action="delete_item"
class="btn btn-danger cleanable-false" onclick="needToConfirm=false;" data-bs-dismiss="modal" value="{tr}Delete event{/tr}">
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/ffb4d26a4d1ba50a1e60c35650768ac1ac701292
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/ffb4d26a4d1ba50a1e60c35650768ac1ac701292
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs