mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 15:30:13 +01:00
Fix Regression - Show calendar popup at set due date.
Thanks to xet7 ! Fixes #5978
This commit is contained in:
parent
b02af27ac3
commit
581733d605
5 changed files with 77 additions and 126 deletions
|
|
@ -97,6 +97,12 @@ template(name="minicardCustomFieldDate")
|
||||||
template(name="editCardReceivedDatePopup")
|
template(name="editCardReceivedDatePopup")
|
||||||
form.edit-card-received-date
|
form.edit-card-received-date
|
||||||
.datepicker
|
.datepicker
|
||||||
|
// Date input field (existing)
|
||||||
|
// Insert calendar selector right after date input
|
||||||
|
.calendar-selector
|
||||||
|
label(for="calendar-received") 🗓️
|
||||||
|
input#calendar-received.js-calendar-date(type="date")
|
||||||
|
// Time input field (if present)
|
||||||
.clear-date
|
.clear-date
|
||||||
a.js-clear-date {{_ 'clear'}}
|
a.js-clear-date {{_ 'clear'}}
|
||||||
.datepicker-actions
|
.datepicker-actions
|
||||||
|
|
@ -106,6 +112,11 @@ template(name="editCardReceivedDatePopup")
|
||||||
template(name="editCardStartDatePopup")
|
template(name="editCardStartDatePopup")
|
||||||
form.edit-card-start-date
|
form.edit-card-start-date
|
||||||
.datepicker
|
.datepicker
|
||||||
|
// Date input field (existing)
|
||||||
|
.calendar-selector
|
||||||
|
label(for="calendar-start") 🗓️
|
||||||
|
input#calendar-start.js-calendar-date(type="date")
|
||||||
|
// Time input field (if present)
|
||||||
.clear-date
|
.clear-date
|
||||||
a.js-clear-date {{_ 'clear'}}
|
a.js-clear-date {{_ 'clear'}}
|
||||||
.datepicker-actions
|
.datepicker-actions
|
||||||
|
|
@ -115,6 +126,11 @@ template(name="editCardStartDatePopup")
|
||||||
template(name="editCardDueDatePopup")
|
template(name="editCardDueDatePopup")
|
||||||
form.edit-card-due-date
|
form.edit-card-due-date
|
||||||
.datepicker
|
.datepicker
|
||||||
|
// Date input field (existing)
|
||||||
|
.calendar-selector
|
||||||
|
label(for="calendar-due") 🗓️
|
||||||
|
input#calendar-due.js-calendar-date(type="date")
|
||||||
|
// Time input field (if present)
|
||||||
.clear-date
|
.clear-date
|
||||||
a.js-clear-date {{_ 'clear'}}
|
a.js-clear-date {{_ 'clear'}}
|
||||||
.datepicker-actions
|
.datepicker-actions
|
||||||
|
|
@ -124,6 +140,11 @@ template(name="editCardDueDatePopup")
|
||||||
template(name="editCardEndDatePopup")
|
template(name="editCardEndDatePopup")
|
||||||
form.edit-card-end-date
|
form.edit-card-end-date
|
||||||
.datepicker
|
.datepicker
|
||||||
|
// Date input field (existing)
|
||||||
|
.calendar-selector
|
||||||
|
label(for="calendar-end") 🗓️
|
||||||
|
input#calendar-end.js-calendar-date(type="date")
|
||||||
|
// Time input field (if present)
|
||||||
.clear-date
|
.clear-date
|
||||||
a.js-clear-date {{_ 'clear'}}
|
a.js-clear-date {{_ 'clear'}}
|
||||||
.datepicker-actions
|
.datepicker-actions
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,17 @@ import {
|
||||||
onRendered() {
|
onRendered() {
|
||||||
super.onRendered();
|
super.onRendered();
|
||||||
// DatePicker base class handles initialization with native HTML inputs
|
// DatePicker base class handles initialization with native HTML inputs
|
||||||
|
const self = this;
|
||||||
|
this.$('.js-calendar-date').on('change', function(evt) {
|
||||||
|
const currentUser = ReactiveCache.getCurrentUser && ReactiveCache.getCurrentUser();
|
||||||
|
const dateFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
||||||
|
const value = evt.target.value;
|
||||||
|
if (value) {
|
||||||
|
// Format date according to user preference
|
||||||
|
const formatted = formatDateByUserPreference(new Date(value), dateFormat, true);
|
||||||
|
self._storeDate(new Date(value));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_storeDate(date) {
|
_storeDate(date) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ template(name="datepicker")
|
||||||
.fields
|
.fields
|
||||||
.left
|
.left
|
||||||
label(for="date") {{_ 'date'}}
|
label(for="date") {{_ 'date'}}
|
||||||
input.js-date-field#date(type="text" name="date" value=showDate autofocus placeholder=dateFormat)
|
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
|
||||||
.right
|
.right
|
||||||
label(for="time") {{_ 'time'}}
|
label(for="time") {{_ 'time'}}
|
||||||
input.js-time-field#time(type="time" name="time" value=showTime)
|
input.js-time-field#time(type="time" name="time" value=showTime)
|
||||||
|
|
|
||||||
|
|
@ -293,6 +293,8 @@
|
||||||
overflow-y: auto !important;
|
overflow-y: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date button,
|
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date button,
|
||||||
.pop-over[data-popup="editCardStartDatePopup"] .edit-date button,
|
.pop-over[data-popup="editCardStartDatePopup"] .edit-date button,
|
||||||
.pop-over[data-popup="editCardDueDatePopup"] .edit-date button,
|
.pop-over[data-popup="editCardDueDatePopup"] .edit-date button,
|
||||||
|
|
@ -387,9 +389,6 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
.pop-over .quiet {
|
|
||||||
/* padding: 6px 6px 4px;*/
|
|
||||||
}
|
|
||||||
.pop-over.search-over {
|
.pop-over.search-over {
|
||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
min-height: 14vh;
|
min-height: 14vh;
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,27 @@
|
||||||
import { ReactiveCache } from '/imports/reactiveCache';
|
import { ReactiveCache } from '/imports/reactiveCache';
|
||||||
import { TAPi18n } from '/imports/i18n';
|
import { TAPi18n } from '/imports/i18n';
|
||||||
import {
|
|
||||||
formatDateTime,
|
|
||||||
formatDate,
|
|
||||||
formatDateByUserPreference,
|
|
||||||
formatTime,
|
|
||||||
getISOWeek,
|
|
||||||
isValidDate,
|
|
||||||
isBefore,
|
|
||||||
isAfter,
|
|
||||||
isSame,
|
|
||||||
add,
|
|
||||||
subtract,
|
|
||||||
startOf,
|
|
||||||
endOf,
|
|
||||||
format,
|
|
||||||
parseDate,
|
|
||||||
now,
|
|
||||||
createDate,
|
|
||||||
fromNow,
|
|
||||||
calendar
|
|
||||||
} from '/imports/lib/dateUtils';
|
|
||||||
|
|
||||||
// Helper function to get time format for 24 hours
|
// Helper to check if a date is valid
|
||||||
function adjustedTimeFormat() {
|
function isValidDate(date) {
|
||||||
return 'HH:mm';
|
return date instanceof Date && !isNaN(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
// .replace(/HH/i, 'H');
|
// Format date as YYYY-MM-DD
|
||||||
|
function formatDate(date) {
|
||||||
|
if (!isValidDate(date)) return '';
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format time as HH:mm
|
||||||
|
function formatTime(date) {
|
||||||
|
if (!isValidDate(date)) return '';
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
return `${hours}:${minutes}`;
|
||||||
|
}
|
||||||
|
|
||||||
export class DatePicker extends BlazeComponent {
|
export class DatePicker extends BlazeComponent {
|
||||||
template() {
|
template() {
|
||||||
|
|
@ -51,35 +45,25 @@ export class DatePicker extends BlazeComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
onRendered() {
|
onRendered() {
|
||||||
// Set initial values for text and time inputs
|
// Set initial values for native HTML inputs
|
||||||
if (isValidDate(this.date.get())) {
|
if (isValidDate(this.date.get())) {
|
||||||
const dateInput = this.find('#date');
|
const dateInput = this.find('#date');
|
||||||
const timeInput = this.find('#time');
|
const timeInput = this.find('#time');
|
||||||
|
|
||||||
if (dateInput) {
|
if (dateInput) {
|
||||||
// Use user's preferred format for text input
|
dateInput.value = formatDate(this.date.get());
|
||||||
const currentUser = ReactiveCache.getCurrentUser();
|
|
||||||
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
||||||
dateInput.value = formatDateByUserPreference(this.date.get(), userFormat, false);
|
|
||||||
}
|
}
|
||||||
if (timeInput) {
|
if (timeInput && !timeInput.value && this.defaultTime) {
|
||||||
if (!timeInput.value && this.defaultTime) {
|
const defaultDate = new Date(this.defaultTime);
|
||||||
const defaultDate = new Date(this.defaultTime);
|
timeInput.value = formatTime(defaultDate);
|
||||||
timeInput.value = formatTime(defaultDate);
|
} else if (timeInput && isValidDate(this.date.get())) {
|
||||||
} else if (isValidDate(this.date.get())) {
|
timeInput.value = formatTime(this.date.get());
|
||||||
timeInput.value = formatTime(this.date.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showDate() {
|
showDate() {
|
||||||
if (isValidDate(this.date.get())) {
|
if (isValidDate(this.date.get())) return formatDate(this.date.get());
|
||||||
// Use user's preferred format for display, but HTML date input needs YYYY-MM-DD
|
|
||||||
const currentUser = ReactiveCache.getCurrentUser();
|
|
||||||
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
||||||
return formatDateByUserPreference(this.date.get(), userFormat, false);
|
|
||||||
}
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
showTime() {
|
showTime() {
|
||||||
|
|
@ -87,56 +71,22 @@ export class DatePicker extends BlazeComponent {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
dateFormat() {
|
dateFormat() {
|
||||||
const currentUser = ReactiveCache.getCurrentUser();
|
return 'YYYY-MM-DD';
|
||||||
const userFormat = currentUser ? currentUser.getDateFormat() : 'YYYY-MM-DD';
|
|
||||||
// Convert format to localized placeholder
|
|
||||||
switch (userFormat) {
|
|
||||||
case 'DD-MM-YYYY':
|
|
||||||
return TAPi18n.__('date-format-dd-mm-yyyy') || 'PP-KK-VVVV';
|
|
||||||
case 'MM-DD-YYYY':
|
|
||||||
return TAPi18n.__('date-format-mm-dd-yyyy') || 'KK-PP-VVVV';
|
|
||||||
case 'YYYY-MM-DD':
|
|
||||||
default:
|
|
||||||
return TAPi18n.__('date-format-yyyy-mm-dd') || 'VVVV-KK-PP';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
timeFormat() {
|
timeFormat() {
|
||||||
return 'LT';
|
return 'HH:mm';
|
||||||
}
|
}
|
||||||
|
|
||||||
events() {
|
events() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'change .js-date-field'() {
|
'change .js-date-field'() {
|
||||||
// Text input date validation
|
// Native HTML date input validation
|
||||||
const dateInput = this.find('#date');
|
const dateValue = this.find('#date').value;
|
||||||
if (!dateInput) return;
|
|
||||||
|
|
||||||
const dateValue = dateInput.value;
|
|
||||||
if (dateValue) {
|
if (dateValue) {
|
||||||
// Try to parse different date formats
|
// HTML date input format is always YYYY-MM-DD
|
||||||
const formats = [
|
const dateObj = new Date(dateValue + 'T12:00:00');
|
||||||
'YYYY-MM-DD',
|
if (isValidDate(dateObj)) {
|
||||||
'DD-MM-YYYY',
|
|
||||||
'MM-DD-YYYY',
|
|
||||||
'DD/MM/YYYY',
|
|
||||||
'MM/DD/YYYY',
|
|
||||||
'DD.MM.YYYY',
|
|
||||||
'MM.DD.YYYY'
|
|
||||||
];
|
|
||||||
|
|
||||||
let parsedDate = null;
|
|
||||||
for (const format of formats) {
|
|
||||||
parsedDate = parseDate(dateValue, [format], true);
|
|
||||||
if (parsedDate) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to native Date parsing
|
|
||||||
if (!parsedDate) {
|
|
||||||
parsedDate = new Date(dateValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValidDate(parsedDate)) {
|
|
||||||
this.error.set('');
|
this.error.set('');
|
||||||
} else {
|
} else {
|
||||||
this.error.set('invalid-date');
|
this.error.set('invalid-date');
|
||||||
|
|
@ -145,12 +95,10 @@ export class DatePicker extends BlazeComponent {
|
||||||
},
|
},
|
||||||
'change .js-time-field'() {
|
'change .js-time-field'() {
|
||||||
// Native HTML time input validation
|
// Native HTML time input validation
|
||||||
const timeInput = this.find('#time');
|
const timeValue = this.find('#time').value;
|
||||||
if (!timeInput) return;
|
|
||||||
|
|
||||||
const timeValue = timeInput.value;
|
|
||||||
if (timeValue) {
|
if (timeValue) {
|
||||||
const timeObj = new Date(`1970-01-01T${timeValue}`);
|
// HTML time input format is always HH:mm
|
||||||
|
const timeObj = new Date(`1970-01-01T${timeValue}:00`);
|
||||||
if (isValidDate(timeObj)) {
|
if (isValidDate(timeObj)) {
|
||||||
this.error.set('');
|
this.error.set('');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -170,44 +118,16 @@ export class DatePicker extends BlazeComponent {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse different date formats
|
// Combine date and time: HTML date input is YYYY-MM-DD, time input is HH:mm
|
||||||
const formats = [
|
const dateTimeString = `${dateValue}T${timeValue}:00`;
|
||||||
'YYYY-MM-DD',
|
const newCompleteDate = new Date(dateTimeString);
|
||||||
'DD-MM-YYYY',
|
|
||||||
'MM-DD-YYYY',
|
|
||||||
'DD/MM/YYYY',
|
|
||||||
'MM/DD/YYYY',
|
|
||||||
'DD.MM.YYYY',
|
|
||||||
'MM.DD.YYYY'
|
|
||||||
];
|
|
||||||
|
|
||||||
let parsedDate = null;
|
if (!isValidDate(newCompleteDate)) {
|
||||||
for (const format of formats) {
|
|
||||||
parsedDate = parseDate(dateValue, [format], true);
|
|
||||||
if (parsedDate) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to native Date parsing
|
|
||||||
if (!parsedDate) {
|
|
||||||
parsedDate = new Date(dateValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isValidDate(parsedDate)) {
|
|
||||||
this.error.set('invalid');
|
this.error.set('invalid');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine with time
|
this._storeDate(newCompleteDate);
|
||||||
const timeObj = new Date(`1970-01-01T${timeValue}`);
|
|
||||||
if (!isValidDate(timeObj)) {
|
|
||||||
this.error.set('invalid-time');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the time on the parsed date
|
|
||||||
parsedDate.setHours(timeObj.getHours(), timeObj.getMinutes(), 0, 0);
|
|
||||||
|
|
||||||
this._storeDate(parsedDate);
|
|
||||||
Popup.back();
|
Popup.back();
|
||||||
},
|
},
|
||||||
'click .js-delete-date'(evt) {
|
'click .js-delete-date'(evt) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue