dce-reactkit 3.2.2-beta.34 → 3.2.2-beta.36

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "3.2.2-beta.34",
3
+ "version": "3.2.2-beta.36",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -69,7 +69,7 @@ const ButtonInputGroup: React.FC<Props> = (props) => {
69
69
 
70
70
  {/* Contents */}
71
71
  <span
72
- className="input-group-text flex-grow-1 rounded-right"
72
+ className="input-group-text flex-grow-1 rounded-right d-flex flex-wrap"
73
73
  style={{
74
74
  backgroundColor: 'white',
75
75
  borderTopLeftRadius: 0,
@@ -30,6 +30,7 @@ import Modal from './Modal';
30
30
  import ModalType from '../types/ModalType';
31
31
  import CheckboxButton from './CheckboxButton';
32
32
  import CSVDownloadButton from './CSVDownloadButton';
33
+ import Variant from '../types/Variant';
33
34
 
34
35
  /*------------------------------------------------------------------------*/
35
36
  /* Types */
@@ -86,7 +87,7 @@ enum ActionType {
86
87
  // Toggle sort column param
87
88
  ToggleSortColumn = 'toggle-sort-column',
88
89
  // Toggle the visibility of a column
89
- ToggleColumnVisibility = 'toggle-column-visibility',
90
+ UpdateColumnVisibility = 'update-column-visibility',
90
91
  // Toggle the column visibility customization modal
91
92
  ToggleColVisCusModalVisibility = 'toggle-col-vis-cus-modal-visibility',
92
93
  }
@@ -101,9 +102,11 @@ type Action = (
101
102
  }
102
103
  | {
103
104
  // Action type
104
- type: ActionType.ToggleColumnVisibility,
105
- // Param for the column to toggle
105
+ type: ActionType.UpdateColumnVisibility,
106
+ // Param for the column to update
106
107
  param: string,
108
+ // If true, make the column visible
109
+ visible: boolean,
107
110
  }
108
111
  | {
109
112
  // Action type
@@ -144,9 +147,9 @@ const reducer = (state: State, action: Action): State => {
144
147
  sortType: SortType.Ascending,
145
148
  };
146
149
  }
147
- case ActionType.ToggleColumnVisibility: {
150
+ case ActionType.UpdateColumnVisibility: {
148
151
  const { columnVisibilityMap } = state;
149
- columnVisibilityMap[action.param] = !columnVisibilityMap[action.param];
152
+ columnVisibilityMap[action.param] = action.visible;
150
153
  return {
151
154
  ...state,
152
155
  columnVisibilityMap,
@@ -234,6 +237,7 @@ const IntelliTable: React.FC<Props> = (props) => {
234
237
  type: ActionType.ToggleColVisCusModalVisibility,
235
238
  });
236
239
  }}
240
+ okayVariant={Variant.Light}
237
241
  >
238
242
  {
239
243
  columns.map((column) => {
@@ -241,15 +245,19 @@ const IntelliTable: React.FC<Props> = (props) => {
241
245
  <CheckboxButton
242
246
  key={column.param}
243
247
  id={`IntelliTable-${id}-toggle-visibility-${column.param}`}
248
+ className="mb-2"
244
249
  text={column.title}
245
- onChanged={() => {
250
+ onChanged={(checked) => {
246
251
  dispatch({
247
- type: ActionType.ToggleColumnVisibility,
252
+ type: ActionType.UpdateColumnVisibility,
248
253
  param: column.param,
254
+ visible: checked,
249
255
  });
250
256
  }}
251
257
  checked={columnVisibilityMap[column.param]}
252
258
  ariaLabel={`show "${column.title}" column`}
259
+ checkedVariant={Variant.Light}
260
+ uncheckedVariant={Variant.Secondary}
253
261
  />
254
262
  );
255
263
  })
@@ -307,7 +315,7 @@ const IntelliTable: React.FC<Props> = (props) => {
307
315
  borderLeft: '0.05rem solid #555',
308
316
  }}
309
317
  >
310
- <div className="d-flex align-items-center justify-content-center flex-row h-100">
318
+ <div className="d-flex align-items-center justify-content-start flex-row h-100">
311
319
  {/* Title */}
312
320
  <span className="text-nowrap">
313
321
  {column.title}
@@ -355,6 +363,33 @@ const IntelliTable: React.FC<Props> = (props) => {
355
363
  const aVal = a[sortColumnParam];
356
364
  const bVal = b[sortColumnParam];
357
365
 
366
+ // Tiebreaker sort by timestamp, most recent first (used if tied)
367
+ const tiebreaker = (
368
+ (b.timestamp ?? 0)
369
+ - (a.timestamp ?? 0)
370
+ );
371
+
372
+ // Auto-sort undefined and null to end of list
373
+ if (
374
+ (aVal === undefined || aVal === null)
375
+ || (bVal === undefined || bVal === null)
376
+ ) {
377
+ // At least one was undefined
378
+ if (
379
+ (aVal === undefined || aVal === null)
380
+ && (bVal === undefined || bVal === null)
381
+ ) {
382
+ // Both undefined
383
+ return tiebreaker;
384
+ }
385
+ if (aVal === undefined || aVal === null) {
386
+ // First was undefined
387
+ return 1;
388
+ }
389
+ // Second was undefined
390
+ return -1;
391
+ }
392
+
358
393
  // Sort differently based on the data type
359
394
  // > Boolean
360
395
  if (paramType === ParamType.Boolean) {
@@ -364,7 +399,7 @@ const IntelliTable: React.FC<Props> = (props) => {
364
399
  if (!aVal && bVal) {
365
400
  return (descending ? 1 : -1);
366
401
  }
367
- return 0;
402
+ return tiebreaker;
368
403
  }
369
404
  // > Number
370
405
  if (
@@ -385,7 +420,7 @@ const IntelliTable: React.FC<Props> = (props) => {
385
420
  if (aVal > bVal) {
386
421
  return (descending ? -1 : 1);
387
422
  }
388
- return 0;
423
+ return tiebreaker;
389
424
  }
390
425
  // > JSON
391
426
  if (paramType === ParamType.JSON) {
@@ -407,7 +442,7 @@ const IntelliTable: React.FC<Props> = (props) => {
407
442
  }
408
443
 
409
444
  // No sort
410
- return 0;
445
+ return tiebreaker;
411
446
  });
412
447
  }
413
448
 
@@ -727,7 +727,6 @@ const LogReviewer: React.FC<Props> = (props) => {
727
727
 
728
728
  // Check which year/month combos we need to load
729
729
  const toLoad = listMonthsToLoad(newDateFilterState);
730
- console.log('Filter update:', newDateFilterState, toLoad, logMap);
731
730
 
732
731
  // If nothing to load, finished
733
732
  if (toLoad.length === 0) {
@@ -1067,6 +1066,10 @@ const LogReviewer: React.FC<Props> = (props) => {
1067
1066
  checked={tagFilterState[tag]}
1068
1067
  onChanged={(checked) => {
1069
1068
  tagFilterState[tag] = checked;
1069
+ dispatch({
1070
+ type: ActionType.UpdateTagFilterState,
1071
+ tagFilterState,
1072
+ });
1070
1073
  }}
1071
1074
  />
1072
1075
  );
@@ -1143,6 +1146,7 @@ const LogReviewer: React.FC<Props> = (props) => {
1143
1146
  text={description}
1144
1147
  ariaLabel={`include logs with action type "${description}" in results`}
1145
1148
  noMarginOnRight={i === Object.keys(LogAction).length - 1}
1149
+ checked={actionErrorFilterState.action[action]}
1146
1150
  onChanged={(checked) => {
1147
1151
  actionErrorFilterState.action[action] = checked;
1148
1152
  dispatch({
@@ -1173,6 +1177,7 @@ const LogReviewer: React.FC<Props> = (props) => {
1173
1177
  id={`LogReviewer-target-${target}-checkbox`}
1174
1178
  text={description}
1175
1179
  ariaLabel={`include logs with target "${description}" in results`}
1180
+ checked={actionErrorFilterState.target[target]}
1176
1181
  onChanged={(checked) => {
1177
1182
  actionErrorFilterState.target[target] = checked;
1178
1183
  dispatch({