Skip to content

Commit 639e647

Browse files
committed
Handle all supported date value types in date picker
1 parent 3d3615a commit 639e647

5 files changed

Lines changed: 86 additions & 2 deletions

File tree

src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,44 @@ describe('DsDatePickerComponent test suite', () => {
206206
});
207207
});
208208

209+
describe('when init model value is a Date object', () => {
210+
beforeEach(() => {
211+
dateFixture = TestBed.createComponent(DsDatePickerComponent);
212+
dateComp = dateFixture.componentInstance;
213+
dateComp.group = DATE_TEST_GROUP;
214+
dateComp.model = new DynamicDsDatePickerModel(DATE_TEST_MODEL_CONFIG);
215+
dateComp.model.value = new Date(Date.UTC(1983, 10, 18));
216+
dateFixture.detectChanges();
217+
});
218+
219+
it('should init component properly from a Date object', () => {
220+
expect(dateComp.year).toBe(1983);
221+
expect(dateComp.month).toBe(11);
222+
expect(dateComp.day).toBe(18);
223+
expect(dateComp.disabledMonth).toBeFalsy();
224+
expect(dateComp.disabledDay).toBeFalsy();
225+
});
226+
});
227+
228+
describe('when init model value is a NgbDateStruct-like object', () => {
229+
beforeEach(() => {
230+
dateFixture = TestBed.createComponent(DsDatePickerComponent);
231+
dateComp = dateFixture.componentInstance;
232+
dateComp.group = DATE_TEST_GROUP;
233+
dateComp.model = new DynamicDsDatePickerModel(DATE_TEST_MODEL_CONFIG);
234+
dateComp.model.value = { year: 1983, month: 11, day: 18 };
235+
dateFixture.detectChanges();
236+
});
237+
238+
it('should init component properly from a NgbDateStruct-like object', () => {
239+
expect(dateComp.year).toBe(1983);
240+
expect(dateComp.month).toBe(11);
241+
expect(dateComp.day).toBe(18);
242+
expect(dateComp.disabledMonth).toBeFalsy();
243+
expect(dateComp.disabledDay).toBeFalsy();
244+
});
245+
});
246+
209247
describe('when init model value is not empty', () => {
210248
beforeEach(() => {
211249

src/app/shared/form/builder/ds-dynamic-form-ui/models/date-picker/date-picker.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
FormsModule,
1515
UntypedFormGroup,
1616
} from '@angular/forms';
17+
import { dateValueToString } from '@dspace/shared/utils/date.util';
1718
import { hasValue } from '@dspace/shared/utils/empty.util';
1819
import {
1920
DynamicFormControlComponent,
@@ -91,7 +92,7 @@ export class DsDatePickerComponent extends DynamicFormControlComponent implement
9192
if (this.model && this.model.value !== null) {
9293
// todo: model value could object or Date according to its type annotation
9394
// eslint-disable-next-line @typescript-eslint/no-base-to-string
94-
const values = this.model.value.toString().split(DS_DATE_PICKER_SEPARATOR);
95+
const values = dateValueToString(this.model.value).split(DS_DATE_PICKER_SEPARATOR);
9596
if (values.length > 0) {
9697
this.initialYear = parseInt(values[0], 10);
9798
this.year = this.initialYear;

src/app/shared/form/builder/parsers/date-field-parser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { FormFieldMetadataValueObject } from '@dspace/core/shared/form/models/form-field-metadata-value.model';
2+
import { dateValueToString } from '@dspace/shared/utils/date.util';
23
import { isNotEmpty } from '@dspace/shared/utils/empty.util';
34

45
import { DS_DATE_PICKER_SEPARATOR } from '../ds-dynamic-form-ui/models/date-picker/date-picker.component';
@@ -21,7 +22,7 @@ export class DateFieldParser extends FieldParser {
2122
if (isNotEmpty(inputDateModelConfig.value)) {
2223
// todo: model value could be object or Date according to its type annotation
2324
// eslint-disable-next-line @typescript-eslint/no-base-to-string
24-
const value = inputDateModelConfig.value.toString();
25+
const value = dateValueToString(inputDateModelConfig.value);
2526
if (value.length >= 4) {
2627
const valuesArray = value.split(DS_DATE_PICKER_SEPARATOR);
2728
if (valuesArray.length < 4) {

src/app/utils/date.util.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
dateToISOFormat,
33
dateToNgbDateStruct,
44
dateToString,
5+
dateValueToString,
56
isValidDate,
67
yearFromString,
78
} from './date.util';
@@ -93,6 +94,24 @@ describe('Date Utils', () => {
9394
});
9495
});
9596

97+
describe('dateValueToString', () => {
98+
it('should return the same string when given a string', () => {
99+
expect(dateValueToString('1983-11-18')).toEqual('1983-11-18');
100+
});
101+
it('should return YYYY-MM-DD when given a Date object', () => {
102+
expect(dateValueToString(new Date(Date.UTC(1983, 10, 18)))).toEqual('1983-11-18');
103+
});
104+
it('should return YYYY-MM-DD when given a NgbDateStruct-like object', () => {
105+
expect(dateValueToString({ year: 1983, month: 11, day: 18 })).toEqual('1983-11-18');
106+
});
107+
it('should throw an error for an arbitrary object', () => {
108+
expect(() => dateValueToString({ foo: 'bar' })).toThrowError(/Unsupported date value type/);
109+
});
110+
it('should throw an error for an empty object', () => {
111+
expect(() => dateValueToString({})).toThrowError(/Unsupported date value type/);
112+
});
113+
});
114+
96115
describe('yearFromString', () => {
97116
it('should return year from YYYY string', () => {
98117
expect(yearFromString('2022')).toEqual(2022);

src/app/utils/date.util.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,28 @@ export function yearFromString(date: string) {
108108
return isValidDate(date) ? new Date(date).getUTCFullYear() : null;
109109
}
110110

111+
/**
112+
* Converts a date model value (string | Date | object) to a YYYY-MM-DD formatted string.
113+
*
114+
* The dynamic form library defines date values as string | object | Date.
115+
* This function safely handles all supported types and throws an informative
116+
* error if an unsupported object type is encountered.
117+
*
118+
* @param value The date value to convert
119+
* @returns The date as a string (e.g. "1983-11-18")
120+
* @throws Error if value is an object without year/month/day properties
121+
*/
122+
export function dateValueToString(value: string | Date | object): string {
123+
if (typeof value === 'string') {
124+
return value;
125+
}
126+
if (value instanceof Date) {
127+
return dateToString(value);
128+
}
129+
if (isNgbDateStruct(value)) {
130+
return dateToString(value as NgbDateStruct);
131+
}
132+
throw new Error(
133+
`Unsupported date value type: expected a string, Date, or object with {year, month, day} properties, but received: ${JSON.stringify(value)}`,
134+
);
135+
}

0 commit comments

Comments
 (0)