Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: Date Picker with only "date" or "time" does not display correctly #2115

Merged
merged 3 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor';
import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor';
import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UmbInputDateElement } from '@umbraco-cms/backoffice/components';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
Expand Down Expand Up @@ -42,13 +42,16 @@ export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implemen
@property()
value?: string;

@state()
private _inputValue?: string;

public set config(config: UmbPropertyEditorConfigCollection | undefined) {
if (!config) return;

// Format string prevalue/config
const format = config.getValueByAlias<string>('format');
const hasTime = format?.includes('H') || format?.includes('m');
const hasSeconds = format?.includes('s');
const hasTime = (format?.includes('H') || format?.includes('m')) ?? false;
const hasSeconds = format?.includes('s') ?? false;
this._inputType = hasTime ? 'datetime-local' : 'date';

// Based on the type of format string change the UUI-input type
Expand All @@ -70,33 +73,54 @@ export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implemen
}

#onChange(event: CustomEvent & { target: UmbInputDateElement }) {
this.#formatValue(event.target.value.toString());
let value = event.target.value.toString();

switch (this._inputType) {
case 'time':
value = `0001-01-01 ${value}`;
break;
case 'date':
value = `${value} 00:00:00`;
break;
case 'datetime-local':
value = value.replace('T', ' ');
break;
}

this.#syncValue(value);
}

/**
* Formats the value depending on the input type.
*/
#formatValue(value: string) {
// Check that the value is a valid date
const valueToDate = new Date(value);
if (isNaN(valueToDate.getTime())) {
console.warn('[Umbraco.DatePicker] The value is not a valid date.', value);
this._inputValue = undefined;

if (isNaN(new Date(value).getTime())) {
console.warn(`[UmbDatePicker] Invalid date: ${value}`);
return;
}

// Replace the potential time demoninator 'T' with a whitespace for backwards compatibility
value = value.replace('T', ' ');

// If the inputType is 'date', we need to make sure the value doesn't have a time
if (this._inputType === 'date' && value.includes(' ')) {
value = value.split(' ')[0];
const dateSplit = value.split(' ');
if (dateSplit.length !== 2) {
console.warn(`[UmbDatePicker] Invalid date: ${value}`);
return;
}

// If the inputType is 'time', we need to remove the date part of the value
if (this._inputType === 'time' && value.includes(' ')) {
value = value.split(' ')[1];
switch (this._inputType) {
case 'time':
this._inputValue = dateSplit[1];
break;
case 'date':
this._inputValue = dateSplit[0];
break;
default:
this._inputValue = dateSplit.join('T');
break;
}
}

#syncValue(value: string) {
const valueHasChanged = this.value !== value;
if (valueHasChanged) {
this.value = value;
Expand All @@ -107,7 +131,7 @@ export class UmbPropertyEditorUIDatePickerElement extends UmbLitElement implemen
override render() {
return html`
<umb-input-date
value="${ifDefined(this.value)}"
.value=${this._inputValue}
.min=${this._min}
.max=${this._max}
.step=${this._step}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,60 @@ describe('UmbPropertyEditorUIDatePickerElement', () => {
await expect(element).shadowDom.to.be.accessible(defaultA11yConfig);
});
}

describe('input', () => {
it('should format the value to a datetime-local', async () => {
element.value = '2024-05-03 10:44:00';
element.config = new UmbPropertyEditorConfigCollection([{ alias: 'format', value: 'YYYY-MM-dd HH:mm:ss' }]);
await element.updateComplete;
expect((element as any)._inputValue).to.equal('2024-05-03T10:44:00');
});

it('should format the value to a date', async () => {
element.value = '2024-05-03 10:44:00';
element.config = new UmbPropertyEditorConfigCollection([{ alias: 'format', value: 'YYYY-MM-dd' }]);
await element.updateComplete;
expect((element as any)._inputValue).to.equal('2024-05-03');
});

it('should format the value to a time', async () => {
element.value = '2024-05-03 10:44:00';
element.config = new UmbPropertyEditorConfigCollection([{ alias: 'format', value: 'HH:mm' }]);
await element.updateComplete;
expect((element as any)._inputValue).to.equal('10:44:00');
});

it('should disregard a non-datetime value', async () => {
element.value = '03/05/2024 10:44:00';
await element.updateComplete;
expect((element as any)._inputValue).to.be.undefined;
});
});

describe('output', () => {
it('should format the value to a datetime-local', async () => {
inputElement.value = '2024-05-03T10:44:00';
inputElement.dispatchEvent(new CustomEvent('change'));
await element.updateComplete;
expect(element.value).to.equal('2024-05-03 10:44:00');
});

it('should format the value to a date', async () => {
element.config = new UmbPropertyEditorConfigCollection([{ alias: 'format', value: 'YYYY-MM-dd' }]);
await element.updateComplete;
inputElement.value = '2024-05-03';
inputElement.dispatchEvent(new CustomEvent('change'));
await element.updateComplete;
expect(element.value).to.equal('2024-05-03 00:00:00');
});

it('should format the value to a time', async () => {
element.config = new UmbPropertyEditorConfigCollection([{ alias: 'format', value: 'HH:mm' }]);
await element.updateComplete;
inputElement.value = '10:44:00';
inputElement.dispatchEvent(new CustomEvent('change'));
await element.updateComplete;
expect(element.value).to.equal('0001-01-01 10:44:00');
});
});
});
Loading