dce-reactkit 4.0.2-beta-simple-date-chooser.1 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +702 -954
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Pagination.d.ts +13 -0
- package/dist/cjs/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- package/dist/cjs/types/helpers/cloneDeep.d.ts +8 -0
- package/dist/cjs/types/index.d.ts +4 -1
- package/dist/cjs/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +17 -0
- package/dist/cjs/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +21 -0
- package/dist/cjs/types/types/LogReviewerFilterState/ContextFilterState.d.ts +10 -0
- package/dist/cjs/types/types/LogReviewerFilterState/DateFilterState.d.ts +17 -0
- package/dist/cjs/types/types/LogReviewerFilterState/TagFilterState.d.ts +8 -0
- package/dist/cjs/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/esm/index.js +701 -956
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Pagination.d.ts +13 -0
- package/dist/esm/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- package/dist/esm/types/helpers/cloneDeep.d.ts +8 -0
- package/dist/esm/types/index.d.ts +4 -1
- package/dist/esm/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +17 -0
- package/dist/esm/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +21 -0
- package/dist/esm/types/types/LogReviewerFilterState/ContextFilterState.d.ts +10 -0
- package/dist/esm/types/types/LogReviewerFilterState/DateFilterState.d.ts +17 -0
- package/dist/esm/types/types/LogReviewerFilterState/TagFilterState.d.ts +8 -0
- package/dist/esm/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/index.d.ts +98 -1
- package/package.json +2 -1
- package/src/components/LogReviewer.tsx +1133 -1307
- package/src/components/Pagination.tsx +172 -0
- package/src/components/SimpleDateChooser.tsx +95 -337
- package/src/constants/LOG_REVIEW_GET_LOGS_ROUTE.ts +9 -0
- package/src/helpers/cloneDeep.ts +11 -0
- package/src/index.ts +6 -0
- package/src/types/LogReviewerFilterState/ActionErrorFilterState.ts +24 -0
- package/src/types/LogReviewerFilterState/AdvancedFilterState.ts +36 -0
- package/src/types/LogReviewerFilterState/ContextFilterState.ts +16 -0
- package/src/types/LogReviewerFilterState/DateFilterState.ts +26 -0
- package/src/types/LogReviewerFilterState/TagFilterState.ts +9 -0
- package/src/types/LogReviewerFilterState/index.ts +24 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Import React
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
// Import FontAwesome
|
|
5
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
6
|
+
import { faArrowLeft, faArrowRight } from '@fortawesome/free-solid-svg-icons';
|
|
7
|
+
|
|
8
|
+
/*------------------------------------------------------------------------*/
|
|
9
|
+
/* -------------------------------- Types ------------------------------- */
|
|
10
|
+
/*------------------------------------------------------------------------*/
|
|
11
|
+
|
|
12
|
+
// Props
|
|
13
|
+
type Props = {
|
|
14
|
+
// Current page number (1-indexed)
|
|
15
|
+
currentPage: number,
|
|
16
|
+
// Total number of pages
|
|
17
|
+
numPages: number,
|
|
18
|
+
// True if a page change is in progress (to disable buttons)
|
|
19
|
+
loading?: boolean,
|
|
20
|
+
/**
|
|
21
|
+
* Handler for when page is changed
|
|
22
|
+
* @param page - the new page number
|
|
23
|
+
*/
|
|
24
|
+
onPageChanged: (page: number) => void,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/*------------------------------------------------------------------------*/
|
|
28
|
+
/* ------------------------------ Component ----------------------------- */
|
|
29
|
+
/*------------------------------------------------------------------------*/
|
|
30
|
+
|
|
31
|
+
const Pagination: React.FC<Props> = (props: Props) => {
|
|
32
|
+
/*------------------------------------------------------------------------*/
|
|
33
|
+
/* -------------------------------- Setup ------------------------------- */
|
|
34
|
+
/*------------------------------------------------------------------------*/
|
|
35
|
+
|
|
36
|
+
/* -------------- Props ------------- */
|
|
37
|
+
|
|
38
|
+
// Destructure props
|
|
39
|
+
const {
|
|
40
|
+
currentPage,
|
|
41
|
+
numPages,
|
|
42
|
+
loading = false,
|
|
43
|
+
onPageChanged,
|
|
44
|
+
} = props;
|
|
45
|
+
|
|
46
|
+
/*------------------------------------------------------------------------*/
|
|
47
|
+
/* ------------------------------- Render ------------------------------- */
|
|
48
|
+
/*------------------------------------------------------------------------*/
|
|
49
|
+
|
|
50
|
+
// Compute pages to display
|
|
51
|
+
const pages: number[] = [];
|
|
52
|
+
const delta = 2; // how many pages to show on either side of current
|
|
53
|
+
let start = Math.max(1, currentPage - delta);
|
|
54
|
+
let end = Math.min(numPages, currentPage + delta);
|
|
55
|
+
|
|
56
|
+
// If we are too close to the beginning or end, shift the window.
|
|
57
|
+
if (currentPage - delta < 1) {
|
|
58
|
+
end = Math.min(numPages, end + (1 - (currentPage - delta)));
|
|
59
|
+
}
|
|
60
|
+
if (currentPage + delta > numPages) {
|
|
61
|
+
start = Math.max(1, start - ((currentPage + delta) - numPages));
|
|
62
|
+
}
|
|
63
|
+
for (let i = start; i <= end; i++) {
|
|
64
|
+
pages.push(i);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Render
|
|
68
|
+
return (
|
|
69
|
+
<nav
|
|
70
|
+
aria-label="Page navigation for logs"
|
|
71
|
+
className="mt-3"
|
|
72
|
+
>
|
|
73
|
+
<ul className="pagination justify-content-center">
|
|
74
|
+
{/* Previous Button */}
|
|
75
|
+
<li className={`page-item ${(currentPage <= 1 || loading) ? 'disabled' : ''}`}>
|
|
76
|
+
<button
|
|
77
|
+
type="button"
|
|
78
|
+
className="page-link"
|
|
79
|
+
onClick={() => { return onPageChanged(currentPage - 1); }}
|
|
80
|
+
disabled={currentPage <= 1 || loading}
|
|
81
|
+
aria-label="Go to previous page"
|
|
82
|
+
>
|
|
83
|
+
<FontAwesomeIcon icon={faArrowLeft} />
|
|
84
|
+
{' '}
|
|
85
|
+
Prev
|
|
86
|
+
</button>
|
|
87
|
+
</li>
|
|
88
|
+
|
|
89
|
+
{/* First page (if needed) */}
|
|
90
|
+
{(currentPage > 3 && pages[0] !== 1) && (
|
|
91
|
+
<li className="page-item">
|
|
92
|
+
<button
|
|
93
|
+
type="button"
|
|
94
|
+
className="page-link"
|
|
95
|
+
onClick={() => { return onPageChanged(1); }}
|
|
96
|
+
disabled={loading}
|
|
97
|
+
aria-label="Go to page 1"
|
|
98
|
+
>
|
|
99
|
+
1
|
|
100
|
+
</button>
|
|
101
|
+
</li>
|
|
102
|
+
)}
|
|
103
|
+
|
|
104
|
+
{/* Ellipsis if gap between first page and start of window */}
|
|
105
|
+
{currentPage > 4 && (
|
|
106
|
+
<li className="page-item disabled">
|
|
107
|
+
<span className="page-link">...</span>
|
|
108
|
+
</li>
|
|
109
|
+
)}
|
|
110
|
+
|
|
111
|
+
{/* Page numbers */}
|
|
112
|
+
{pages.map((pageNum) => {
|
|
113
|
+
return (
|
|
114
|
+
<li key={pageNum} className={`page-item ${pageNum === currentPage ? 'active' : ''}`}>
|
|
115
|
+
<button
|
|
116
|
+
type="button"
|
|
117
|
+
className="page-link"
|
|
118
|
+
onClick={() => { return onPageChanged(pageNum); }}
|
|
119
|
+
disabled={loading}
|
|
120
|
+
aria-label={`Go to page ${pageNum}`}
|
|
121
|
+
>
|
|
122
|
+
{pageNum}
|
|
123
|
+
</button>
|
|
124
|
+
</li>
|
|
125
|
+
);
|
|
126
|
+
})}
|
|
127
|
+
|
|
128
|
+
{/* Ellipsis if gap between end of window and last page */}
|
|
129
|
+
{currentPage < numPages - 3 && (
|
|
130
|
+
<li className="page-item disabled">
|
|
131
|
+
<span className="page-link">...</span>
|
|
132
|
+
</li>
|
|
133
|
+
)}
|
|
134
|
+
|
|
135
|
+
{/* Last page (if needed) */}
|
|
136
|
+
{(
|
|
137
|
+
currentPage < numPages - 2
|
|
138
|
+
&& pages[pages.length - 1] !== numPages
|
|
139
|
+
) && (
|
|
140
|
+
<li className="page-item">
|
|
141
|
+
<button
|
|
142
|
+
type="button"
|
|
143
|
+
className="page-link"
|
|
144
|
+
onClick={() => { return onPageChanged(numPages); }}
|
|
145
|
+
disabled={loading}
|
|
146
|
+
aria-label="Go to last page"
|
|
147
|
+
>
|
|
148
|
+
{numPages}
|
|
149
|
+
</button>
|
|
150
|
+
</li>
|
|
151
|
+
)}
|
|
152
|
+
|
|
153
|
+
{/* Next Button */}
|
|
154
|
+
<li className={`page-item ${(currentPage >= numPages || loading) ? 'disabled' : ''}`}>
|
|
155
|
+
<button
|
|
156
|
+
type="button"
|
|
157
|
+
className="page-link"
|
|
158
|
+
onClick={() => { return onPageChanged(currentPage + 1); }}
|
|
159
|
+
disabled={currentPage >= numPages || loading}
|
|
160
|
+
aria-label="Go to next page"
|
|
161
|
+
>
|
|
162
|
+
Next
|
|
163
|
+
{' '}
|
|
164
|
+
<FontAwesomeIcon icon={faArrowRight} />
|
|
165
|
+
</button>
|
|
166
|
+
</li>
|
|
167
|
+
</ul>
|
|
168
|
+
</nav>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export default Pagination;
|
|
@@ -5,10 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
// Import React
|
|
8
|
-
import React
|
|
9
|
-
|
|
10
|
-
// Import AppWrapper helpers
|
|
11
|
-
import { confirm } from './AppWrapper';
|
|
8
|
+
import React from 'react';
|
|
12
9
|
|
|
13
10
|
// Import helpers
|
|
14
11
|
import getOrdinal from '../helpers/getOrdinal';
|
|
@@ -54,86 +51,32 @@ type Props = {
|
|
|
54
51
|
};
|
|
55
52
|
|
|
56
53
|
/*------------------------------------------------------------------------*/
|
|
57
|
-
/*
|
|
54
|
+
/* ------------------------------ Component ----------------------------- */
|
|
58
55
|
/*------------------------------------------------------------------------*/
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
DateChooser = 'DateChooser',
|
|
65
|
-
// Invalid date
|
|
66
|
-
InvalidDate = 'InvalidDate',
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/* -------- State Definition -------- */
|
|
70
|
-
|
|
71
|
-
type State = {
|
|
72
|
-
view: View,
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/* ------------- Actions ------------ */
|
|
76
|
-
|
|
77
|
-
// Types of actions
|
|
78
|
-
enum ActionType {
|
|
79
|
-
// Fix invalid date so it is now in range
|
|
80
|
-
FixInvalidDate = 'FixInvalidDate',
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Action definitions
|
|
84
|
-
type Action = {
|
|
85
|
-
// Action type
|
|
86
|
-
type: ActionType.FixInvalidDate,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Reducer that executes actions
|
|
91
|
-
* @author Gardenia Liu
|
|
92
|
-
* @param state current state
|
|
93
|
-
* @param action action to execute
|
|
94
|
-
* @returns updated state
|
|
95
|
-
*/
|
|
96
|
-
const reducer = (state: State, action: Action): State => {
|
|
97
|
-
switch (action.type) {
|
|
98
|
-
case ActionType.FixInvalidDate: {
|
|
99
|
-
return {
|
|
100
|
-
...state,
|
|
101
|
-
view: View.DateChooser,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
default: {
|
|
105
|
-
return state;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
57
|
+
const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
58
|
+
/*------------------------------------------------------------------------*/
|
|
59
|
+
/* -------------------------------- Setup ------------------------------- */
|
|
60
|
+
/*------------------------------------------------------------------------*/
|
|
109
61
|
|
|
110
|
-
|
|
111
|
-
/* --------------------------- Static Helpers --------------------------- */
|
|
112
|
-
/*------------------------------------------------------------------------*/
|
|
62
|
+
/* -------------- Props ------------- */
|
|
113
63
|
|
|
114
|
-
/**
|
|
115
|
-
* Get the list of choices in the date chooser given props
|
|
116
|
-
* @author Gardenia Liu
|
|
117
|
-
* @author Gabe Abrams
|
|
118
|
-
* @param opts object containing all arguments
|
|
119
|
-
* @param opts.numMonthsToShow number of months to show
|
|
120
|
-
* @param opts.dontAllowPast if true, the user isn't allowed to select dates in the past
|
|
121
|
-
* @param opts.dontAllowFuture if true, the user isn't allowed to select dates in the future
|
|
122
|
-
* @returns choices
|
|
123
|
-
*/
|
|
124
|
-
const getChoices = (
|
|
125
|
-
opts: {
|
|
126
|
-
numMonthsToShow?: number,
|
|
127
|
-
dontAllowPast?: boolean,
|
|
128
|
-
dontAllowFuture?: boolean,
|
|
129
|
-
},
|
|
130
|
-
) => {
|
|
131
|
-
// Destructure props
|
|
132
64
|
const {
|
|
65
|
+
ariaLabel,
|
|
66
|
+
name,
|
|
67
|
+
onChange,
|
|
68
|
+
numMonthsToShow = 6,
|
|
133
69
|
dontAllowFuture,
|
|
134
70
|
dontAllowPast,
|
|
135
|
-
|
|
136
|
-
|
|
71
|
+
} = props;
|
|
72
|
+
|
|
73
|
+
/*------------------------------------------------------------------------*/
|
|
74
|
+
/* ------------------------------- Render ------------------------------- */
|
|
75
|
+
/*------------------------------------------------------------------------*/
|
|
76
|
+
|
|
77
|
+
/*----------------------------------------*/
|
|
78
|
+
/* --------------- Main UI -------------- */
|
|
79
|
+
/*----------------------------------------*/
|
|
137
80
|
|
|
138
81
|
// Determine the set of choices allowed
|
|
139
82
|
const today = getTimeInfoInET();
|
|
@@ -228,278 +171,93 @@ const getChoices = (
|
|
|
228
171
|
});
|
|
229
172
|
}
|
|
230
173
|
|
|
231
|
-
//
|
|
232
|
-
return choices;
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Checks whether a given date is outside the valid range of allowed choices
|
|
237
|
-
* @author Gardenia Liu
|
|
238
|
-
* @param opts object containing all arguments
|
|
239
|
-
* @param opts.month 1-indexed month
|
|
240
|
-
* @param opts.day day of the month
|
|
241
|
-
* @param opts.year full year
|
|
242
|
-
* @param opts.choices valid date choices
|
|
243
|
-
* @returns true if date is out of range
|
|
244
|
-
*/
|
|
245
|
-
const isDateOutOfRange = (
|
|
246
|
-
opts: {
|
|
247
|
-
month: number,
|
|
248
|
-
day: number,
|
|
249
|
-
year: number,
|
|
250
|
-
choices: {
|
|
251
|
-
month: number,
|
|
252
|
-
year: number,
|
|
253
|
-
days: number[]
|
|
254
|
-
}[],
|
|
255
|
-
},
|
|
256
|
-
): boolean => {
|
|
174
|
+
// Create choice options
|
|
257
175
|
const {
|
|
258
176
|
month,
|
|
259
177
|
day,
|
|
260
178
|
year,
|
|
261
|
-
choices,
|
|
262
|
-
} = opts;
|
|
263
|
-
|
|
264
|
-
return !choices.some((choice) => {
|
|
265
|
-
return (
|
|
266
|
-
choice.month === month
|
|
267
|
-
&& choice.year === year
|
|
268
|
-
&& choice.days.includes(day)
|
|
269
|
-
);
|
|
270
|
-
});
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
/*------------------------------------------------------------------------*/
|
|
274
|
-
/* ------------------------------ Component ----------------------------- */
|
|
275
|
-
/*------------------------------------------------------------------------*/
|
|
276
|
-
|
|
277
|
-
const SimpleDateChooser: React.FC<Props> = (props) => {
|
|
278
|
-
/*------------------------------------------------------------------------*/
|
|
279
|
-
/* -------------------------------- Setup ------------------------------- */
|
|
280
|
-
/*------------------------------------------------------------------------*/
|
|
281
|
-
|
|
282
|
-
/* -------------- Props ------------- */
|
|
283
|
-
|
|
284
|
-
const {
|
|
285
|
-
ariaLabel,
|
|
286
|
-
name,
|
|
287
|
-
dontAllowPast,
|
|
288
|
-
dontAllowFuture,
|
|
289
|
-
numMonthsToShow,
|
|
290
|
-
onChange,
|
|
291
|
-
month,
|
|
292
|
-
day,
|
|
293
|
-
year,
|
|
294
179
|
} = props;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
choices,
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// Initial state
|
|
314
|
-
const initialState: State = {
|
|
315
|
-
view: (
|
|
316
|
-
currentSelectedDateOutOfRange
|
|
317
|
-
? View.InvalidDate
|
|
318
|
-
: View.DateChooser
|
|
319
|
-
),
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
// Initialize state
|
|
323
|
-
const [state, dispatch] = useReducer(reducer, initialState);
|
|
324
|
-
|
|
325
|
-
// Destructure common state
|
|
326
|
-
const {
|
|
327
|
-
view,
|
|
328
|
-
} = state;
|
|
329
|
-
|
|
330
|
-
/*------------------------------------------------------------------------*/
|
|
331
|
-
/* ------------------------- Component Functions ------------------------ */
|
|
332
|
-
/*------------------------------------------------------------------------*/
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Ask the user if they want to edit an invalid date
|
|
336
|
-
* @author Gardenia Liu
|
|
337
|
-
* @author Gabe Abrams
|
|
338
|
-
*/
|
|
339
|
-
const askToEditInvalidDate = async () => {
|
|
340
|
-
// Ask the user if they want to edit the date
|
|
341
|
-
const confirmed = await confirm(
|
|
342
|
-
'Are you sure?',
|
|
343
|
-
'The current date is outside the normal range. If you edit it, you\'ll need to choose a new date in the normal range.',
|
|
344
|
-
{
|
|
345
|
-
confirmButtonText: 'Edit Date',
|
|
346
|
-
},
|
|
180
|
+
const monthOptions: React.ReactNode[] = [];
|
|
181
|
+
const dayOptions: React.ReactNode[] = [];
|
|
182
|
+
choices.forEach((choice) => {
|
|
183
|
+
// Create month option
|
|
184
|
+
monthOptions.push(
|
|
185
|
+
<option
|
|
186
|
+
key={`${choice.year}-${choice.month}`}
|
|
187
|
+
value={`${choice.month}-${choice.year}`}
|
|
188
|
+
aria-label={`choose ${choice.choiceName}`}
|
|
189
|
+
onSelect={() => {
|
|
190
|
+
onChange(choice.month, choice.days[0], choice.year);
|
|
191
|
+
}}
|
|
192
|
+
>
|
|
193
|
+
{choice.choiceName}
|
|
194
|
+
</option>,
|
|
347
195
|
);
|
|
348
196
|
|
|
349
|
-
//
|
|
350
|
-
if (
|
|
351
|
-
//
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
197
|
+
// This is the currently selected month
|
|
198
|
+
if (month === choice.month) {
|
|
199
|
+
// Create day options
|
|
200
|
+
choice.days.forEach((dayChoice) => {
|
|
201
|
+
const ordinal = getOrdinal(dayChoice);
|
|
202
|
+
dayOptions.push(
|
|
203
|
+
<option
|
|
204
|
+
key={`${choice.year}-${choice.month}-${dayChoice}`}
|
|
205
|
+
value={dayChoice}
|
|
206
|
+
aria-label={`choose date ${dayChoice}`}
|
|
207
|
+
>
|
|
208
|
+
{dayChoice}
|
|
209
|
+
{ordinal}
|
|
210
|
+
</option>,
|
|
211
|
+
);
|
|
358
212
|
});
|
|
359
213
|
}
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
/*------------------------------------------------------------------------*/
|
|
363
|
-
/* ------------------------------- Render ------------------------------- */
|
|
364
|
-
/*------------------------------------------------------------------------*/
|
|
365
|
-
|
|
366
|
-
/*----------------------------------------*/
|
|
367
|
-
/* ---------------- Views --------------- */
|
|
368
|
-
/*----------------------------------------*/
|
|
369
|
-
|
|
370
|
-
// Body that will be filled with the current view
|
|
371
|
-
let body: React.ReactNode;
|
|
372
|
-
|
|
373
|
-
/* ---------- DateChooser ---------- */
|
|
374
|
-
|
|
375
|
-
if (view === View.DateChooser) {
|
|
376
|
-
// Create lists of options
|
|
377
|
-
const monthOptions: React.ReactNode[] = [];
|
|
378
|
-
const dayOptions: React.ReactNode[] = [];
|
|
379
|
-
|
|
380
|
-
// Render each option and add it to the list
|
|
381
|
-
choices.forEach((choice) => {
|
|
382
|
-
// Create month option
|
|
383
|
-
monthOptions.push(
|
|
384
|
-
<option
|
|
385
|
-
key={`${choice.year}-${choice.month}`}
|
|
386
|
-
value={`${choice.month}-${choice.year}`}
|
|
387
|
-
aria-label={`choose ${choice.choiceName}`}
|
|
388
|
-
onSelect={() => {
|
|
389
|
-
onChange(choice.month, choice.days[0], choice.year);
|
|
390
|
-
}}
|
|
391
|
-
>
|
|
392
|
-
{choice.choiceName}
|
|
393
|
-
</option>,
|
|
394
|
-
);
|
|
214
|
+
});
|
|
395
215
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
216
|
+
return (
|
|
217
|
+
<div
|
|
218
|
+
className="SimpleDateChooser d-inline-block"
|
|
219
|
+
aria-label={`date chooser with selected date: ${month}/${day}/${year}`}
|
|
220
|
+
>
|
|
221
|
+
{/* Month Chooser */}
|
|
222
|
+
<select
|
|
223
|
+
aria-label={`month for ${ariaLabel}`}
|
|
224
|
+
className="custom-select d-inline-block mr-1"
|
|
225
|
+
style={{ width: 'auto' }}
|
|
226
|
+
id={`SimpleDateChooser-${name}-month`}
|
|
227
|
+
value={`${month}-${year}`}
|
|
228
|
+
onChange={(e) => {
|
|
229
|
+
const choice = choices[e.target.selectedIndex];
|
|
230
|
+
|
|
231
|
+
// Change day, month, and year
|
|
232
|
+
onChange(
|
|
233
|
+
choice.month,
|
|
234
|
+
choice.days[0],
|
|
235
|
+
choice.year,
|
|
410
236
|
);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
|
|
415
|
-
// Create body
|
|
416
|
-
body = (
|
|
417
|
-
<div
|
|
418
|
-
className="SimpleDateChooser-inner-container d-inline-block"
|
|
419
|
-
aria-label={`date chooser with selected date: ${month}/${day}/${year}`}
|
|
237
|
+
}}
|
|
420
238
|
>
|
|
421
|
-
{
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
<select
|
|
444
|
-
aria-label={`day for ${ariaLabel}`}
|
|
445
|
-
className="custom-select d-inline-block"
|
|
446
|
-
style={{ width: 'auto' }}
|
|
447
|
-
id={`SimpleDateChooser-${name}-day`}
|
|
448
|
-
value={day}
|
|
449
|
-
onChange={(e) => {
|
|
450
|
-
// Only change the day
|
|
451
|
-
onChange(
|
|
452
|
-
month,
|
|
453
|
-
Number.parseInt(e.target.value, 10),
|
|
454
|
-
year,
|
|
455
|
-
);
|
|
456
|
-
}}
|
|
457
|
-
>
|
|
458
|
-
{dayOptions}
|
|
459
|
-
</select>
|
|
460
|
-
</div>
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/* --------- DateOutOfRange --------- */
|
|
465
|
-
|
|
466
|
-
if (view === View.InvalidDate) {
|
|
467
|
-
body = (
|
|
468
|
-
<div className="SimpleDateChooser-inner-container d-inline-block">
|
|
469
|
-
<button
|
|
470
|
-
type="button"
|
|
471
|
-
className="btn btn-light"
|
|
472
|
-
onClick={askToEditInvalidDate}
|
|
473
|
-
aria-label={`edit date for ${ariaLabel}`}
|
|
474
|
-
>
|
|
475
|
-
{getMonthName(month).full}
|
|
476
|
-
{' '}
|
|
477
|
-
{day}
|
|
478
|
-
{getOrdinal(day)}
|
|
479
|
-
,
|
|
480
|
-
{' '}
|
|
481
|
-
{year}
|
|
482
|
-
</button>
|
|
483
|
-
<button
|
|
484
|
-
type="button"
|
|
485
|
-
className="btn btn-secondary"
|
|
486
|
-
onClick={askToEditInvalidDate}
|
|
487
|
-
aria-label={`edit date for ${ariaLabel}`}
|
|
488
|
-
>
|
|
489
|
-
Edit
|
|
490
|
-
</button>
|
|
491
|
-
</div>
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/*----------------------------------------*/
|
|
496
|
-
/* --------------- Main UI -------------- */
|
|
497
|
-
/*----------------------------------------*/
|
|
498
|
-
|
|
499
|
-
return (
|
|
500
|
-
<span className="SimpleDateChooser-outer-container">
|
|
501
|
-
{body}
|
|
502
|
-
</span>
|
|
239
|
+
{monthOptions}
|
|
240
|
+
</select>
|
|
241
|
+
|
|
242
|
+
{/* Day Chooser */}
|
|
243
|
+
<select
|
|
244
|
+
aria-label={`day for ${ariaLabel}`}
|
|
245
|
+
className="custom-select d-inline-block"
|
|
246
|
+
style={{ width: 'auto' }}
|
|
247
|
+
id={`SimpleDateChooser-${name}-day`}
|
|
248
|
+
value={day}
|
|
249
|
+
onChange={(e) => {
|
|
250
|
+
// Only change the day
|
|
251
|
+
onChange(
|
|
252
|
+
month,
|
|
253
|
+
Number.parseInt(e.target.value, 10),
|
|
254
|
+
year,
|
|
255
|
+
);
|
|
256
|
+
}}
|
|
257
|
+
>
|
|
258
|
+
{dayOptions}
|
|
259
|
+
</select>
|
|
260
|
+
</div>
|
|
503
261
|
);
|
|
504
262
|
};
|
|
505
263
|
|