Skip to content

Commit

Permalink
Fix manual date inputting in the basic date picker (#12180)
Browse files Browse the repository at this point in the history
* Fix manual date inputting in the basic date picker

Manually typing a date would not always work in the basic date pickers.
Especially in the work package edit views, singular keyboard inputs
would trigger a work package save, which would render an error right
away.

This commit fixes that.

Adresses https://community.openproject.org/work_packages/46211/activity#activity-13

* Fix linting errors
  • Loading branch information
Yule authored Mar 1, 2023
1 parent 750310c commit a14c123
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
[attr.name]="name"
[required]="required"
[disabled]="disabled"
[ngModel]="value"
(ngModelChange)="changeValueFromInputDebounced($event)"
(input)="changeValueFromInput($event)"
(focus)="showDatePicker()"
[attr.data-remote-field-key]="remoteFieldKey"
/>
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
forwardRef,
Injector,
Input,
OnDestroy,
Output,
ViewChild,
ViewEncapsulation,
Expand All @@ -47,14 +48,13 @@ import {
} from '@angular/forms';
import {
onDayCreate,
parseDate,
validDate,
} from 'core-app/shared/components/datepicker/helpers/date-modal.helpers';
import { TimezoneService } from 'core-app/core/datetime/timezone.service';
import { DatePicker } from '../datepicker';
import flatpickr from 'flatpickr';
import { DayElement } from 'flatpickr/dist/types/instance';
import { populateInputsFromDataset } from '../../dataset-inputs';
import { debounce } from 'lodash';
import { SpotDropModalTeleportationService } from 'core-app/spot/components/drop-modal/drop-modal-teleportation.service';

export const opBasicSingleDatePickerSelector = 'op-basic-single-date-picker';
Expand All @@ -73,8 +73,10 @@ export const opBasicSingleDatePickerSelector = 'op-basic-single-date-picker';
},
],
})
export class OpBasicSingleDatePickerComponent implements ControlValueAccessor, AfterViewInit {
@Output('valueChange') valueChange = new EventEmitter();
export class OpBasicSingleDatePickerComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {
@Output() valueChange = new EventEmitter();

@Output() picked = new EventEmitter();

private _value = '';

Expand Down Expand Up @@ -124,20 +126,24 @@ export class OpBasicSingleDatePickerComponent implements ControlValueAccessor, A
this.initializeDatePicker();
}

changeValueFromInputDebounced = debounce(this.changeValueFromInput.bind(this), 16);

changeValueFromInput(value:string) {
this.valueChange.emit(value);
this.onChange(value);
this.writeValue(value);

const date = parseDate(value || '');
ngOnDestroy():void {
this.datePickerInstance?.destroy();
}

if (date !== '') {
const dateString = this.timezoneService.formattedISODate(date);
changeValueFromInput($event:KeyboardEvent) {
const value = ($event.target as HTMLInputElement).value;
if (validDate(value)) {
const dateString = this.timezoneService.formattedISODate(value);
this.datePickerInstance.setDates(dateString);
this.valueChange.emit(dateString);
this.onTouched(dateString);
this.onChange(dateString);
this.writeValue(dateString);
} else if (value === '') {
this.datePickerInstance.setDates('');
this.onTouched('');
this.onChange('');
}
this.cdRef.detectChanges();
}

showDatePicker():void {
Expand All @@ -156,17 +162,20 @@ export class OpBasicSingleDatePickerComponent implements ControlValueAccessor, A
onReady: (_date:Date[], _datestr:string, instance:flatpickr.Instance) => {
instance.calendarContainer.classList.add('op-datepicker-modal--flatpickr-instance');
},
onChange: (dates:Date[]) => {
if (dates.length > 0) {
const dateString = this.timezoneService.formattedISODate(dates[0]);
this.writeValue(dateString);
this.onChange(dateString);
onChange: (_:Date[], dateStr:string) => {
this.writeValue(dateStr);
if (dateStr.length > 0) {
const dateString = this.timezoneService.formattedISODate(dateStr);
this.valueChange.emit(dateString);
this.onTouched(dateString);
this.onChange(dateString);
this.writeValue(dateString);
this.picked.emit();
}

this.cdRef.detectChanges();
},
onDayCreate: (dObj:Date[], dStr:string, fp:flatpickr.Instance, dayElem:DayElement) => {
onDayCreate: (_dObj:Date[], _dStr:string, _fp:flatpickr.Instance, dayElem:DayElement) => {
onDayCreate(
dayElem,
true,
Expand All @@ -181,6 +190,7 @@ export class OpBasicSingleDatePickerComponent implements ControlValueAccessor, A

writeValue(value:string):void {
this.value = value;
this.datePickerInstance?.setDates(this.value);
}

onChange = (_:string):void => {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ export class HalResourceEditFieldHandler extends EditFieldHandler {

return this
.onSubmit()
.then(() => this.form.submit())
.then(() => {
void this.form.submit();
this.blurActiveField();
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ import { TimezoneService } from 'core-app/core/datetime/timezone.service';
<op-basic-single-date-picker
[(ngModel)]="value"
(keydown.escape)="onCancel()"
[id]="handler.htmlId"
(keydown.enter)="handler.handleUserSubmit()"
(picked)="handler.handleUserSubmit()"
class="inline-edit--field"
[id]="handler.htmlId"
[required]="required"
[disabled]="inFlight"
[opAutofocus]="autofocus"
></op-basic-single-date-picker>
`,
Expand All @@ -61,7 +65,13 @@ export class DateEditFieldComponent extends EditFieldComponent implements OnInit

public set value(value:string) {
this.resource[this.name] = this.parseValue(value);
void this.handler.handleUserSubmit();
}

public parseValue(data:string) {
if (moment(data, 'YYYY-MM-DD', true).isValid()) {
return data;
}
return null;
}

public onCancel():void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
display: flex

&_reversed
margin-left: auto
padding-left: 0.5rem
padding-right: 0

Expand Down

0 comments on commit a14c123

Please sign in to comment.