Changed wekan-boostrap-datepicker to HTML datepicker.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2025-10-16 23:19:26 +03:00
parent 33e4b046e8
commit 79b94824ef
112 changed files with 192 additions and 5589 deletions

View file

@ -1,11 +1,11 @@
.assignee {
border-radius: 0.4vw;
border-radius: 3px;
display: block;
position: relative;
float: left;
height: 4vw;
width: 4vw;
margin: 0.4vh;
height: 30px;
width: 30px;
margin: .3vh;
cursor: pointer;
user-select: none;
z-index: 1;
@ -34,11 +34,11 @@
background-color: #b3b3b3;
border: 1px solid #fff;
border-radius: 50%;
height: 1vw;
width: 1vw;
height: 7px;
width: 7px;
position: absolute;
right: -0.1vw;
bottom: -0.1vw;
right: -1px;
bottom: -1px;
border: 1px solid #fff;
z-index: 15;
}

View file

@ -4,11 +4,10 @@ template(name="datepicker")
.fields
.left
label(for="date") {{_ 'date'}}
input.js-date-field#date(type="text" name="date" value=showDate placeholder=dateFormat autofocus)
input.js-date-field#date(type="date" name="date" value=showDate autofocus)
.right
label(for="time") {{_ 'time'}}
input.js-time-field#time(type="text" name="time" value=showTime placeholder=timeFormat)
.js-datepicker
input.js-time-field#time(type="time" name="time" value=showTime)
if error.get
.warning {{_ error.get}}
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}

View file

@ -107,6 +107,137 @@
.pop-over[data-popup="changeLanguage"] .content-container {
max-height: inherit; /* Use dynamic height from JavaScript */
}
/* Date popup sizing for native HTML inputs */
.pop-over[data-popup="editCardReceivedDatePopup"],
.pop-over[data-popup="editCardStartDatePopup"],
.pop-over[data-popup="editCardDueDatePopup"],
.pop-over[data-popup="editCardEndDatePopup"],
.pop-over[data-popup*="Date"] {
width: min(400px, 90vw) !important; /* Smaller width for native inputs */
min-width: 350px !important;
max-height: 80vh !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .content-wrapper,
.pop-over[data-popup="editCardStartDatePopup"] .content-wrapper,
.pop-over[data-popup="editCardDueDatePopup"] .content-wrapper,
.pop-over[data-popup="editCardEndDatePopup"] .content-wrapper,
.pop-over[data-popup*="Date"] .content-wrapper {
max-height: 60vh !important;
overflow-y: auto !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .content-container,
.pop-over[data-popup="editCardStartDatePopup"] .content-container,
.pop-over[data-popup="editCardDueDatePopup"] .content-container,
.pop-over[data-popup="editCardEndDatePopup"] .content-container,
.pop-over[data-popup*="Date"] .content-container {
max-height: 60vh !important;
}
/* Native HTML input styling */
.pop-over[data-popup*="Date"] .datepicker-container {
width: 100% !important;
padding: 15px !important;
}
.pop-over[data-popup*="Date"] .datepicker-container .fields {
display: flex !important;
gap: 15px !important;
margin-bottom: 15px !important;
}
.pop-over[data-popup*="Date"] .datepicker-container .fields .left,
.pop-over[data-popup*="Date"] .datepicker-container .fields .right {
flex: 1 !important;
width: auto !important;
}
.pop-over[data-popup*="Date"] .datepicker-container label {
display: block !important;
margin-bottom: 5px !important;
font-weight: bold !important;
}
.pop-over[data-popup*="Date"] .datepicker-container input[type="date"],
.pop-over[data-popup*="Date"] .datepicker-container input[type="time"] {
width: 100% !important;
padding: 8px !important;
border: 1px solid #ccc !important;
border-radius: 4px !important;
font-size: 14px !important;
box-sizing: border-box !important;
}
.pop-over[data-popup*="Date"] .datepicker-container input[type="date"]:focus,
.pop-over[data-popup*="Date"] .datepicker-container input[type="time"]:focus {
outline: none !important;
border-color: #007cba !important;
box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.2) !important;
}
/* Ensure date popup buttons stay within popup boundaries */
.pop-over[data-popup="editCardReceivedDatePopup"] .content,
.pop-over[data-popup="editCardStartDatePopup"] .content,
.pop-over[data-popup="editCardDueDatePopup"] .content,
.pop-over[data-popup="editCardEndDatePopup"] .content,
.pop-over[data-popup*="Date"] .content {
max-height: 60vh !important; /* Leave space for buttons */
overflow-y: auto !important;
padding-bottom: 100px !important; /* More space for buttons */
margin-bottom: 0 !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .datepicker-container,
.pop-over[data-popup="editCardStartDatePopup"] .datepicker-container,
.pop-over[data-popup="editCardDueDatePopup"] .datepicker-container,
.pop-over[data-popup="editCardEndDatePopup"] .datepicker-container,
.pop-over[data-popup*="Date"] .datepicker-container {
max-height: 50vh !important; /* Limit calendar height */
overflow-y: auto !important;
margin-bottom: 20px !important; /* Space before buttons */
}
/* Ensure buttons are properly positioned */
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date,
.pop-over[data-popup="editCardStartDatePopup"] .edit-date,
.pop-over[data-popup="editCardDueDatePopup"] .edit-date,
.pop-over[data-popup="editCardEndDatePopup"] .edit-date,
.pop-over[data-popup*="Date"] .edit-date {
display: flex !important;
flex-direction: column !important;
height: 100% !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date .fields,
.pop-over[data-popup="editCardStartDatePopup"] .edit-date .fields,
.pop-over[data-popup="editCardDueDatePopup"] .edit-date .fields,
.pop-over[data-popup="editCardEndDatePopup"] .edit-date .fields,
.pop-over[data-popup*="Date"] .edit-date .fields {
flex-shrink: 0 !important;
margin-bottom: 15px !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date .js-datepicker,
.pop-over[data-popup="editCardStartDatePopup"] .edit-date .js-datepicker,
.pop-over[data-popup="editCardDueDatePopup"] .edit-date .js-datepicker,
.pop-over[data-popup="editCardEndDatePopup"] .edit-date .js-datepicker,
.pop-over[data-popup*="Date"] .edit-date .js-datepicker {
flex: 1 !important;
overflow-y: auto !important;
}
.pop-over[data-popup="editCardReceivedDatePopup"] .edit-date button,
.pop-over[data-popup="editCardStartDatePopup"] .edit-date button,
.pop-over[data-popup="editCardDueDatePopup"] .edit-date button,
.pop-over[data-popup="editCardEndDatePopup"] .edit-date button,
.pop-over[data-popup*="Date"] .edit-date button {
flex-shrink: 0 !important;
margin-top: 15px !important;
position: relative !important;
z-index: 10 !important;
}
.pop-over .content-container .content {
/* Match wider popover, leave padding */
width: 100%;

View file

@ -33,42 +33,29 @@ export class DatePicker extends BlazeComponent {
}
onRendered() {
const $picker = this.$('.js-datepicker')
.datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
weekStart: this.startDayOfWeek(),
calendarWeeks: true,
})
.on(
'changeDate',
function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
const timeInput = this.find('#time');
timeInput.focus();
if (!timeInput.value && this.defaultTime) {
const currentHour = evt.date.getHours();
const defaultMoment = moment(
currentHour > 0 ? evt.date : this.defaultTime,
); // default to 8:00 am local time
timeInput.value = defaultMoment.format('LT');
}
}.bind(this),
);
// Set initial values for native HTML inputs
if (this.date.get().isValid()) {
$picker.datepicker('update', this.date.get().toDate());
const dateInput = this.find('#date');
const timeInput = this.find('#time');
if (dateInput) {
dateInput.value = this.date.get().format('YYYY-MM-DD');
}
if (timeInput && !timeInput.value && this.defaultTime) {
const defaultMoment = moment(this.defaultTime);
timeInput.value = defaultMoment.format('HH:mm');
} else if (timeInput && this.date.get().isValid()) {
timeInput.value = this.date.get().format('HH:mm');
}
}
}
showDate() {
if (this.date.get().isValid()) return this.date.get().format('L');
if (this.date.get().isValid()) return this.date.get().format('YYYY-MM-DD');
return '';
}
showTime() {
if (this.date.get().isValid()) return this.date.get().format('LT');
if (this.date.get().isValid()) return this.date.get().format('HH:mm');
return '';
}
dateFormat() {
@ -81,54 +68,51 @@ export class DatePicker extends BlazeComponent {
events() {
return [
{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
'change .js-date-field'() {
// Native HTML date input validation
const dateValue = this.find('#date').value;
if (dateValue) {
const dateMoment = moment(dateValue, 'YYYY-MM-DD', true);
if (dateMoment.isValid()) {
this.error.set('');
} else {
this.error.set('invalid-date');
}
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(
this.find('#time').value,
adjustedTimeFormat(),
true,
);
if (dateMoment.isValid()) {
this.error.set('');
'change .js-time-field'() {
// Native HTML time input validation
const timeValue = this.find('#time').value;
if (timeValue) {
const timeMoment = moment(timeValue, 'HH:mm', true);
if (timeMoment.isValid()) {
this.error.set('');
} else {
this.error.set('invalid-time');
}
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
// if no time was given, init with 12:00
const time =
evt.target.time.value ||
moment(new Date().setHours(12, 0, 0)).format('LT');
const newTime = moment(time, adjustedTimeFormat(), true);
const newDate = moment(evt.target.date.value, 'L', true);
const dateString = `${evt.target.date.value} ${time}`;
const newCompleteDate = moment(
dateString,
`L ${adjustedTimeFormat()}`,
true,
);
if (!newTime.isValid()) {
this.error.set('invalid-time');
evt.target.time.focus();
}
if (!newDate.isValid()) {
const dateValue = evt.target.date.value;
const timeValue = evt.target.time.value || '12:00'; // Default to 12:00 if no time given
if (!dateValue) {
this.error.set('invalid-date');
evt.target.date.focus();
return;
}
if (newCompleteDate.isValid()) {
this._storeDate(newCompleteDate.toDate());
Popup.back();
} else if (!this.error) {
const newCompleteDate = moment(`${dateValue} ${timeValue}`, 'YYYY-MM-DD HH:mm', true);
if (!newCompleteDate.isValid()) {
this.error.set('invalid');
return;
}
this._storeDate(newCompleteDate.toDate());
Popup.back();
},
'click .js-delete-date'(evt) {
evt.preventDefault();