Skip to content

Commit b97525e

Browse files
committed
MBS-12230: Update date parser when date changes
This makes it so that the date parser and the parsed date are kept in sync, so it is easier to edit and copy the dates.
1 parent 92e1e42 commit b97525e

File tree

8 files changed

+176
-85
lines changed

8 files changed

+176
-85
lines changed

root/static/scripts/alias/AliasEditForm.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import isBlank from '../common/utility/isBlank.js';
1717
import DateRangeFieldset, {
1818
type ActionT as DateRangeFieldsetActionT,
1919
runReducer as runDateRangeFieldsetReducer,
20+
setInitialStateOnForm as setInitialDateRangeFieldsetStateOnForm,
2021
} from '../edit/components/DateRangeFieldset.js';
2122
import EnterEdit from '../edit/components/EnterEdit.js';
2223
import EnterEditNote from '../edit/components/EnterEditNote.js';
@@ -96,7 +97,7 @@ const blankDatePeriod = {
9697

9798
function createInitialState(form: AliasEditFormT, searchHintType: number) {
9899
return {
99-
form,
100+
form: setInitialDateRangeFieldsetStateOnForm(form),
100101
guessCaseOptions: createGuessCaseOptionsState(),
101102
isEnded: form.field.period.field.ended.value,
102103
isGuessCaseOptionsOpen: false,

root/static/scripts/common/utility/formatDate.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,34 @@ import ko from 'knockout';
1111

1212
import {fixedWidthInteger} from './strings.js';
1313

14-
function formatDate(date: ?PartialDateT): string {
14+
function formatDate(date: ?{
15+
+day?: ?StrOrNum,
16+
+month?: ?StrOrNum,
17+
+year?: ?StrOrNum,
18+
}): string {
1519
if (!date) {
1620
return '';
1721
}
1822

19-
const y: number | null = ko.unwrap(date.year ?? null);
20-
const m: number | null = ko.unwrap(date.month ?? null);
21-
const d: number | null = ko.unwrap(date.day ?? null);
23+
const y: StrOrNum | null = ko.unwrap(date.year ?? null);
24+
const m: StrOrNum | null = ko.unwrap(date.month ?? null);
25+
const d: StrOrNum | null = ko.unwrap(date.day ?? null);
2226

2327
let result = '';
2428

2529
if (nonEmpty(y)) {
2630
result += fixedWidthInteger(y, 4);
27-
} else if (m != null || d != null) {
31+
} else if (nonEmpty(m) || nonEmpty(d)) {
2832
result = '????';
2933
}
3034

31-
if (m != null) {
35+
if (nonEmpty(m)) {
3236
result += '-' + fixedWidthInteger(m, 2);
33-
} else if (d != null) {
37+
} else if (nonEmpty(d)) {
3438
result += '-??';
3539
}
3640

37-
if (d != null) {
41+
if (nonEmpty(d)) {
3842
result += '-' + fixedWidthInteger(d, 2);
3943
}
4044

root/static/scripts/edit/components/DateRangeFieldset.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import FormRowPartialDate, {
2222
type ActionT as FormRowPartialDateActionT,
2323
runReducer as runFormRowPartialDateReducer,
2424
} from './FormRowPartialDate.js';
25+
import {
26+
createInitialState as createPartialDateInputState,
27+
} from './PartialDateInput.js';
2528

2629
/* eslint-disable ft-flow/sort-keys */
2730
export type ActionT =
@@ -33,6 +36,11 @@ export type ActionT =
3336

3437
export type StateT = DatePeriodFieldT;
3538

39+
type FormWithDateRangeT = FormT<{
40+
+period: DatePeriodFieldT,
41+
...
42+
}>;
43+
3644
export function partialDateFromField(
3745
compoundField: PartialDateFieldT,
3846
): PartialDateT {
@@ -44,6 +52,26 @@ export function partialDateFromField(
4452
};
4553
}
4654

55+
export function setInitialStateOnForm<T: FormWithDateRangeT>(form: T): T {
56+
const formCtx = mutate(form);
57+
// $FlowIssue[incompatible-call]
58+
const periodCtx = formCtx.get('field', 'period');
59+
periodCtx.set(createInitialState(periodCtx.read()));
60+
return formCtx.final();
61+
}
62+
63+
64+
export function createInitialState(
65+
field: StateT,
66+
): StateT {
67+
const fieldCtx = mutate(field);
68+
const beginDateField = fieldCtx.get('field', 'begin_date');
69+
beginDateField.set(createPartialDateInputState(beginDateField.read()));
70+
const endDateField = fieldCtx.get('field', 'end_date');
71+
endDateField.set(createPartialDateInputState(endDateField.read()));
72+
return fieldCtx.final();
73+
}
74+
4775
function validateDatePeriod(stateCtx: CowContext<StateT>) {
4876
const state = stateCtx.read();
4977
const beginDateField = state.field.begin_date;

root/static/scripts/edit/components/ExternalLinkAttributeDialog.js

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import DateRangeFieldset, {
3030
partialDateFromField,
3131
runReducer as runDateRangeFieldsetReducer,
3232
} from './DateRangeFieldset.js';
33+
import {formatParserDate} from './PartialDateInput.js';
3334
import UrlRelationshipCreditFieldset
3435
from './UrlRelationshipCreditFieldset.js';
3536

@@ -66,25 +67,35 @@ const createInitialState = (
6667
: null,
6768
);
6869

70+
const beginDateField = createCompoundFieldFromObject(
71+
'period.begin_date',
72+
{
73+
day: beginDate?.day ?? null,
74+
month: beginDate?.month ?? null,
75+
year: beginDate?.year ?? null,
76+
},
77+
);
78+
79+
const endDateField = createCompoundFieldFromObject(
80+
'period.end_date',
81+
{
82+
day: endDate?.day ?? null,
83+
month: endDate?.month ?? null,
84+
year: endDate?.year ?? null,
85+
},
86+
);
87+
6988
const datePeriodField = {
7089
errors: [],
7190
field: {
72-
begin_date: createCompoundFieldFromObject(
73-
'period.begin_date',
74-
{
75-
day: beginDate?.day ?? null,
76-
month: beginDate?.month ?? null,
77-
year: beginDate?.year ?? null,
78-
},
79-
),
80-
end_date: createCompoundFieldFromObject(
81-
'period.end_date',
82-
{
83-
day: endDate?.day ?? null,
84-
month: endDate?.month ?? null,
85-
year: endDate?.year ?? null,
86-
},
87-
),
91+
begin_date: {
92+
...beginDateField,
93+
formattedDate: formatParserDate(beginDateField),
94+
},
95+
end_date: {
96+
...endDateField,
97+
formattedDate: formatParserDate(endDateField),
98+
},
8899
ended: createField('period.ended', relationship.ended),
89100
},
90101
has_errors: false,

root/static/scripts/edit/components/PartialDateInput.js

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import type {CowContext} from 'mutate-cow';
1111

12+
import formatDate from '../../common/utility/formatDate.js';
1213
import parseNaturalDate from '../../common/utility/parseNaturalDate.js';
1314
import {isDateValid, isYearFourDigits} from '../utility/dates.js';
1415
import {applyPendingErrors} from '../utility/subfieldErrors.js';
@@ -17,12 +18,9 @@ import {applyPendingErrors} from '../utility/subfieldErrors.js';
1718
export type ActionT =
1819
| {
1920
+type: 'set-date',
20-
+date: {
21-
+year?: string,
22-
+month?: string,
23-
+day?: string,
24-
},
21+
+date: PartialDateStringsT,
2522
}
23+
| {+type: 'set-parsed-date', +date: string}
2624
| {+type: 'show-pending-errors'};
2725
/* eslint-enable ft-flow/sort-keys */
2826

@@ -32,6 +30,39 @@ type ControlledPropsT =
3230

3331
export type StateT = PartialDateFieldT;
3432

33+
export function createInitialState(
34+
date: StateT,
35+
): StateT {
36+
return {
37+
...date,
38+
formattedDate: formatParserDate(date),
39+
};
40+
}
41+
42+
export function formatParserDate(date: StateT): string {
43+
return formatDate({
44+
day: date.field.day.value,
45+
month: date.field.month.value,
46+
year: date.field.year.value,
47+
});
48+
}
49+
50+
function updateDate(dateCtx: CowContext<StateT>, date: PartialDateStringsT) {
51+
const newYear = date.year;
52+
const newMonth = date.month;
53+
const newDay = date.day;
54+
if (newYear != null) {
55+
dateCtx.set('field', 'year', 'value', newYear);
56+
}
57+
if (newMonth != null) {
58+
dateCtx.set('field', 'month', 'value', newMonth);
59+
}
60+
if (newDay != null) {
61+
dateCtx.set('field', 'day', 'value', newDay);
62+
}
63+
validateDate(dateCtx);
64+
}
65+
3566
function validateDate(dateCtx: CowContext<StateT>) {
3667
const date = dateCtx.read();
3768
const year = String(date.field.year.value ?? '');
@@ -66,20 +97,20 @@ export function runReducer(
6697
applyPendingErrors(state);
6798
break;
6899
}
100+
case 'set-parsed-date': {
101+
const date = parseNaturalDate(action.date);
102+
updateDate(state, date);
103+
state.set('formattedDate', action.date);
104+
break;
105+
}
69106
case 'set-date': {
70-
const newYear = action.date.year;
71-
const newMonth = action.date.month;
72-
const newDay = action.date.day;
73-
if (newYear != null) {
74-
state.set('field', 'year', 'value', newYear);
107+
updateDate(state, action.date);
108+
const formattedDate = formatParserDate(state.read());
109+
if (nonEmpty(formattedDate)) {
110+
state.set('formattedDate', formatParserDate(state.read()));
111+
} else {
112+
state.set('formattedDate', formatParserDate(state.read()));
75113
}
76-
if (newMonth != null) {
77-
state.set('field', 'month', 'value', newMonth);
78-
}
79-
if (newDay != null) {
80-
state.set('field', 'day', 'value', newDay);
81-
}
82-
validateDate(state);
83114
break;
84115
}
85116
}
@@ -95,6 +126,7 @@ type DatePartPropsT = {
95126
type DateParserPropsT = {
96127
onBlur?: () => void,
97128
onChange?: (SyntheticEvent<HTMLInputElement>) => void,
129+
value?: string,
98130
};
99131

100132
component PartialDateInput(
@@ -147,16 +179,16 @@ component PartialDateInput(
147179
);
148180

149181
parserProps.onChange = (event) => {
150-
const date = parseNaturalDate(event.currentTarget.value);
151182
controlledProps.dispatch({
152-
date,
153-
type: 'set-date',
183+
date: event.currentTarget.value,
184+
type: 'set-parsed-date',
154185
});
155186
};
156187

157188
yearProps.value = field.field.year.value ?? '';
158189
monthProps.value = field.field.month.value ?? '';
159190
dayProps.value = field.field.day.value ?? '';
191+
parserProps.value = field.formattedDate ?? '';
160192
}
161193

162194
return (

root/static/scripts/event/components/EventEditForm.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import isBlank from '../../common/utility/isBlank.js';
1818
import DateRangeFieldset, {
1919
type ActionT as DateRangeFieldsetActionT,
2020
runReducer as runDateRangeFieldsetReducer,
21+
setInitialStateOnForm as setInitialDateRangeFieldsetStateOnForm,
2122
} from '../../edit/components/DateRangeFieldset.js';
2223
import EnterEdit from '../../edit/components/EnterEdit.js';
2324
import EnterEditNote from '../../edit/components/EnterEditNote.js';
@@ -67,7 +68,7 @@ type StateT = {
6768

6869
function createInitialState(form: EventFormT) {
6970
return {
70-
form,
71+
form: setInitialDateRangeFieldsetStateOnForm(form),
7172
guessCaseOptions: createGuessCaseOptionsState(),
7273
isGuessCaseOptionsOpen: false,
7374
showTypeBubble: false,

0 commit comments

Comments
 (0)