dce-reactkit 3.4.0-beta.2 → 3.4.0-beta.3

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 CHANGED
@@ -319,7 +319,7 @@ const ModalButtonTypeToLabelAndVariant = {
319
319
  /*------------------------------------------------------------------------*/
320
320
  /* Style */
321
321
  /*------------------------------------------------------------------------*/
322
- const style$9 = `
322
+ const style$8 = `
323
323
  .Modal-backdrop {
324
324
  position: fixed;
325
325
  top: 0;
@@ -493,7 +493,7 @@ const Modal = (props) => {
493
493
  left: 0,
494
494
  right: 0,
495
495
  } },
496
- React__default["default"].createElement("style", null, style$9),
496
+ React__default["default"].createElement("style", null, style$8),
497
497
  React__default["default"].createElement("div", { className: `Modal-backdrop ${backdropAnimationClass}`, style: {
498
498
  zIndex: 5000000003,
499
499
  }, onClick: () => __awaiter$1(void 0, void 0, void 0, function* () {
@@ -589,7 +589,7 @@ const getSendRequest = () => __awaiter$1(void 0, void 0, void 0, function* () {
589
589
  yield initialized;
590
590
  // Error if no send request function
591
591
  if (timedOut) {
592
- showFatalError$1(new ErrorWithCode$1('Could not send a request because the request needed to be sent before dce-reactkit was properly initialized. Perhaps dce-reactkit was not initialized with initClient.', ReactKitErrorCode$3.NoCACCLSendRequestFunction));
592
+ showFatalError(new ErrorWithCode$1('Could not send a request because the request needed to be sent before dce-reactkit was properly initialized. Perhaps dce-reactkit was not initialized with initClient.', ReactKitErrorCode$3.NoCACCLSendRequestFunction));
593
593
  // Return dummy function that never resolves
594
594
  return (() => {
595
595
  return new Promise(() => { });
@@ -628,12 +628,12 @@ const initClient = (opts) => {
628
628
  };
629
629
 
630
630
  // Keep track of whether or not session expiry has already been handled
631
- let sessionAlreadyExpired$1 = false;
631
+ let sessionAlreadyExpired = false;
632
632
  /*------------------------------------------------------------------------*/
633
633
  /* Stub Logic */
634
634
  /*------------------------------------------------------------------------*/
635
635
  // Stored stub responses
636
- const stubResponses$1 = {};
636
+ const stubResponses = {};
637
637
  /**
638
638
  * Add a stub response
639
639
  * @author Gabe Abrams
@@ -651,10 +651,10 @@ const _setStubResponse = (opts) => {
651
651
  const errorMessage = ((_b = opts.errorMessage) !== null && _b !== void 0 ? _b : 'An unknown error has occurred.');
652
652
  const errorCode = ((_c = opts.errorCode) !== null && _c !== void 0 ? _c : ReactKitErrorCode$3.NoCode);
653
653
  // Store to stub responses
654
- if (!stubResponses$1[method]) {
655
- stubResponses$1[method] = {};
654
+ if (!stubResponses[method]) {
655
+ stubResponses[method] = {};
656
656
  }
657
- stubResponses$1[method][path] = ((opts.errorMessage || opts.errorCode)
657
+ stubResponses[method][path] = ((opts.errorMessage || opts.errorCode)
658
658
  ? {
659
659
  success: false,
660
660
  errorMessage,
@@ -677,15 +677,15 @@ const _setStubResponse = (opts) => {
677
677
  * @param [opts.params] - query/body parameters to include
678
678
  * @returns response from server
679
679
  */
680
- const visitServerEndpoint$1 = (opts) => __awaiter$1(void 0, void 0, void 0, function* () {
680
+ const visitServerEndpoint = (opts) => __awaiter$1(void 0, void 0, void 0, function* () {
681
681
  var _a, _b, _c;
682
682
  const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET');
683
683
  // Handle stubs
684
- const stubResponse = (_b = stubResponses$1[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
684
+ const stubResponse = (_b = stubResponses[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
685
685
  if (stubResponse) {
686
686
  // Remove from list
687
687
  try {
688
- stubResponses$1[method][opts.path] = undefined;
688
+ stubResponses[method][opts.path] = undefined;
689
689
  }
690
690
  catch (err) {
691
691
  // Ignore
@@ -712,13 +712,13 @@ const visitServerEndpoint$1 = (opts) => __awaiter$1(void 0, void 0, void 0, func
712
712
  // Session expired
713
713
  if (response.body.code === ReactKitErrorCode$3.SessionExpired) {
714
714
  // Skip notice if session was already expired
715
- if (sessionAlreadyExpired$1) {
715
+ if (sessionAlreadyExpired) {
716
716
  // Never return (browser is already reloading)
717
717
  yield new Promise(() => {
718
718
  // Promise that never returns
719
719
  });
720
720
  }
721
- sessionAlreadyExpired$1 = true;
721
+ sessionAlreadyExpired = true;
722
722
  // Show session expiration message
723
723
  {
724
724
  // Fallback to alert
@@ -747,7 +747,7 @@ const visitServerEndpoint$1 = (opts) => __awaiter$1(void 0, void 0, void 0, func
747
747
  */
748
748
  const logClientEvent = (opts) => __awaiter$1(void 0, void 0, void 0, function* () {
749
749
  var _a, _b, _c, _d, _e, _f, _g;
750
- return visitServerEndpoint$1({
750
+ return visitServerEndpoint({
751
751
  path: LOG_ROUTE_PATH,
752
752
  method: 'POST',
753
753
  params: {
@@ -797,7 +797,7 @@ let onAlertClosed;
797
797
  * @param title the title text to display at the top of the alert
798
798
  * @param text the text to display in the alert
799
799
  */
800
- const alert$2 = (title, text) => __awaiter$1(void 0, void 0, void 0, function* () {
800
+ const alert$1 = (title, text) => __awaiter$1(void 0, void 0, void 0, function* () {
801
801
  // Fallback if alert not available
802
802
  if (!setAlertInfo) {
803
803
  window.alert(`${title}\n\n${text}`);
@@ -869,7 +869,7 @@ let setFatalErrorTitle;
869
869
  * @param error the error to show
870
870
  * @param [errorTitle] title of the error box
871
871
  */
872
- const showFatalError$1 = (error, errorTitle = 'An Error Occurred') => {
872
+ const showFatalError = (error, errorTitle = 'An Error Occurred') => {
873
873
  var _a, _b;
874
874
  // Determine message and code
875
875
  const message = (typeof error === 'string'
@@ -892,7 +892,7 @@ const showFatalError$1 = (error, errorTitle = 'An Error Occurred') => {
892
892
  });
893
893
  // Handle case where app hasn't loaded
894
894
  if (!setFatalErrorMessage || !setFatalErrorCode) {
895
- alert$2(errorTitle, `${message} (code: ${code}). Please contact support.`);
895
+ alert$1(errorTitle, `${message} (code: ${code}). Please contact support.`);
896
896
  return undefined;
897
897
  }
898
898
  // Use setters
@@ -997,7 +997,7 @@ const AppWrapper = (props) => {
997
997
  /*------------------------------------------------------------------------*/
998
998
  /* Style */
999
999
  /*------------------------------------------------------------------------*/
1000
- const style$8 = `
1000
+ const style$7 = `
1001
1001
  /* Container fades in */
1002
1002
  .LoadingSpinner-container {
1003
1003
  animation-name: LoadingSpinner-container-fade-in;
@@ -1069,13 +1069,13 @@ const style$8 = `
1069
1069
  /*------------------------------------------------------------------------*/
1070
1070
  /* Component */
1071
1071
  /*------------------------------------------------------------------------*/
1072
- const LoadingSpinner$1 = () => {
1072
+ const LoadingSpinner = () => {
1073
1073
  /*------------------------------------------------------------------------*/
1074
1074
  /* Render */
1075
1075
  /*------------------------------------------------------------------------*/
1076
1076
  // Add all four blips to a container
1077
1077
  return (React__default["default"].createElement("div", { className: "text-center LoadingSpinner LoadingSpinner-container" },
1078
- React__default["default"].createElement("style", null, style$8),
1078
+ React__default["default"].createElement("style", null, style$7),
1079
1079
  React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-1 me-1" }),
1080
1080
  React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-2 me-1" }),
1081
1081
  React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-3 me-1" }),
@@ -1089,7 +1089,7 @@ const LoadingSpinner$1 = () => {
1089
1089
  /*------------------------------------------------------------------------*/
1090
1090
  /* Style */
1091
1091
  /*------------------------------------------------------------------------*/
1092
- const style$7 = `
1092
+ const style$6 = `
1093
1093
  /* Tab Box */
1094
1094
  .TabBox-box {
1095
1095
  /* Light Border */
@@ -1169,7 +1169,7 @@ const TabBox = (props) => {
1169
1169
  /*----------------------------------------*/
1170
1170
  // Full UI
1171
1171
  return (React__default["default"].createElement("div", { className: `TabBox-container ${noBottomMargin ? '' : 'mb-2'}` },
1172
- React__default["default"].createElement("style", null, style$7),
1172
+ React__default["default"].createElement("style", null, style$6),
1173
1173
  React__default["default"].createElement("div", { className: "TabBox-title-container" },
1174
1174
  React__default["default"].createElement("div", { className: "TabBox-title" }, title)),
1175
1175
  React__default["default"].createElement("div", { className: `TabBox-box ps-2 pt-2 pe-2 ${noBottomPadding ? '' : 'pb-2'}` },
@@ -1183,7 +1183,7 @@ const TabBox = (props) => {
1183
1183
  /*------------------------------------------------------------------------*/
1184
1184
  /* Component */
1185
1185
  /*------------------------------------------------------------------------*/
1186
- const RadioButton$1 = (props) => {
1186
+ const RadioButton = (props) => {
1187
1187
  /*------------------------------------------------------------------------*/
1188
1188
  /* Setup */
1189
1189
  /*------------------------------------------------------------------------*/
@@ -1211,7 +1211,7 @@ const RadioButton$1 = (props) => {
1211
1211
  /*------------------------------------------------------------------------*/
1212
1212
  /* Component */
1213
1213
  /*------------------------------------------------------------------------*/
1214
- const CheckboxButton$1 = (props) => {
1214
+ const CheckboxButton = (props) => {
1215
1215
  /*------------------------------------------------------------------------*/
1216
1216
  /* Setup */
1217
1217
  /*------------------------------------------------------------------------*/
@@ -1248,7 +1248,7 @@ const CheckboxButton$1 = (props) => {
1248
1248
  /*------------------------------------------------------------------------*/
1249
1249
  /* Component */
1250
1250
  /*------------------------------------------------------------------------*/
1251
- const ButtonInputGroup$1 = (props) => {
1251
+ const ButtonInputGroup = (props) => {
1252
1252
  /*------------------------------------------------------------------------*/
1253
1253
  /* Setup */
1254
1254
  /*------------------------------------------------------------------------*/
@@ -1490,7 +1490,7 @@ const SimpleDateChooser = (props) => {
1490
1490
  /*------------------------------------------------------------------------*/
1491
1491
  /* Style */
1492
1492
  /*------------------------------------------------------------------------*/
1493
- const style$6 = `
1493
+ const style$5 = `
1494
1494
  .Drawer-container {
1495
1495
  margin-left: 1rem;
1496
1496
  margin-right: 1rem;
@@ -1524,7 +1524,7 @@ const Drawer = (props) => {
1524
1524
  return (React__default["default"].createElement("div", { className: "Drawer-container", style: {
1525
1525
  backgroundColor: (customBackgroundColor !== null && customBackgroundColor !== void 0 ? customBackgroundColor : undefined),
1526
1526
  } },
1527
- React__default["default"].createElement("style", null, style$6),
1527
+ React__default["default"].createElement("style", null, style$5),
1528
1528
  children));
1529
1529
  };
1530
1530
 
@@ -1862,13 +1862,13 @@ const PopPendingMark = (props) => {
1862
1862
  */
1863
1863
  /* ------------- Actions ------------ */
1864
1864
  // Types of actions
1865
- var ActionType$7;
1865
+ var ActionType$8;
1866
1866
  (function (ActionType) {
1867
1867
  // Indicate that the text was recently copied
1868
1868
  ActionType["IndicateRecentlyCopied"] = "indicate-recently-copied";
1869
1869
  // Clear the status
1870
1870
  ActionType["ClearRecentlyCopiedStatus"] = "clear-recently-copied-status";
1871
- })(ActionType$7 || (ActionType$7 = {}));
1871
+ })(ActionType$8 || (ActionType$8 = {}));
1872
1872
  /**
1873
1873
  * Reducer that executes actions
1874
1874
  * @author Gabe Abrams
@@ -1877,12 +1877,12 @@ var ActionType$7;
1877
1877
  */
1878
1878
  const reducer$6 = (state, action) => {
1879
1879
  switch (action.type) {
1880
- case ActionType$7.IndicateRecentlyCopied: {
1880
+ case ActionType$8.IndicateRecentlyCopied: {
1881
1881
  return {
1882
1882
  recentlyCopied: true,
1883
1883
  };
1884
1884
  }
1885
- case ActionType$7.ClearRecentlyCopiedStatus: {
1885
+ case ActionType$8.ClearRecentlyCopiedStatus: {
1886
1886
  return {
1887
1887
  recentlyCopied: false,
1888
1888
  };
@@ -1924,17 +1924,17 @@ const CopiableBox = (props) => {
1924
1924
  yield navigator.clipboard.writeText(text);
1925
1925
  }
1926
1926
  catch (err) {
1927
- return alert$2('Unable to copy', 'Oops! We couldn\'t copy that to the clipboard. Please copy the text manually.');
1927
+ return alert$1('Unable to copy', 'Oops! We couldn\'t copy that to the clipboard. Please copy the text manually.');
1928
1928
  }
1929
1929
  // Show copied notice
1930
1930
  dispatch({
1931
- type: ActionType$7.IndicateRecentlyCopied,
1931
+ type: ActionType$8.IndicateRecentlyCopied,
1932
1932
  });
1933
1933
  // Wait a moment
1934
1934
  yield waitMs(4000);
1935
1935
  // Hide copied notice
1936
1936
  dispatch({
1937
- type: ActionType$7.ClearRecentlyCopiedStatus,
1937
+ type: ActionType$8.ClearRecentlyCopiedStatus,
1938
1938
  });
1939
1939
  });
1940
1940
  /*------------------------------------------------------------------------*/
@@ -1990,11 +1990,11 @@ const CopiableBox = (props) => {
1990
1990
  */
1991
1991
  /* ------------- Actions ------------ */
1992
1992
  // Types of actions
1993
- var ActionType$6;
1993
+ var ActionType$7;
1994
1994
  (function (ActionType) {
1995
1995
  // Toggle whether a child are being shown
1996
1996
  ActionType["ToggleChild"] = "toggle-child";
1997
- })(ActionType$6 || (ActionType$6 = {}));
1997
+ })(ActionType$7 || (ActionType$7 = {}));
1998
1998
  /**
1999
1999
  * Reducer that executes actions
2000
2000
  * @author Gabe Abrams
@@ -2003,7 +2003,7 @@ var ActionType$6;
2003
2003
  */
2004
2004
  const reducer$5 = (state, action) => {
2005
2005
  switch (action.type) {
2006
- case ActionType$6.ToggleChild: {
2006
+ case ActionType$7.ToggleChild: {
2007
2007
  return Object.assign(Object.assign({}, state), { childExpanded: Object.assign(Object.assign({}, state.childExpanded), { [String(action.id)]: !state.childExpanded[String(action.id)] }) });
2008
2008
  }
2009
2009
  default: {
@@ -2122,12 +2122,12 @@ const NestableItemList = (props) => {
2122
2122
  backgroundColor: 'transparent',
2123
2123
  }, type: "button", onClick: () => {
2124
2124
  dispatch({
2125
- type: ActionType$6.ToggleChild,
2125
+ type: ActionType$7.ToggleChild,
2126
2126
  id: item.id,
2127
2127
  });
2128
2128
  }, "aria-label": `${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${item.name}` },
2129
2129
  React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: childExpanded[item.id] ? freeSolidSvgIcons.faChevronDown : freeSolidSvgIcons.faChevronRight })))),
2130
- React__default["default"].createElement(CheckboxButton$1, { className: `NestableItemList-CheckboxButton-${item.id}`, text: item.name, checked: item.isGroup ? allChecked(item.children) : item.checked, dashed: item.isGroup ? !noneChecked(item.children) : false, onChanged: (checked) => {
2130
+ React__default["default"].createElement(CheckboxButton, { className: `NestableItemList-CheckboxButton-${item.id}`, text: item.name, checked: item.isGroup ? allChecked(item.children) : item.checked, dashed: item.isGroup ? !noneChecked(item.children) : false, onChanged: (checked) => {
2131
2131
  onChanged(changeChecked(item.id, checked, items));
2132
2132
  }, ariaLabel: `Select ${item.name}`, checkedVariant: Variant$3.Light }),
2133
2133
  (item.isGroup && childExpanded[item.id]) && (React__default["default"].createElement("div", { className: "NestableItemList-children-container", style: {
@@ -2397,7 +2397,7 @@ var SortType;
2397
2397
  })(SortType || (SortType = {}));
2398
2398
  /* ------------- Actions ------------ */
2399
2399
  // Types of actions
2400
- var ActionType$5;
2400
+ var ActionType$6;
2401
2401
  (function (ActionType) {
2402
2402
  // Toggle sort column param
2403
2403
  ActionType["ToggleSortColumn"] = "toggle-sort-column";
@@ -2409,7 +2409,7 @@ var ActionType$5;
2409
2409
  ActionType["ShowAllColumns"] = "show-all-columns";
2410
2410
  // Hide all columns
2411
2411
  ActionType["HideAllColumns"] = "hide-all-columns";
2412
- })(ActionType$5 || (ActionType$5 = {}));
2412
+ })(ActionType$6 || (ActionType$6 = {}));
2413
2413
  /**
2414
2414
  * Reducer that executes actions
2415
2415
  * @author Gabe Abrams
@@ -2418,7 +2418,7 @@ var ActionType$5;
2418
2418
  */
2419
2419
  const reducer$4 = (state, action) => {
2420
2420
  switch (action.type) {
2421
- case ActionType$5.ToggleSortColumn: {
2421
+ case ActionType$6.ToggleSortColumn: {
2422
2422
  if (action.param !== state.sortColumnParam) {
2423
2423
  // Different column param
2424
2424
  return Object.assign(Object.assign({}, state), { sortColumnParam: action.param, sortType: SortType.Ascending });
@@ -2430,22 +2430,22 @@ const reducer$4 = (state, action) => {
2430
2430
  // Stop sorting by column
2431
2431
  return Object.assign(Object.assign({}, state), { sortColumnParam: undefined, sortType: SortType.Ascending });
2432
2432
  }
2433
- case ActionType$5.UpdateColumnVisibility: {
2433
+ case ActionType$6.UpdateColumnVisibility: {
2434
2434
  const { columnVisibilityMap } = state;
2435
2435
  columnVisibilityMap[action.param] = action.visible;
2436
2436
  return Object.assign(Object.assign({}, state), { columnVisibilityMap });
2437
2437
  }
2438
- case ActionType$5.ToggleColVisCusModalVisibility: {
2438
+ case ActionType$6.ToggleColVisCusModalVisibility: {
2439
2439
  return Object.assign(Object.assign({}, state), { columnVisibilityCustomizationModalVisible: !state.columnVisibilityCustomizationModalVisible });
2440
2440
  }
2441
- case ActionType$5.ShowAllColumns: {
2441
+ case ActionType$6.ShowAllColumns: {
2442
2442
  const { columnVisibilityMap } = state;
2443
2443
  Object.keys(columnVisibilityMap).forEach((param) => {
2444
2444
  columnVisibilityMap[param] = true;
2445
2445
  });
2446
2446
  return Object.assign(Object.assign({}, state), { columnVisibilityMap });
2447
2447
  }
2448
- case ActionType$5.HideAllColumns: {
2448
+ case ActionType$6.HideAllColumns: {
2449
2449
  const { columnVisibilityMap } = state;
2450
2450
  Object.keys(columnVisibilityMap).forEach((param) => {
2451
2451
  columnVisibilityMap[param] = false;
@@ -2512,16 +2512,16 @@ const IntelliTable = (props) => {
2512
2512
  return !isSelected;
2513
2513
  }));
2514
2514
  if (noColumnsSelected) {
2515
- return alert$2('Choose at least one column', 'To continue, you have to choose at least one column to show');
2515
+ return alert$1('Choose at least one column', 'To continue, you have to choose at least one column to show');
2516
2516
  }
2517
2517
  dispatch({
2518
- type: ActionType$5.ToggleColVisCusModalVisibility,
2518
+ type: ActionType$6.ToggleColVisCusModalVisibility,
2519
2519
  });
2520
2520
  }, okayVariant: Variant$3.Light },
2521
2521
  columns.map((column) => {
2522
- return (React__default["default"].createElement(CheckboxButton$1, { key: column.param, id: `IntelliTable-${id}-toggle-visibility-${column.param}`, className: "mb-2", text: column.title, onChanged: (checked) => {
2522
+ return (React__default["default"].createElement(CheckboxButton, { key: column.param, id: `IntelliTable-${id}-toggle-visibility-${column.param}`, className: "mb-2", text: column.title, onChanged: (checked) => {
2523
2523
  dispatch({
2524
- type: ActionType$5.UpdateColumnVisibility,
2524
+ type: ActionType$6.UpdateColumnVisibility,
2525
2525
  param: column.param,
2526
2526
  visible: checked,
2527
2527
  });
@@ -2530,12 +2530,12 @@ const IntelliTable = (props) => {
2530
2530
  React__default["default"].createElement("div", { className: "mt-3" }, "Or you can:"),
2531
2531
  React__default["default"].createElement("button", { type: "button", id: `IntelliTable-${id}-select-all-columns`, className: "btn btn-secondary me-2", "aria-label": `show all columns in the ${title} table`, onClick: () => {
2532
2532
  dispatch({
2533
- type: ActionType$5.ShowAllColumns,
2533
+ type: ActionType$6.ShowAllColumns,
2534
2534
  });
2535
2535
  } }, "Select All"),
2536
2536
  React__default["default"].createElement("button", { type: "button", id: `IntelliTable-${id}-select-none-columns`, className: "btn btn-secondary", "aria-label": `hide all columns in the ${title} table`, onClick: () => {
2537
2537
  dispatch({
2538
- type: ActionType$5.HideAllColumns,
2538
+ type: ActionType$6.HideAllColumns,
2539
2539
  });
2540
2540
  } }, "Deselect All")));
2541
2541
  }
@@ -2586,7 +2586,7 @@ const IntelliTable = (props) => {
2586
2586
  React__default["default"].createElement("div", null,
2587
2587
  React__default["default"].createElement("button", { type: "button", id: `IntelliTable-${id}-sort-by-${column.param}-button`, className: `btn btn-${sortingByThisColumn ? 'light' : 'secondary'} btn-sm ms-1 ps-1 pe-1 pt-0 pb-0`, "aria-label": sortButtonAriaLabel, onClick: () => {
2588
2588
  dispatch({
2589
- type: ActionType$5.ToggleSortColumn,
2589
+ type: ActionType$6.ToggleSortColumn,
2590
2590
  param: column.param,
2591
2591
  });
2592
2592
  } },
@@ -2775,7 +2775,7 @@ const IntelliTable = (props) => {
2775
2775
  React__default["default"].createElement(CSVDownloadButton, { "aria-label": `download data as csv for ${title}`, id: `IntelliTable-${id}-download-as-csv`, filename: filename, csv: csv }),
2776
2776
  React__default["default"].createElement("button", { type: "button", className: "btn btn-secondary ms-2", "aria-label": `show panel for customizing which columns show in table ${title}`, id: `IntelliTable-${id}-show-column-customization-modal`, onClick: () => {
2777
2777
  dispatch({
2778
- type: ActionType$5.ToggleColVisCusModalVisibility,
2778
+ type: ActionType$6.ToggleColVisCusModalVisibility,
2779
2779
  });
2780
2780
  } },
2781
2781
  "Show/Hide Cols",
@@ -3141,7 +3141,7 @@ const genHumanReadableName = (machineReadableName) => {
3141
3141
  };
3142
3142
  /* ------------- Actions ------------ */
3143
3143
  // Types of actions
3144
- var ActionType$4;
3144
+ var ActionType$5;
3145
3145
  (function (ActionType) {
3146
3146
  // Show the loading bar
3147
3147
  ActionType["StartLoading"] = "start-loading";
@@ -3163,7 +3163,7 @@ var ActionType$4;
3163
3163
  ActionType["UpdateActionErrorFilterState"] = "update-action-error-filter-state";
3164
3164
  // Update the advanced filter state
3165
3165
  ActionType["UpdateAdvancedFilterState"] = "update-advanced-filter-state";
3166
- })(ActionType$4 || (ActionType$4 = {}));
3166
+ })(ActionType$5 || (ActionType$5 = {}));
3167
3167
  /**
3168
3168
  * Reducer that executes actions
3169
3169
  * @author Gabe Abrams
@@ -3172,36 +3172,36 @@ var ActionType$4;
3172
3172
  */
3173
3173
  const reducer$3 = (state, action) => {
3174
3174
  switch (action.type) {
3175
- case ActionType$4.StartLoading: {
3175
+ case ActionType$5.StartLoading: {
3176
3176
  return Object.assign(Object.assign({}, state), { loading: true });
3177
3177
  }
3178
- case ActionType$4.FinishLoading: {
3178
+ case ActionType$5.FinishLoading: {
3179
3179
  return Object.assign(Object.assign({}, state), { loading: false, logMap: action.logMap });
3180
3180
  }
3181
- case ActionType$4.ToggleFilterDrawer: {
3181
+ case ActionType$5.ToggleFilterDrawer: {
3182
3182
  return Object.assign(Object.assign({}, state), { expandedFilterDrawer: (state.expandedFilterDrawer === action.filterDrawer
3183
3183
  ? undefined // hide
3184
3184
  : action.filterDrawer) });
3185
3185
  }
3186
- case ActionType$4.HideFilterDrawer: {
3186
+ case ActionType$5.HideFilterDrawer: {
3187
3187
  return Object.assign(Object.assign({}, state), { expandedFilterDrawer: undefined });
3188
3188
  }
3189
- case ActionType$4.ResetFilters: {
3189
+ case ActionType$5.ResetFilters: {
3190
3190
  return Object.assign(Object.assign({}, state), { dateFilterState: action.initDateFilterState, contextFilterState: action.initContextFilterState, tagFilterState: action.initTagFilterState, actionErrorFilterState: action.initActionErrorFilterState, advancedFilterState: action.initAdvancedFilterState });
3191
3191
  }
3192
- case ActionType$4.UpdateDateFilterState: {
3192
+ case ActionType$5.UpdateDateFilterState: {
3193
3193
  return Object.assign(Object.assign({}, state), { dateFilterState: action.dateFilterState });
3194
3194
  }
3195
- case ActionType$4.UpdateContextFilterState: {
3195
+ case ActionType$5.UpdateContextFilterState: {
3196
3196
  return Object.assign(Object.assign({}, state), { contextFilterState: action.contextFilterState });
3197
3197
  }
3198
- case ActionType$4.UpdateTagFilterState: {
3198
+ case ActionType$5.UpdateTagFilterState: {
3199
3199
  return Object.assign(Object.assign({}, state), { tagFilterState: action.tagFilterState });
3200
3200
  }
3201
- case ActionType$4.UpdateActionErrorFilterState: {
3201
+ case ActionType$5.UpdateActionErrorFilterState: {
3202
3202
  return Object.assign(Object.assign({}, state), { actionErrorFilterState: action.actionErrorFilterState });
3203
3203
  }
3204
- case ActionType$4.UpdateAdvancedFilterState: {
3204
+ case ActionType$5.UpdateAdvancedFilterState: {
3205
3205
  return Object.assign(Object.assign({}, state), { advancedFilterState: action.advancedFilterState });
3206
3206
  }
3207
3207
  default: {
@@ -3381,7 +3381,7 @@ const LogReviewer = (props) => {
3381
3381
  const handleDateRangeUpdated = (newDateFilterState) => __awaiter$1(void 0, void 0, void 0, function* () {
3382
3382
  // Update state
3383
3383
  dispatch({
3384
- type: ActionType$4.UpdateDateFilterState,
3384
+ type: ActionType$5.UpdateDateFilterState,
3385
3385
  dateFilterState: newDateFilterState,
3386
3386
  });
3387
3387
  // Check which year/month combos we need to load
@@ -3392,7 +3392,7 @@ const LogReviewer = (props) => {
3392
3392
  }
3393
3393
  // Start loading
3394
3394
  dispatch({
3395
- type: ActionType$4.StartLoading,
3395
+ type: ActionType$5.StartLoading,
3396
3396
  });
3397
3397
  // Load required months
3398
3398
  try {
@@ -3400,7 +3400,7 @@ const LogReviewer = (props) => {
3400
3400
  // Destructure
3401
3401
  const { year, month } = toLoad[i];
3402
3402
  // Load
3403
- const logs = yield visitServerEndpoint$1({
3403
+ const logs = yield visitServerEndpoint({
3404
3404
  path: `${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/${year}/months/${month}`,
3405
3405
  method: 'GET',
3406
3406
  });
@@ -3412,11 +3412,11 @@ const LogReviewer = (props) => {
3412
3412
  }
3413
3413
  }
3414
3414
  catch (err) {
3415
- return showFatalError$1(err);
3415
+ return showFatalError(err);
3416
3416
  }
3417
3417
  // Finish loading
3418
3418
  dispatch({
3419
- type: ActionType$4.FinishLoading,
3419
+ type: ActionType$5.FinishLoading,
3420
3420
  logMap,
3421
3421
  });
3422
3422
  });
@@ -3442,7 +3442,7 @@ const LogReviewer = (props) => {
3442
3442
  /* ------------- Loading ------------ */
3443
3443
  if (loading) {
3444
3444
  body = (React__default["default"].createElement("div", { className: "text-center p-5" },
3445
- React__default["default"].createElement(LoadingSpinner$1, null)));
3445
+ React__default["default"].createElement(LoadingSpinner, null)));
3446
3446
  }
3447
3447
  /* ------------ Review UI ----------- */
3448
3448
  if (!loading) {
@@ -3455,7 +3455,7 @@ const LogReviewer = (props) => {
3455
3455
  React__default["default"].createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
3456
3456
  React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-date-filter-drawer", className: `btn btn-${FilterDrawer.Date === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle date filter drawer", onClick: () => {
3457
3457
  dispatch({
3458
- type: ActionType$4.ToggleFilterDrawer,
3458
+ type: ActionType$5.ToggleFilterDrawer,
3459
3459
  filterDrawer: FilterDrawer.Date,
3460
3460
  });
3461
3461
  } },
@@ -3463,7 +3463,7 @@ const LogReviewer = (props) => {
3463
3463
  "Date"),
3464
3464
  React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-context-filter-drawer", className: `btn btn-${FilterDrawer.Context === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle context filter drawer", onClick: () => {
3465
3465
  dispatch({
3466
- type: ActionType$4.ToggleFilterDrawer,
3466
+ type: ActionType$5.ToggleFilterDrawer,
3467
3467
  filterDrawer: FilterDrawer.Context,
3468
3468
  });
3469
3469
  } },
@@ -3471,7 +3471,7 @@ const LogReviewer = (props) => {
3471
3471
  "Context"),
3472
3472
  (LogMetadata.Tag && Object.keys(LogMetadata.Tag).length > 0) && (React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-tag-filter-drawer", className: `btn btn-${FilterDrawer.Tag === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle tag filter drawer", onClick: () => {
3473
3473
  dispatch({
3474
- type: ActionType$4.ToggleFilterDrawer,
3474
+ type: ActionType$5.ToggleFilterDrawer,
3475
3475
  filterDrawer: FilterDrawer.Tag,
3476
3476
  });
3477
3477
  } },
@@ -3479,7 +3479,7 @@ const LogReviewer = (props) => {
3479
3479
  "Tag")),
3480
3480
  React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-action-filter-drawer", className: `btn btn-${FilterDrawer.Action === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle action and error filter drawer", onClick: () => {
3481
3481
  dispatch({
3482
- type: ActionType$4.ToggleFilterDrawer,
3482
+ type: ActionType$5.ToggleFilterDrawer,
3483
3483
  filterDrawer: FilterDrawer.Action,
3484
3484
  });
3485
3485
  } },
@@ -3487,7 +3487,7 @@ const LogReviewer = (props) => {
3487
3487
  "Action"),
3488
3488
  React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-advanced-filter-drawer", className: `btn btn-${FilterDrawer.Advanced === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle advanced filter drawer", onClick: () => {
3489
3489
  dispatch({
3490
- type: ActionType$4.ToggleFilterDrawer,
3490
+ type: ActionType$5.ToggleFilterDrawer,
3491
3491
  filterDrawer: FilterDrawer.Advanced,
3492
3492
  });
3493
3493
  } },
@@ -3495,7 +3495,7 @@ const LogReviewer = (props) => {
3495
3495
  "Advanced"),
3496
3496
  React__default["default"].createElement("button", { type: "button", id: "LogReviewer-reset-filters-button", className: "btn btn-light", "aria-label": "reset filters", onClick: () => {
3497
3497
  dispatch({
3498
- type: ActionType$4.ResetFilters,
3498
+ type: ActionType$5.ResetFilters,
3499
3499
  initActionErrorFilterState,
3500
3500
  initAdvancedFilterState,
3501
3501
  initContextFilterState,
@@ -3525,7 +3525,7 @@ const LogReviewer = (props) => {
3525
3525
  || (year === dateFilterState.startDate.year
3526
3526
  && month === dateFilterState.startDate.month
3527
3527
  && day < dateFilterState.startDate.day)) {
3528
- return alert$2('Invalid Start Date', 'The start date cannot be before the end date.');
3528
+ return alert$1('Invalid Start Date', 'The start date cannot be before the end date.');
3529
3529
  }
3530
3530
  dateFilterState.endDate = { month, day, year };
3531
3531
  handleDateRangeUpdated(dateFilterState);
@@ -3617,7 +3617,7 @@ const LogReviewer = (props) => {
3617
3617
  }
3618
3618
  });
3619
3619
  dispatch({
3620
- type: ActionType$4.UpdateContextFilterState,
3620
+ type: ActionType$5.UpdateContextFilterState,
3621
3621
  contextFilterState,
3622
3622
  });
3623
3623
  } }));
@@ -3629,10 +3629,10 @@ const LogReviewer = (props) => {
3629
3629
  React__default["default"].createElement("div", { className: "d-flex gap-1 flex-wrap" }, Object.keys((_d = LogMetadata.Tag) !== null && _d !== void 0 ? _d : {})
3630
3630
  .map((tag) => {
3631
3631
  const description = genHumanReadableName(tag);
3632
- return (React__default["default"].createElement(CheckboxButton$1, { key: tag, id: `LogReviewer-tag-${tag}-checkbox`, text: description, ariaLabel: `require that logs be tagged with "${description}" or any other selected tag`, checked: tagFilterState[tag], onChanged: (checked) => {
3632
+ return (React__default["default"].createElement(CheckboxButton, { key: tag, id: `LogReviewer-tag-${tag}-checkbox`, text: description, ariaLabel: `require that logs be tagged with "${description}" or any other selected tag`, checked: tagFilterState[tag], onChanged: (checked) => {
3633
3633
  tagFilterState[tag] = checked;
3634
3634
  dispatch({
3635
- type: ActionType$4.UpdateTagFilterState,
3635
+ type: ActionType$5.UpdateTagFilterState,
3636
3636
  tagFilterState,
3637
3637
  });
3638
3638
  } }));
@@ -3642,47 +3642,47 @@ const LogReviewer = (props) => {
3642
3642
  // Create filter UI
3643
3643
  filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
3644
3644
  React__default["default"].createElement(TabBox, { title: "Log Type" },
3645
- React__default["default"].createElement(RadioButton$1, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
3645
+ React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
3646
3646
  actionErrorFilterState.type = undefined;
3647
3647
  dispatch({
3648
- type: ActionType$4.UpdateActionErrorFilterState,
3648
+ type: ActionType$5.UpdateActionErrorFilterState,
3649
3649
  actionErrorFilterState,
3650
3650
  });
3651
3651
  }, ariaLabel: "show logs of all types", selected: actionErrorFilterState.type === undefined }),
3652
- React__default["default"].createElement(RadioButton$1, { id: "LogReviewer-type-action-only", text: "Action Logs Only", onSelected: () => {
3652
+ React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-action-only", text: "Action Logs Only", onSelected: () => {
3653
3653
  actionErrorFilterState.type = LogType$1.Action;
3654
3654
  dispatch({
3655
- type: ActionType$4.UpdateActionErrorFilterState,
3655
+ type: ActionType$5.UpdateActionErrorFilterState,
3656
3656
  actionErrorFilterState,
3657
3657
  });
3658
3658
  }, ariaLabel: "only show action logs", selected: actionErrorFilterState.type === LogType$1.Action }),
3659
- React__default["default"].createElement(RadioButton$1, { id: "LogReviewer-type-error-only", text: "Action Error Only", onSelected: () => {
3659
+ React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-error-only", text: "Action Error Only", onSelected: () => {
3660
3660
  actionErrorFilterState.type = LogType$1.Error;
3661
3661
  dispatch({
3662
- type: ActionType$4.UpdateActionErrorFilterState,
3662
+ type: ActionType$5.UpdateActionErrorFilterState,
3663
3663
  actionErrorFilterState,
3664
3664
  });
3665
3665
  }, ariaLabel: "only show error logs", selected: actionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true })),
3666
3666
  (actionErrorFilterState.type === undefined
3667
3667
  || actionErrorFilterState.type === LogType$1.Action) && (React__default["default"].createElement(TabBox, { title: "Action Log Details" },
3668
- React__default["default"].createElement(ButtonInputGroup$1, { label: "Action", className: "mb-2", wrapButtonsAndAddGaps: true }, Object.keys(LogAction$1)
3668
+ React__default["default"].createElement(ButtonInputGroup, { label: "Action", className: "mb-2", wrapButtonsAndAddGaps: true }, Object.keys(LogAction$1)
3669
3669
  .map((action) => {
3670
3670
  const description = genHumanReadableName(action);
3671
- return (React__default["default"].createElement(CheckboxButton$1, { key: action, id: `LogReviewer-action-${action}-checkbox`, text: description, ariaLabel: `include logs with action type "${description}" in results`, noMarginOnRight: true, checked: actionErrorFilterState.action[action], onChanged: (checked) => {
3671
+ return (React__default["default"].createElement(CheckboxButton, { key: action, id: `LogReviewer-action-${action}-checkbox`, text: description, ariaLabel: `include logs with action type "${description}" in results`, noMarginOnRight: true, checked: actionErrorFilterState.action[action], onChanged: (checked) => {
3672
3672
  actionErrorFilterState.action[action] = checked;
3673
3673
  dispatch({
3674
- type: ActionType$4.UpdateActionErrorFilterState,
3674
+ type: ActionType$5.UpdateActionErrorFilterState,
3675
3675
  actionErrorFilterState,
3676
3676
  });
3677
3677
  } }));
3678
3678
  })),
3679
- React__default["default"].createElement(ButtonInputGroup$1, { label: "Target", wrapButtonsAndAddGaps: true }, Object.keys(targetMap)
3679
+ React__default["default"].createElement(ButtonInputGroup, { label: "Target", wrapButtonsAndAddGaps: true }, Object.keys(targetMap)
3680
3680
  .map((target) => {
3681
3681
  const description = genHumanReadableName(target);
3682
- return (React__default["default"].createElement(CheckboxButton$1, { key: target, id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, checked: actionErrorFilterState.target[target], noMarginOnRight: true, onChanged: (checked) => {
3682
+ return (React__default["default"].createElement(CheckboxButton, { key: target, id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, checked: actionErrorFilterState.target[target], noMarginOnRight: true, onChanged: (checked) => {
3683
3683
  actionErrorFilterState.target[target] = checked;
3684
3684
  dispatch({
3685
- type: ActionType$4.UpdateActionErrorFilterState,
3685
+ type: ActionType$5.UpdateActionErrorFilterState,
3686
3686
  actionErrorFilterState,
3687
3687
  });
3688
3688
  } }));
@@ -3694,7 +3694,7 @@ const LogReviewer = (props) => {
3694
3694
  React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error message", value: actionErrorFilterState.errorMessage, placeholder: "e.g. undefined is not a function", onChange: (e) => {
3695
3695
  actionErrorFilterState.errorMessage = e.target.value;
3696
3696
  dispatch({
3697
- type: ActionType$4.UpdateActionErrorFilterState,
3697
+ type: ActionType$5.UpdateActionErrorFilterState,
3698
3698
  actionErrorFilterState,
3699
3699
  });
3700
3700
  } })),
@@ -3705,7 +3705,7 @@ const LogReviewer = (props) => {
3705
3705
  .trim()
3706
3706
  .toUpperCase());
3707
3707
  dispatch({
3708
- type: ActionType$4.UpdateActionErrorFilterState,
3708
+ type: ActionType$5.UpdateActionErrorFilterState,
3709
3709
  actionErrorFilterState,
3710
3710
  });
3711
3711
  } }))))));
@@ -3719,7 +3719,7 @@ const LogReviewer = (props) => {
3719
3719
  React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user first name", value: advancedFilterState.userFirstName, placeholder: "e.g. Divardo", onChange: (e) => {
3720
3720
  advancedFilterState.userFirstName = e.target.value;
3721
3721
  dispatch({
3722
- type: ActionType$4.UpdateAdvancedFilterState,
3722
+ type: ActionType$5.UpdateAdvancedFilterState,
3723
3723
  advancedFilterState,
3724
3724
  });
3725
3725
  } })),
@@ -3728,7 +3728,7 @@ const LogReviewer = (props) => {
3728
3728
  React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user last name", value: advancedFilterState.userLastName, placeholder: "e.g. Calicci", onChange: (e) => {
3729
3729
  advancedFilterState.userLastName = e.target.value;
3730
3730
  dispatch({
3731
- type: ActionType$4.UpdateAdvancedFilterState,
3731
+ type: ActionType$5.UpdateAdvancedFilterState,
3732
3732
  advancedFilterState,
3733
3733
  });
3734
3734
  } })),
@@ -3738,7 +3738,7 @@ const LogReviewer = (props) => {
3738
3738
  advancedFilterState.userEmail = ((e.target.value)
3739
3739
  .trim());
3740
3740
  dispatch({
3741
- type: ActionType$4.UpdateAdvancedFilterState,
3741
+ type: ActionType$5.UpdateAdvancedFilterState,
3742
3742
  advancedFilterState,
3743
3743
  });
3744
3744
  } })),
@@ -3752,29 +3752,29 @@ const LogReviewer = (props) => {
3752
3752
  .trim());
3753
3753
  }
3754
3754
  dispatch({
3755
- type: ActionType$4.UpdateAdvancedFilterState,
3755
+ type: ActionType$5.UpdateAdvancedFilterState,
3756
3756
  advancedFilterState,
3757
3757
  });
3758
3758
  } })),
3759
- React__default["default"].createElement(ButtonInputGroup$1, { label: "Role" },
3760
- React__default["default"].createElement(CheckboxButton$1, { text: "Students", onChanged: (checked) => {
3759
+ React__default["default"].createElement(ButtonInputGroup, { label: "Role" },
3760
+ React__default["default"].createElement(CheckboxButton, { text: "Students", onChanged: (checked) => {
3761
3761
  advancedFilterState.includeLearners = checked;
3762
3762
  dispatch({
3763
- type: ActionType$4.UpdateAdvancedFilterState,
3763
+ type: ActionType$5.UpdateAdvancedFilterState,
3764
3764
  advancedFilterState,
3765
3765
  });
3766
3766
  }, checked: advancedFilterState.includeLearners, ariaLabel: "show logs from students" }),
3767
- React__default["default"].createElement(CheckboxButton$1, { text: "Teaching Team Members", onChanged: (checked) => {
3767
+ React__default["default"].createElement(CheckboxButton, { text: "Teaching Team Members", onChanged: (checked) => {
3768
3768
  advancedFilterState.includeTTMs = checked;
3769
3769
  dispatch({
3770
- type: ActionType$4.UpdateAdvancedFilterState,
3770
+ type: ActionType$5.UpdateAdvancedFilterState,
3771
3771
  advancedFilterState,
3772
3772
  });
3773
3773
  }, checked: advancedFilterState.includeTTMs, ariaLabel: "show logs from teaching team members" }),
3774
- React__default["default"].createElement(CheckboxButton$1, { text: "Admins", onChanged: (checked) => {
3774
+ React__default["default"].createElement(CheckboxButton, { text: "Admins", onChanged: (checked) => {
3775
3775
  advancedFilterState.includeAdmins = checked;
3776
3776
  dispatch({
3777
- type: ActionType$4.UpdateAdvancedFilterState,
3777
+ type: ActionType$5.UpdateAdvancedFilterState,
3778
3778
  advancedFilterState,
3779
3779
  });
3780
3780
  }, checked: advancedFilterState.includeAdmins, ariaLabel: "show logs from admins" }))),
@@ -3784,7 +3784,7 @@ const LogReviewer = (props) => {
3784
3784
  React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course name", value: advancedFilterState.courseName, placeholder: "e.g. GLC 200", onChange: (e) => {
3785
3785
  advancedFilterState.courseName = e.target.value;
3786
3786
  dispatch({
3787
- type: ActionType$4.UpdateAdvancedFilterState,
3787
+ type: ActionType$5.UpdateAdvancedFilterState,
3788
3788
  advancedFilterState,
3789
3789
  });
3790
3790
  } })),
@@ -3798,53 +3798,53 @@ const LogReviewer = (props) => {
3798
3798
  .trim());
3799
3799
  }
3800
3800
  dispatch({
3801
- type: ActionType$4.UpdateAdvancedFilterState,
3801
+ type: ActionType$5.UpdateAdvancedFilterState,
3802
3802
  advancedFilterState,
3803
3803
  });
3804
3804
  } }))),
3805
3805
  React__default["default"].createElement(TabBox, { title: "Device" },
3806
- React__default["default"].createElement(ButtonInputGroup$1, { label: "Device Type" },
3807
- React__default["default"].createElement(RadioButton$1, { text: "All Devices", ariaLabel: "show logs from all devices", selected: advancedFilterState.isMobile === undefined, onSelected: () => {
3806
+ React__default["default"].createElement(ButtonInputGroup, { label: "Device Type" },
3807
+ React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected: advancedFilterState.isMobile === undefined, onSelected: () => {
3808
3808
  advancedFilterState.isMobile = undefined;
3809
3809
  dispatch({
3810
- type: ActionType$4.UpdateAdvancedFilterState,
3810
+ type: ActionType$5.UpdateAdvancedFilterState,
3811
3811
  advancedFilterState,
3812
3812
  });
3813
3813
  } }),
3814
- React__default["default"].createElement(RadioButton$1, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: advancedFilterState.isMobile === true, onSelected: () => {
3814
+ React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: advancedFilterState.isMobile === true, onSelected: () => {
3815
3815
  advancedFilterState.isMobile = true;
3816
3816
  dispatch({
3817
- type: ActionType$4.UpdateAdvancedFilterState,
3817
+ type: ActionType$5.UpdateAdvancedFilterState,
3818
3818
  advancedFilterState,
3819
3819
  });
3820
3820
  } }),
3821
- React__default["default"].createElement(RadioButton$1, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: advancedFilterState.isMobile === false, onSelected: () => {
3821
+ React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: advancedFilterState.isMobile === false, onSelected: () => {
3822
3822
  advancedFilterState.isMobile = false;
3823
3823
  dispatch({
3824
- type: ActionType$4.UpdateAdvancedFilterState,
3824
+ type: ActionType$5.UpdateAdvancedFilterState,
3825
3825
  advancedFilterState,
3826
3826
  });
3827
3827
  }, noMarginOnRight: true }))),
3828
3828
  React__default["default"].createElement(TabBox, { title: "Source" },
3829
- React__default["default"].createElement(ButtonInputGroup$1, { label: "Source Type" },
3830
- React__default["default"].createElement(RadioButton$1, { text: "Both", ariaLabel: "show logs from all sources", selected: advancedFilterState.source === undefined, onSelected: () => {
3829
+ React__default["default"].createElement(ButtonInputGroup, { label: "Source Type" },
3830
+ React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected: advancedFilterState.source === undefined, onSelected: () => {
3831
3831
  advancedFilterState.source = undefined;
3832
3832
  dispatch({
3833
- type: ActionType$4.UpdateAdvancedFilterState,
3833
+ type: ActionType$5.UpdateAdvancedFilterState,
3834
3834
  advancedFilterState,
3835
3835
  });
3836
3836
  } }),
3837
- React__default["default"].createElement(RadioButton$1, { text: "Client Only", ariaLabel: "show logs from client source", selected: advancedFilterState.source === LogSource$1.Client, onSelected: () => {
3837
+ React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected: advancedFilterState.source === LogSource$1.Client, onSelected: () => {
3838
3838
  advancedFilterState.source = LogSource$1.Client;
3839
3839
  dispatch({
3840
- type: ActionType$4.UpdateAdvancedFilterState,
3840
+ type: ActionType$5.UpdateAdvancedFilterState,
3841
3841
  advancedFilterState,
3842
3842
  });
3843
3843
  } }),
3844
- React__default["default"].createElement(RadioButton$1, { text: "Server Only", ariaLabel: "show logs from server source", selected: advancedFilterState.source === LogSource$1.Server, onSelected: () => {
3844
+ React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected: advancedFilterState.source === LogSource$1.Server, onSelected: () => {
3845
3845
  advancedFilterState.source = LogSource$1.Server;
3846
3846
  dispatch({
3847
- type: ActionType$4.UpdateAdvancedFilterState,
3847
+ type: ActionType$5.UpdateAdvancedFilterState,
3848
3848
  advancedFilterState,
3849
3849
  });
3850
3850
  }, noMarginOnRight: true })),
@@ -3855,7 +3855,7 @@ const LogReviewer = (props) => {
3855
3855
  advancedFilterState.courseName = ((e.target.value)
3856
3856
  .trim());
3857
3857
  dispatch({
3858
- type: ActionType$4.UpdateAdvancedFilterState,
3858
+ type: ActionType$5.UpdateAdvancedFilterState,
3859
3859
  advancedFilterState,
3860
3860
  });
3861
3861
  } })),
@@ -3865,7 +3865,7 @@ const LogReviewer = (props) => {
3865
3865
  advancedFilterState.courseName = ((e.target.value)
3866
3866
  .trim());
3867
3867
  dispatch({
3868
- type: ActionType$4.UpdateAdvancedFilterState,
3868
+ type: ActionType$5.UpdateAdvancedFilterState,
3869
3869
  advancedFilterState,
3870
3870
  });
3871
3871
  } })))))));
@@ -4155,1427 +4155,464 @@ const LogReviewer = (props) => {
4155
4155
  React__default["default"].createElement("div", { className: "LogReviewer-contents" }, body))));
4156
4156
  };
4157
4157
 
4158
- /******************************************************************************
4159
- Copyright (c) Microsoft Corporation.
4160
-
4161
- Permission to use, copy, modify, and/or distribute this software for any
4162
- purpose with or without fee is hereby granted.
4163
-
4164
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
4165
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
4166
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
4167
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
4168
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
4169
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
4170
- PERFORMANCE OF THIS SOFTWARE.
4171
- ***************************************************************************** */
4172
-
4173
- function __awaiter(thisArg, _arguments, P, generator) {
4174
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4175
- return new (P || (P = Promise))(function (resolve, reject) {
4176
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
4177
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
4178
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
4179
- step((generator = generator.apply(thisArg, _arguments || [])).next());
4180
- });
4181
- }
4182
-
4183
- // Highest error code = DRK10
4184
4158
  /**
4185
- * List of error codes built into the react kit
4186
- * @author Gabe Abrams
4159
+ * Options for field types
4160
+ * @author Yuen Ler Chow
4187
4161
  */
4188
- var ReactKitErrorCode;
4189
- (function (ReactKitErrorCode) {
4190
- ReactKitErrorCode["NoResponse"] = "DRK1";
4191
- ReactKitErrorCode["NoCode"] = "DRK2";
4192
- ReactKitErrorCode["SessionExpired"] = "DRK3";
4193
- ReactKitErrorCode["MissingParameter"] = "DRK4";
4194
- ReactKitErrorCode["InvalidParameter"] = "DRK5";
4195
- ReactKitErrorCode["WrongCourse"] = "DRK6";
4196
- ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
4197
- ReactKitErrorCode["NoCACCLGetLaunchInfoFunction"] = "DRK8";
4198
- ReactKitErrorCode["NotTTM"] = "DRK9";
4199
- ReactKitErrorCode["NotAdmin"] = "DRK10";
4200
- })(ReactKitErrorCode || (ReactKitErrorCode = {}));
4201
- var ReactKitErrorCode$1 = ReactKitErrorCode;
4162
+ var DBEntryFieldType;
4163
+ (function (DBEntryFieldType) {
4164
+ // A string input field
4165
+ DBEntryFieldType["String"] = "String";
4166
+ // A number input field
4167
+ DBEntryFieldType["Number"] = "Number";
4168
+ // input field with subfields that are also DBEntryFields
4169
+ DBEntryFieldType["Object"] = "Object";
4170
+ // list of strings input field
4171
+ DBEntryFieldType["StringArray"] = "StringArray";
4172
+ // list of numbers input field
4173
+ DBEntryFieldType["NumberArray"] = "NumberArray";
4174
+ })(DBEntryFieldType || (DBEntryFieldType = {}));
4175
+ var DBEntryFieldType$1 = DBEntryFieldType;
4202
4176
 
4203
- /**
4204
- * Types of buttons in the modal
4205
- * @author Gabe Abrams
4206
- */
4207
- var ModalButtonType;
4208
- (function (ModalButtonType) {
4209
- ModalButtonType["Okay"] = "okay";
4210
- ModalButtonType["Cancel"] = "cancel";
4211
- ModalButtonType["Yes"] = "yes";
4212
- ModalButtonType["No"] = "no";
4213
- ModalButtonType["Abandon"] = "abandon";
4214
- ModalButtonType["GoBack"] = "goBack";
4215
- ModalButtonType["Continue"] = "continue";
4216
- ModalButtonType["ImSure"] = "imSure";
4217
- ModalButtonType["Delete"] = "delete";
4218
- ModalButtonType["Confirm"] = "confirm";
4219
- })(ModalButtonType || (ModalButtonType = {}));
4220
- var ModalButtonType$1 = ModalButtonType;
4177
+ function _extends() {
4178
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
4179
+ for (var i = 1; i < arguments.length; i++) {
4180
+ var source = arguments[i];
4181
+ for (var key in source) {
4182
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
4183
+ target[key] = source[key];
4184
+ }
4185
+ }
4186
+ }
4187
+ return target;
4188
+ };
4189
+ return _extends.apply(this, arguments);
4190
+ }
4221
4191
 
4222
- /**
4223
- * Types of modals
4224
- * @author Gabe Abrams
4225
- */
4226
- var ModalType;
4227
- (function (ModalType) {
4228
- ModalType["Okay"] = "okay";
4229
- ModalType["OkayCancel"] = "okay-cancel";
4230
- ModalType["YesNo"] = "yes-no";
4231
- ModalType["YesNoCancel"] = "yes-no-cancel";
4232
- ModalType["AbandonGoBack"] = "abandon-goBack";
4233
- ModalType["ImSureCancel"] = "imSure-cancel";
4234
- ModalType["DeleteCancel"] = "delete-cancel";
4235
- ModalType["ConfirmCancel"] = "confirm-cancel";
4236
- ModalType["NoButtons"] = "-";
4237
- })(ModalType || (ModalType = {}));
4238
- var ModalType$1 = ModalType;
4192
+ function _typeof(obj) {
4193
+ "@babel/helpers - typeof";
4239
4194
 
4240
- /**
4241
- * Bootstrap variants
4242
- * @author Gabe Abrams
4243
- */
4244
- var Variant;
4245
- (function (Variant) {
4246
- Variant["Primary"] = "primary";
4247
- Variant["Secondary"] = "secondary";
4248
- Variant["Success"] = "success";
4249
- Variant["Warning"] = "warning";
4250
- Variant["Info"] = "info";
4251
- Variant["Danger"] = "danger";
4252
- Variant["Light"] = "light";
4253
- Variant["Dark"] = "dark";
4254
- })(Variant || (Variant = {}));
4255
- var Variant$1 = Variant;
4195
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
4196
+ return typeof obj;
4197
+ } : function (obj) {
4198
+ return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
4199
+ }, _typeof(obj);
4200
+ }
4256
4201
 
4257
- /**
4258
- * Modal sizes
4259
- * @author Gabe Abrams
4260
- */
4261
- var ModalSize;
4262
- (function (ModalSize) {
4263
- ModalSize["Small"] = "sm";
4264
- ModalSize["Medium"] = "md";
4265
- ModalSize["Large"] = "lg";
4266
- ModalSize["ExtraLarge"] = "xl";
4267
- })(ModalSize || (ModalSize = {}));
4268
- // Modal type to list of buttons
4269
- ({
4270
- [ModalType$1.Okay]: [
4271
- ModalButtonType$1.Okay,
4272
- ],
4273
- [ModalType$1.OkayCancel]: [
4274
- ModalButtonType$1.Okay,
4275
- ModalButtonType$1.Cancel,
4276
- ],
4277
- [ModalType$1.YesNo]: [
4278
- ModalButtonType$1.Yes,
4279
- ModalButtonType$1.No,
4280
- ],
4281
- [ModalType$1.YesNoCancel]: [
4282
- ModalButtonType$1.Yes,
4283
- ModalButtonType$1.No,
4284
- ModalButtonType$1.Cancel,
4285
- ],
4286
- [ModalType$1.AbandonGoBack]: [
4287
- ModalButtonType$1.Abandon,
4288
- ModalButtonType$1.GoBack,
4289
- ],
4290
- [ModalType$1.ImSureCancel]: [
4291
- ModalButtonType$1.ImSure,
4292
- ModalButtonType$1.Cancel,
4293
- ],
4294
- [ModalType$1.DeleteCancel]: [
4295
- ModalButtonType$1.Delete,
4296
- ModalButtonType$1.Cancel,
4297
- ],
4298
- [ModalType$1.ConfirmCancel]: [
4299
- ModalButtonType$1.Confirm,
4300
- ModalButtonType$1.Cancel,
4301
- ],
4302
- });
4303
- // Button type styling and labels
4304
- ({
4305
- [ModalButtonType$1.Okay]: {
4306
- label: 'Okay',
4307
- variant: Variant$1.Dark,
4308
- },
4309
- [ModalButtonType$1.Cancel]: {
4310
- label: 'Cancel',
4311
- variant: Variant$1.Secondary,
4312
- },
4313
- [ModalButtonType$1.Yes]: {
4314
- label: 'Yes',
4315
- variant: Variant$1.Dark,
4316
- },
4317
- [ModalButtonType$1.No]: {
4318
- label: 'No',
4319
- variant: Variant$1.Secondary,
4320
- },
4321
- [ModalButtonType$1.Abandon]: {
4322
- label: 'Abandon Changes',
4323
- variant: Variant$1.Warning,
4324
- },
4325
- [ModalButtonType$1.GoBack]: {
4326
- label: 'Go Back',
4327
- variant: Variant$1.Secondary,
4328
- },
4329
- [ModalButtonType$1.Continue]: {
4330
- label: 'Continue',
4331
- variant: Variant$1.Dark,
4332
- },
4333
- [ModalButtonType$1.ImSure]: {
4334
- label: 'I am sure',
4335
- variant: Variant$1.Warning,
4336
- },
4337
- [ModalButtonType$1.Delete]: {
4338
- label: 'Yes, Delete',
4339
- variant: Variant$1.Danger,
4340
- },
4341
- [ModalButtonType$1.Confirm]: {
4342
- label: 'Confirm',
4343
- variant: Variant$1.Dark,
4344
- },
4345
- });
4202
+ function _toPrimitive(input, hint) {
4203
+ if (_typeof(input) !== "object" || input === null) return input;
4204
+ var prim = input[Symbol.toPrimitive];
4205
+ if (prim !== undefined) {
4206
+ var res = prim.call(input, hint || "default");
4207
+ if (_typeof(res) !== "object") return res;
4208
+ throw new TypeError("@@toPrimitive must return a primitive value.");
4209
+ }
4210
+ return (hint === "string" ? String : Number)(input);
4211
+ }
4346
4212
 
4347
- /**
4348
- * An error with a code
4349
- * @author Gabe Abrams
4350
- */
4351
- class ErrorWithCode extends Error {
4352
- constructor(message, code) {
4353
- super(message);
4354
- this.name = 'ErrorWithCode';
4355
- this.code = code;
4356
- }
4213
+ function _toPropertyKey(arg) {
4214
+ var key = _toPrimitive(arg, "string");
4215
+ return _typeof(key) === "symbol" ? key : String(key);
4357
4216
  }
4358
- /**
4359
- * Send a request using caccl's send request feature
4360
- * @author Gabe Abrams
4361
- * @param opts send request options
4362
- * @returns send request response
4363
- */
4364
- const cacclSendRequest = (opts) => __awaiter(void 0, void 0, void 0, function* () {
4365
- // Make sure send request has been passed in
4366
- {
4367
- throw new ErrorWithCode(`\nThe request could not be sent because the AppWrapper component does not have a copy of sendRequest from CACCL.\nIf you are currently writing tests for your app, this means you did not properly stub the server response.\nMethod: ${opts.method}\nPath: ${opts.path}\n\n`, ReactKitErrorCode$1.NoCACCLSendRequestFunction);
4368
- }
4369
- });
4370
- /**
4371
- * Show an alert modal with an "Okay" button
4372
- * @author Gabe Abrams
4373
- * @param title the title text to display at the top of the alert
4374
- * @param text the text to display in the alert
4375
- */
4376
- const alert$1 = (title, text) => __awaiter(void 0, void 0, void 0, function* () {
4377
- // Fallback if alert not available
4378
- {
4379
- window.alert(`${title}\n\n${text}`);
4380
- return undefined;
4381
- }
4382
- });
4383
- /**
4384
- * Show a fatal error message
4385
- * @author Gabe Abrams
4386
- * @param error the error to show
4387
- * @param [errorTitle] title of the error box
4388
- */
4389
- const showFatalError = (error, errorTitle = 'An Error Occurred') => {
4390
- var _a, _b;
4391
- // Determine message and code
4392
- const message = (typeof error === 'string'
4393
- ? error.trim()
4394
- : String((_a = error.message) !== null && _a !== void 0 ? _a : 'An unknown error occurred.'));
4395
- const code = (typeof error === 'string'
4396
- ? ReactKitErrorCode$1.NoCode
4397
- : String((_b = error.code) !== null && _b !== void 0 ? _b : ReactKitErrorCode$1.NoCode));
4398
- // Handle case where app hasn't loaded
4399
- {
4400
- alert$1(errorTitle, `${message} (code: ${code}). Please contact support.`);
4401
- return undefined;
4402
- }
4403
- };
4404
4217
 
4405
- /**
4406
- * Loading spinner/indicator
4407
- * @author Gabe Abrams
4408
- */
4409
- /*------------------------------------------------------------------------*/
4410
- /* Style */
4411
- /*------------------------------------------------------------------------*/
4412
- const style$5 = `
4413
- /* Container fades in */
4414
- .LoadingSpinner-container {
4415
- animation-name: LoadingSpinner-container-fade-in;
4416
- animation-duration: 0.3s;
4417
- animation-delay: 0.4s;
4418
- animation-fill-mode: both;
4419
- animation-timing-function: ease-out;
4218
+ function _defineProperty(obj, key, value) {
4219
+ key = _toPropertyKey(key);
4220
+ if (key in obj) {
4221
+ Object.defineProperty(obj, key, {
4222
+ value: value,
4223
+ enumerable: true,
4224
+ configurable: true,
4225
+ writable: true
4226
+ });
4227
+ } else {
4228
+ obj[key] = value;
4229
+ }
4230
+ return obj;
4420
4231
  }
4421
- @keyframes LoadingSpinner-container-fade-in {
4422
- 0% {
4423
- opacity: 0;
4232
+
4233
+ function ownKeys(object, enumerableOnly) {
4234
+ var keys = Object.keys(object);
4235
+ if (Object.getOwnPropertySymbols) {
4236
+ var symbols = Object.getOwnPropertySymbols(object);
4237
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
4238
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
4239
+ })), keys.push.apply(keys, symbols);
4424
4240
  }
4425
- 100% {
4426
- opacity: 1;
4241
+ return keys;
4242
+ }
4243
+ function _objectSpread2(target) {
4244
+ for (var i = 1; i < arguments.length; i++) {
4245
+ var source = null != arguments[i] ? arguments[i] : {};
4246
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
4247
+ _defineProperty(target, key, source[key]);
4248
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
4249
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
4250
+ });
4427
4251
  }
4252
+ return target;
4428
4253
  }
4429
4254
 
4430
- /* Blips */
4431
- .LoadingSpinner-blip-1,
4432
- .LoadingSpinner-blip-2,
4433
- .LoadingSpinner-blip-3,
4434
- .LoadingSpinner-blip-4 {
4435
- font-size: 1.8rem;
4436
- opacity: 0.6;
4437
- margin-top: 1rem;
4438
- margin-bottom: 1rem;
4255
+ function _classCallCheck(instance, Constructor) {
4256
+ if (!(instance instanceof Constructor)) {
4257
+ throw new TypeError("Cannot call a class as a function");
4258
+ }
4439
4259
  }
4440
4260
 
4441
- /* First Blip */
4442
- .LoadingSpinner-blip-1 {
4443
- animation: LoadingSpinner-pop-animation 2s infinite;
4261
+ function _defineProperties(target, props) {
4262
+ for (var i = 0; i < props.length; i++) {
4263
+ var descriptor = props[i];
4264
+ descriptor.enumerable = descriptor.enumerable || false;
4265
+ descriptor.configurable = true;
4266
+ if ("value" in descriptor) descriptor.writable = true;
4267
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
4268
+ }
4269
+ }
4270
+ function _createClass(Constructor, protoProps, staticProps) {
4271
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
4272
+ if (staticProps) _defineProperties(Constructor, staticProps);
4273
+ Object.defineProperty(Constructor, "prototype", {
4274
+ writable: false
4275
+ });
4276
+ return Constructor;
4444
4277
  }
4445
4278
 
4446
- /* Second Blip */
4447
- .LoadingSpinner-blip-2 {
4448
- animation: LoadingSpinner-pop-animation 2s infinite;
4449
- -webkit-animation-delay: 0.1s;
4450
- animation-delay: 0.1s;
4279
+ function _setPrototypeOf(o, p) {
4280
+ _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
4281
+ o.__proto__ = p;
4282
+ return o;
4283
+ };
4284
+ return _setPrototypeOf(o, p);
4451
4285
  }
4452
4286
 
4453
- /* Third Blip */
4454
- .LoadingSpinner-blip-3 {
4455
- animation: LoadingSpinner-pop-animation 2s infinite;
4456
- animation-delay: 0.2s;
4287
+ function _inherits(subClass, superClass) {
4288
+ if (typeof superClass !== "function" && superClass !== null) {
4289
+ throw new TypeError("Super expression must either be null or a function");
4290
+ }
4291
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
4292
+ constructor: {
4293
+ value: subClass,
4294
+ writable: true,
4295
+ configurable: true
4296
+ }
4297
+ });
4298
+ Object.defineProperty(subClass, "prototype", {
4299
+ writable: false
4300
+ });
4301
+ if (superClass) _setPrototypeOf(subClass, superClass);
4457
4302
  }
4458
4303
 
4459
- /* Fourth Blip */
4460
- .LoadingSpinner-blip-4 {
4461
- animation: LoadingSpinner-pop-animation 2s infinite;
4462
- animation-delay: 0.3s;
4304
+ function _getPrototypeOf(o) {
4305
+ _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
4306
+ return o.__proto__ || Object.getPrototypeOf(o);
4307
+ };
4308
+ return _getPrototypeOf(o);
4463
4309
  }
4464
4310
 
4465
- /* Pop Animation for Each Blip */
4466
- @keyframes LoadingSpinner-pop-animation {
4467
- 0% {
4468
- transform: scale(1.0);
4469
- }
4470
- 10% {
4471
- transform: scale(1.5);
4311
+ function _isNativeReflectConstruct() {
4312
+ if (typeof Reflect === "undefined" || !Reflect.construct) return false;
4313
+ if (Reflect.construct.sham) return false;
4314
+ if (typeof Proxy === "function") return true;
4315
+ try {
4316
+ Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
4317
+ return true;
4318
+ } catch (e) {
4319
+ return false;
4472
4320
  }
4473
- 30% {
4474
- transform: scale(1.0);
4321
+ }
4322
+
4323
+ function _assertThisInitialized(self) {
4324
+ if (self === void 0) {
4325
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
4475
4326
  }
4476
- 100% {
4477
- transform: scale(1.0);
4327
+ return self;
4328
+ }
4329
+
4330
+ function _possibleConstructorReturn(self, call) {
4331
+ if (call && (_typeof(call) === "object" || typeof call === "function")) {
4332
+ return call;
4333
+ } else if (call !== void 0) {
4334
+ throw new TypeError("Derived constructors may only return object or undefined");
4478
4335
  }
4336
+ return _assertThisInitialized(self);
4479
4337
  }
4480
- `;
4481
- /*------------------------------------------------------------------------*/
4482
- /* Component */
4483
- /*------------------------------------------------------------------------*/
4484
- const LoadingSpinner = () => {
4485
- /*------------------------------------------------------------------------*/
4486
- /* Render */
4487
- /*------------------------------------------------------------------------*/
4488
- // Add all four blips to a container
4489
- return (React__default["default"].createElement("div", { className: "text-center LoadingSpinner LoadingSpinner-container" },
4490
- React__default["default"].createElement("style", null, style$5),
4491
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-1 me-1" }),
4492
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-2 me-1" }),
4493
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-3 me-1" }),
4494
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "LoadingSpinner-blip-4" })));
4495
- };
4496
4338
 
4497
- /**
4498
- * A radio selection button
4499
- * @author Gabe Abrams
4500
- */
4501
- /*------------------------------------------------------------------------*/
4502
- /* Component */
4503
- /*------------------------------------------------------------------------*/
4504
- const RadioButton = (props) => {
4505
- /*------------------------------------------------------------------------*/
4506
- /* Setup */
4507
- /*------------------------------------------------------------------------*/
4508
- /* -------------- Props ------------- */
4509
- const { text, onSelected, ariaLabel, title, selected, id, noMarginOnRight, selectedVariant = Variant$1.Secondary, unselectedVariant = Variant$1.Light, small, } = props;
4510
- /*------------------------------------------------------------------------*/
4511
- /* Render */
4512
- /*------------------------------------------------------------------------*/
4513
- /*----------------------------------------*/
4514
- /* Main UI */
4515
- /*----------------------------------------*/
4516
- return (React__default["default"].createElement("button", { type: "button", id: id, title: title, className: `btn btn-${selected ? selectedVariant : unselectedVariant}${selected ? ' selected' : ''}${small ? ' btn-sm' : ''} m-0${noMarginOnRight ? '' : ' me-1'}`, "aria-label": `${ariaLabel}${selected ? ': currently selected' : ''}`, onClick: () => {
4517
- if (!selected) {
4518
- onSelected();
4519
- }
4520
- } },
4521
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: selected ? freeSolidSvgIcons.faDotCircle : freeRegularSvgIcons.faCircle, className: "me-1" }),
4522
- text));
4523
- };
4339
+ function _createSuper(Derived) {
4340
+ var hasNativeReflectConstruct = _isNativeReflectConstruct();
4341
+ return function _createSuperInternal() {
4342
+ var Super = _getPrototypeOf(Derived),
4343
+ result;
4344
+ if (hasNativeReflectConstruct) {
4345
+ var NewTarget = _getPrototypeOf(this).constructor;
4346
+ result = Reflect.construct(Super, arguments, NewTarget);
4347
+ } else {
4348
+ result = Super.apply(this, arguments);
4349
+ }
4350
+ return _possibleConstructorReturn(this, result);
4351
+ };
4352
+ }
4524
4353
 
4525
- /**
4526
- * A checkbox button
4527
- * @author Gabe Abrams
4528
- */
4529
- /*------------------------------------------------------------------------*/
4530
- /* Component */
4531
- /*------------------------------------------------------------------------*/
4532
- const CheckboxButton = (props) => {
4533
- /*------------------------------------------------------------------------*/
4534
- /* Setup */
4535
- /*------------------------------------------------------------------------*/
4536
- /* -------------- Props ------------- */
4537
- const { text, onChanged, ariaLabel, title, checked, id, className, noMarginOnRight, checkedVariant = Variant$1.Secondary, uncheckedVariant = Variant$1.Light, small, dashed, } = props;
4538
- /*------------------------------------------------------------------------*/
4539
- /* Render */
4540
- /*------------------------------------------------------------------------*/
4541
- /*----------------------------------------*/
4542
- /* Main UI */
4543
- /*----------------------------------------*/
4544
- // Determine the icon
4545
- let icon;
4546
- if (checked) {
4547
- icon = freeSolidSvgIcons.faCheckSquare;
4354
+ function _arrayLikeToArray(arr, len) {
4355
+ if (len == null || len > arr.length) len = arr.length;
4356
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
4357
+ return arr2;
4358
+ }
4359
+
4360
+ function _arrayWithoutHoles(arr) {
4361
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
4362
+ }
4363
+
4364
+ function _iterableToArray(iter) {
4365
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
4366
+ }
4367
+
4368
+ function _unsupportedIterableToArray(o, minLen) {
4369
+ if (!o) return;
4370
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
4371
+ var n = Object.prototype.toString.call(o).slice(8, -1);
4372
+ if (n === "Object" && o.constructor) n = o.constructor.name;
4373
+ if (n === "Map" || n === "Set") return Array.from(o);
4374
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
4375
+ }
4376
+
4377
+ function _nonIterableSpread() {
4378
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
4379
+ }
4380
+
4381
+ function _toConsumableArray(arr) {
4382
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
4383
+ }
4384
+
4385
+ /*
4386
+
4387
+ Based off glamor's StyleSheet, thanks Sunil ❤️
4388
+
4389
+ high performance StyleSheet for css-in-js systems
4390
+
4391
+ - uses multiple style tags behind the scenes for millions of rules
4392
+ - uses `insertRule` for appending in production for *much* faster performance
4393
+
4394
+ // usage
4395
+
4396
+ import { StyleSheet } from '@emotion/sheet'
4397
+
4398
+ let styleSheet = new StyleSheet({ key: '', container: document.head })
4399
+
4400
+ styleSheet.insert('#box { border: 1px solid red; }')
4401
+ - appends a css rule into the stylesheet
4402
+
4403
+ styleSheet.flush()
4404
+ - empties the stylesheet of all its contents
4405
+
4406
+ */
4407
+ // $FlowFixMe
4408
+ function sheetForTag(tag) {
4409
+ if (tag.sheet) {
4410
+ // $FlowFixMe
4411
+ return tag.sheet;
4412
+ } // this weirdness brought to you by firefox
4413
+
4414
+ /* istanbul ignore next */
4415
+
4416
+
4417
+ for (var i = 0; i < document.styleSheets.length; i++) {
4418
+ if (document.styleSheets[i].ownerNode === tag) {
4419
+ // $FlowFixMe
4420
+ return document.styleSheets[i];
4548
4421
  }
4549
- else {
4550
- icon = (dashed
4551
- ? freeRegularSvgIcons.faSquareMinus
4552
- : freeRegularSvgIcons.faSquare);
4422
+ }
4423
+ }
4424
+
4425
+ function createStyleElement(options) {
4426
+ var tag = document.createElement('style');
4427
+ tag.setAttribute('data-emotion', options.key);
4428
+
4429
+ if (options.nonce !== undefined) {
4430
+ tag.setAttribute('nonce', options.nonce);
4431
+ }
4432
+
4433
+ tag.appendChild(document.createTextNode(''));
4434
+ tag.setAttribute('data-s', '');
4435
+ return tag;
4436
+ }
4437
+
4438
+ var StyleSheet = /*#__PURE__*/function () {
4439
+ // Using Node instead of HTMLElement since container may be a ShadowRoot
4440
+ function StyleSheet(options) {
4441
+ var _this = this;
4442
+
4443
+ this._insertTag = function (tag) {
4444
+ var before;
4445
+
4446
+ if (_this.tags.length === 0) {
4447
+ if (_this.insertionPoint) {
4448
+ before = _this.insertionPoint.nextSibling;
4449
+ } else if (_this.prepend) {
4450
+ before = _this.container.firstChild;
4451
+ } else {
4452
+ before = _this.before;
4453
+ }
4454
+ } else {
4455
+ before = _this.tags[_this.tags.length - 1].nextSibling;
4456
+ }
4457
+
4458
+ _this.container.insertBefore(tag, before);
4459
+
4460
+ _this.tags.push(tag);
4461
+ };
4462
+
4463
+ this.isSpeedy = options.speedy === undefined ? process.env.NODE_ENV === 'production' : options.speedy;
4464
+ this.tags = [];
4465
+ this.ctr = 0;
4466
+ this.nonce = options.nonce; // key is the value of the data-emotion attribute, it's used to identify different sheets
4467
+
4468
+ this.key = options.key;
4469
+ this.container = options.container;
4470
+ this.prepend = options.prepend;
4471
+ this.insertionPoint = options.insertionPoint;
4472
+ this.before = null;
4473
+ }
4474
+
4475
+ var _proto = StyleSheet.prototype;
4476
+
4477
+ _proto.hydrate = function hydrate(nodes) {
4478
+ nodes.forEach(this._insertTag);
4479
+ };
4480
+
4481
+ _proto.insert = function insert(rule) {
4482
+ // the max length is how many rules we have per style tag, it's 65000 in speedy mode
4483
+ // it's 1 in dev because we insert source maps that map a single rule to a location
4484
+ // and you can only have one source map per style tag
4485
+ if (this.ctr % (this.isSpeedy ? 65000 : 1) === 0) {
4486
+ this._insertTag(createStyleElement(this));
4553
4487
  }
4554
- // Create the button
4555
- return (React__default["default"].createElement("button", { type: "button", id: id, title: title, className: `CheckboxButton-status-${checked ? 'checked' : 'unchecked'} ${dashed ? 'CheckboxButton-dashed ' : ''}btn btn-${checked ? checkedVariant : uncheckedVariant}${checked ? ' selected' : ''}${small ? ' btn-sm' : ''} m-0${noMarginOnRight ? '' : ' me-1'} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": `${ariaLabel}${checked ? ': currently checked' : ''}`, onClick: () => {
4556
- onChanged(!checked);
4557
- } },
4558
- React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: icon, className: "me-1" }),
4559
- text));
4560
- };
4488
+
4489
+ var tag = this.tags[this.tags.length - 1];
4490
+
4491
+ if (process.env.NODE_ENV !== 'production') {
4492
+ var isImportRule = rule.charCodeAt(0) === 64 && rule.charCodeAt(1) === 105;
4493
+
4494
+ if (isImportRule && this._alreadyInsertedOrderInsensitiveRule) {
4495
+ // this would only cause problem in speedy mode
4496
+ // but we don't want enabling speedy to affect the observable behavior
4497
+ // so we report this error at all times
4498
+ console.error("You're attempting to insert the following rule:\n" + rule + '\n\n`@import` rules must be before all other types of rules in a stylesheet but other rules have already been inserted. Please ensure that `@import` rules are before all other rules.');
4499
+ }
4500
+ this._alreadyInsertedOrderInsensitiveRule = this._alreadyInsertedOrderInsensitiveRule || !isImportRule;
4501
+ }
4502
+
4503
+ if (this.isSpeedy) {
4504
+ var sheet = sheetForTag(tag);
4505
+
4506
+ try {
4507
+ // this is the ultrafast version, works across browsers
4508
+ // the big drawback is that the css won't be editable in devtools
4509
+ sheet.insertRule(rule, sheet.cssRules.length);
4510
+ } catch (e) {
4511
+ if (process.env.NODE_ENV !== 'production' && !/:(-moz-placeholder|-moz-focus-inner|-moz-focusring|-ms-input-placeholder|-moz-read-write|-moz-read-only|-ms-clear|-ms-expand|-ms-reveal){/.test(rule)) {
4512
+ console.error("There was a problem inserting the following rule: \"" + rule + "\"", e);
4513
+ }
4514
+ }
4515
+ } else {
4516
+ tag.appendChild(document.createTextNode(rule));
4517
+ }
4518
+
4519
+ this.ctr++;
4520
+ };
4521
+
4522
+ _proto.flush = function flush() {
4523
+ // $FlowFixMe
4524
+ this.tags.forEach(function (tag) {
4525
+ return tag.parentNode && tag.parentNode.removeChild(tag);
4526
+ });
4527
+ this.tags = [];
4528
+ this.ctr = 0;
4529
+
4530
+ if (process.env.NODE_ENV !== 'production') {
4531
+ this._alreadyInsertedOrderInsensitiveRule = false;
4532
+ }
4533
+ };
4534
+
4535
+ return StyleSheet;
4536
+ }();
4537
+
4538
+ var MS = '-ms-';
4539
+ var MOZ = '-moz-';
4540
+ var WEBKIT = '-webkit-';
4541
+
4542
+ var COMMENT = 'comm';
4543
+ var RULESET = 'rule';
4544
+ var DECLARATION = 'decl';
4545
+ var IMPORT = '@import';
4546
+ var KEYFRAMES = '@keyframes';
4547
+ var LAYER = '@layer';
4561
4548
 
4562
4549
  /**
4563
- * Input group with a title and space for buttons
4564
- * @author Gabe Abrams
4550
+ * @param {number}
4551
+ * @return {number}
4565
4552
  */
4566
- /*------------------------------------------------------------------------*/
4567
- /* Component */
4568
- /*------------------------------------------------------------------------*/
4569
- const ButtonInputGroup = (props) => {
4570
- /*------------------------------------------------------------------------*/
4571
- /* Setup */
4572
- /*------------------------------------------------------------------------*/
4573
- /* -------------- Props ------------- */
4574
- // Destructure all props
4575
- const { label, minLabelWidth, children, } = props;
4576
- /*------------------------------------------------------------------------*/
4577
- /* Render */
4578
- /*------------------------------------------------------------------------*/
4579
- /*----------------------------------------*/
4580
- /* Main UI */
4581
- /*----------------------------------------*/
4582
- return (React__default["default"].createElement("div", { className: "input-group" },
4583
- React__default["default"].createElement("div", { className: "input-group-prepend d-flex w-100" },
4584
- React__default["default"].createElement("span", { className: "input-group-text", style: {
4585
- minWidth: (minLabelWidth !== null && minLabelWidth !== void 0 ? minLabelWidth : undefined),
4586
- borderTopRightRadius: 0,
4587
- borderBottomRightRadius: 0,
4588
- } }, label),
4589
- React__default["default"].createElement("span", { className: "input-group-text flex-grow-1 rounded-right", style: {
4590
- backgroundColor: 'white',
4591
- borderTopLeftRadius: 0,
4592
- borderBottomLeftRadius: 0,
4593
- borderLeftWidth: 0,
4594
- } }, children))));
4595
- };
4553
+ var abs = Math.abs;
4596
4554
 
4597
4555
  /**
4598
- * Copiable text box
4599
- * @author Gabe Abrams
4556
+ * @param {number}
4557
+ * @return {string}
4600
4558
  */
4601
- /* ------------- Actions ------------ */
4602
- // Types of actions
4603
- var ActionType$1$1;
4604
- (function (ActionType) {
4605
- // Indicate that the text was recently copied
4606
- ActionType["IndicateRecentlyCopied"] = "indicate-recently-copied";
4607
- // Clear the status
4608
- ActionType["ClearRecentlyCopiedStatus"] = "clear-recently-copied-status";
4609
- })(ActionType$1$1 || (ActionType$1$1 = {}));
4559
+ var from = String.fromCharCode;
4610
4560
 
4611
4561
  /**
4612
- * Reusable nested item picker
4613
- * @author Yuen Ler Chow
4562
+ * @param {object}
4563
+ * @return {object}
4614
4564
  */
4615
- /* ------------- Actions ------------ */
4616
- // Types of actions
4617
- var ActionType$3;
4618
- (function (ActionType) {
4619
- // Toggle whether the children are being shown
4620
- ActionType["ToggleItems"] = "toggle-items";
4621
- })(ActionType$3 || (ActionType$3 = {}));
4565
+ var assign = Object.assign;
4622
4566
 
4623
- // Keep track of whether or not session expiry has already been handled
4624
- let sessionAlreadyExpired = false;
4625
- /*------------------------------------------------------------------------*/
4626
- /* Stub Logic */
4627
- /*------------------------------------------------------------------------*/
4628
- // Stored stub responses
4629
- const stubResponses = {};
4630
- /*------------------------------------------------------------------------*/
4631
- /* Main */
4632
- /*------------------------------------------------------------------------*/
4633
4567
  /**
4634
- * Visit an endpoint on the server [for client only]
4635
- * @author Gabe Abrams
4636
- * @param opts object containing all arguments
4637
- * @param opts.path - the path of the server endpoint
4638
- * @param [opts.method=GET] - the method of the endpoint
4639
- * @param [opts.params] - query/body parameters to include
4640
- * @returns response from server
4568
+ * @param {string} value
4569
+ * @param {number} length
4570
+ * @return {number}
4641
4571
  */
4642
- const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function* () {
4643
- var _a, _b, _c;
4644
- const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET');
4645
- // Handle stubs
4646
- const stubResponse = (_b = stubResponses[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
4647
- if (stubResponse) {
4648
- // Remove from list
4649
- try {
4650
- stubResponses[method][opts.path] = undefined;
4651
- }
4652
- catch (err) {
4653
- // Ignore
4654
- }
4655
- // Success
4656
- if (stubResponse.success) {
4657
- return stubResponse.body;
4658
- }
4659
- // Error
4660
- throw new ErrorWithCode(stubResponse.errorMessage, stubResponse.errorCode);
4661
- }
4662
- // Send the request
4663
- const response = yield cacclSendRequest({
4664
- path: opts.path,
4665
- method: (_c = opts.method) !== null && _c !== void 0 ? _c : 'GET',
4666
- params: opts.params,
4667
- });
4668
- // Check for failure
4669
- if (!response || !response.body) {
4670
- throw new ErrorWithCode('We didn\'t get a response from the server. Please check your internet connection.', ReactKitErrorCode$1.NoResponse);
4671
- }
4672
- if (!response.body.success) {
4673
- // Session expired
4674
- if (response.body.code === ReactKitErrorCode$1.SessionExpired) {
4675
- // Skip notice if session was already expired
4676
- if (sessionAlreadyExpired) {
4677
- // Never return (browser is already reloading)
4678
- yield new Promise(() => {
4679
- // Promise that never returns
4680
- });
4681
- }
4682
- sessionAlreadyExpired = true;
4683
- // Show session expiration message
4684
- {
4685
- // Fallback to alert
4686
- // eslint-disable-next-line no-alert
4687
- alert('Your session has expired. Please start over.');
4688
- }
4689
- // Never return (don't continue execution)
4690
- yield new Promise(() => {
4691
- // Promise that never returns
4692
- });
4693
- }
4694
- // Other errors
4695
- throw new ErrorWithCode((response.body.message
4696
- || 'An unknown error occurred. Please contact an admin.'), (response.body.code
4697
- || ReactKitErrorCode$1.NoCode));
4698
- }
4699
- // Success! Extract the body
4700
- const { body } = response.body;
4701
- // Return
4702
- return body;
4703
- });
4572
+ function hash (value, length) {
4573
+ return charat(value, 0) ^ 45 ? (((((((length << 2) ^ charat(value, 0)) << 2) ^ charat(value, 1)) << 2) ^ charat(value, 2)) << 2) ^ charat(value, 3) : 0
4574
+ }
4704
4575
 
4705
- // Import custom error
4706
- // Stored copy of caccl functions
4707
- let _cacclGetLaunchInfo$1;
4708
- /*------------------------------------------------------------------------*/
4709
- /* Helpers */
4710
- /*------------------------------------------------------------------------*/
4711
4576
  /**
4712
- * Get launch info via CACCL
4713
- * @author Gabe Abrams
4714
- * @param req express request object
4715
- * @returns object { launched, launchInfo }
4577
+ * @param {string} value
4578
+ * @return {string}
4716
4579
  */
4717
- const cacclGetLaunchInfo$1 = (req) => {
4718
- {
4719
- throw new ErrorWithCode('Could not get launch info because server was not initialized with dce-reactkit\'s initServer function', ReactKitErrorCode$1.NoCACCLGetLaunchInfoFunction);
4720
- }
4721
- };
4580
+ function trim (value) {
4581
+ return value.trim()
4582
+ }
4722
4583
 
4723
4584
  /**
4724
- * Server-side API param types
4725
- * @author Gabe Abrams
4585
+ * @param {string} value
4586
+ * @param {RegExp} pattern
4587
+ * @return {string?}
4726
4588
  */
4727
- var ParamType;
4728
- (function (ParamType) {
4729
- ParamType["Boolean"] = "boolean";
4730
- ParamType["BooleanOptional"] = "boolean-optional";
4731
- ParamType["Float"] = "float";
4732
- ParamType["FloatOptional"] = "float-optional";
4733
- ParamType["Int"] = "int";
4734
- ParamType["IntOptional"] = "int-optional";
4735
- ParamType["JSON"] = "json";
4736
- ParamType["JSONOptional"] = "json-optional";
4737
- ParamType["String"] = "string";
4738
- ParamType["StringOptional"] = "string-optional";
4739
- })(ParamType || (ParamType = {}));
4740
- var ParamType$1 = ParamType;
4589
+ function match (value, pattern) {
4590
+ return (value = pattern.exec(value)) ? value[0] : value
4591
+ }
4741
4592
 
4742
- // Import shared types
4743
4593
  /**
4744
- * Handle an error and respond to the client
4745
- * @author Gabe Abrams
4746
- * @param res express response
4747
- * @param error error info
4748
- * @param opts.err the error to send to the client
4749
- * or the error message
4750
- * @param [opts.code] an error code (only used if err.code is not
4751
- * included)
4752
- * @param [opts.status=500] the https status code to use
4753
- * defined)
4594
+ * @param {string} value
4595
+ * @param {(string|RegExp)} pattern
4596
+ * @param {string} replacement
4597
+ * @return {string}
4754
4598
  */
4755
- const handleError$1 = (res, error) => {
4756
- // Get the error message
4757
- let message;
4758
- if (error && error.message) {
4759
- message = (error.message || 'An unknown error occurred.');
4760
- }
4761
- else if (typeof error === 'string') {
4762
- message = (error.trim().length > 0
4763
- ? error
4764
- : 'An unknown error occurred.');
4765
- }
4766
- else {
4767
- message = 'An unknown error occurred.';
4768
- }
4769
- // Get the error code
4770
- const code = (error.code || ReactKitErrorCode$1.NoCode);
4771
- // Get the status code
4772
- const status = (error.status || 500);
4773
- // Respond to user
4774
- res
4775
- // Set the http status code
4776
- .status(status)
4777
- // Send a JSON response
4778
- .json({
4779
- // Error message
4780
- message,
4781
- // Error code
4782
- code,
4783
- // Success = false flag so client can detect server-side errors
4784
- success: false,
4785
- });
4786
- return undefined;
4787
- };
4599
+ function replace (value, pattern, replacement) {
4600
+ return value.replace(pattern, replacement)
4601
+ }
4788
4602
 
4789
4603
  /**
4790
- * Send successful API response
4791
- * @author Gabe Abrams
4792
- * @param res express response
4793
- * @param body the body of the response to send to the client
4604
+ * @param {string} value
4605
+ * @param {string} search
4606
+ * @return {number}
4794
4607
  */
4795
- const handleSuccess$1 = (res, body) => {
4796
- // Send a http 200 json response
4797
- res.json({
4798
- // Include the body as a parameter
4799
- body,
4800
- // Success = true flag so client can detect successful responses
4801
- success: true,
4802
- });
4803
- return undefined;
4804
- };
4608
+ function indexof (value, search) {
4609
+ return value.indexOf(search)
4610
+ }
4805
4611
 
4806
4612
  /**
4807
- * Generate an express API route handler
4808
- * @author Gabe Abrams
4809
- * @param opts object containing all arguments
4810
- * @param opts.paramTypes map containing the types for each parameter that is
4811
- * included in the request (map: param name => type)
4812
- * @param opts.handler function that processes the request
4813
- * @returns express route handler that takes the following arguments:
4814
- * params (map: param name => value), handleSuccess (function for handling
4815
- * successful requests), handleError (function for handling failed requests),
4816
- * req (express request object), res (express response object),
4817
- * next (express next function). Params also has userId, userFirstName,
4818
- * userLastName, isLearner, isTTM, isAdmin, and any other variables that
4819
- * are directly added to the session
4820
- */
4821
- const genRouteHandler$1 = (opts) => {
4822
- // Return a route handler
4823
- return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
4824
- var _a, _b;
4825
- // Output params
4826
- const output = {};
4827
- /*----------------------------------------*/
4828
- /* Parse Params */
4829
- /*----------------------------------------*/
4830
- // Process items one by one
4831
- const paramList = Object.entries((_a = opts.paramTypes) !== null && _a !== void 0 ? _a : {});
4832
- for (let i = 0; i < paramList.length; i++) {
4833
- const [name, type] = paramList[i];
4834
- // Find the value as a string
4835
- const value = (req.params[name]
4836
- || req.query[name]
4837
- || req.body[name]);
4838
- // Parse
4839
- if (type === ParamType$1.Boolean || type === ParamType$1.BooleanOptional) {
4840
- // Boolean
4841
- // Handle case where value doesn't exist
4842
- if (value === undefined) {
4843
- if (type === ParamType$1.BooleanOptional) {
4844
- output[name] = undefined;
4845
- }
4846
- else {
4847
- return handleError$1(res, {
4848
- message: `Parameter ${name} is required, but it was not included.`,
4849
- code: ReactKitErrorCode$1.MissingParameter,
4850
- status: 422,
4851
- });
4852
- }
4853
- }
4854
- else {
4855
- // Value exists
4856
- // Simplify value
4857
- const simpleVal = (String(value)
4858
- .trim()
4859
- .toLowerCase());
4860
- // Parse
4861
- output[name] = ([
4862
- 'true',
4863
- 'yes',
4864
- 'y',
4865
- '1',
4866
- 't',
4867
- ].indexOf(simpleVal) >= 0);
4868
- }
4869
- }
4870
- else if (type === ParamType$1.Float || type === ParamType$1.FloatOptional) {
4871
- // Float
4872
- // Handle case where value doesn't exist
4873
- if (value === undefined) {
4874
- if (type === ParamType$1.FloatOptional) {
4875
- output[name] = undefined;
4876
- }
4877
- else {
4878
- return handleError$1(res, {
4879
- message: `Parameter ${name} is required, but it was not included.`,
4880
- code: ReactKitErrorCode$1.MissingParameter,
4881
- status: 422,
4882
- });
4883
- }
4884
- }
4885
- else if (!Number.isNaN(Number.parseFloat(String(value)))) {
4886
- // Value is a number
4887
- output[name] = Number.parseFloat(String(value));
4888
- }
4889
- else {
4890
- // Issue!
4891
- return handleError$1(res, {
4892
- message: `Request data was malformed: ${name} was not a valid float.`,
4893
- code: ReactKitErrorCode$1.InvalidParameter,
4894
- status: 422,
4895
- });
4896
- }
4897
- }
4898
- else if (type === ParamType$1.Int || type === ParamType$1.IntOptional) {
4899
- // Int
4900
- // Handle case where value doesn't exist
4901
- if (value === undefined) {
4902
- if (type === ParamType$1.IntOptional) {
4903
- output[name] = undefined;
4904
- }
4905
- else {
4906
- return handleError$1(res, {
4907
- message: `Parameter ${name} is required, but it was not included.`,
4908
- code: ReactKitErrorCode$1.MissingParameter,
4909
- status: 422,
4910
- });
4911
- }
4912
- }
4913
- else if (!Number.isNaN(Number.parseInt(String(value), 10))) {
4914
- // Value is a number
4915
- output[name] = Number.parseInt(String(value), 10);
4916
- }
4917
- else {
4918
- // Issue!
4919
- return handleError$1(res, {
4920
- message: `Request data was malformed: ${name} was not a valid int.`,
4921
- code: ReactKitErrorCode$1.InvalidParameter,
4922
- status: 422,
4923
- });
4924
- }
4925
- }
4926
- else if (type === ParamType$1.JSON || type === ParamType$1.JSONOptional) {
4927
- // Stringified JSON
4928
- // Handle case where value doesn't exist
4929
- if (value === undefined) {
4930
- if (type === ParamType$1.JSONOptional) {
4931
- output[name] = undefined;
4932
- }
4933
- else {
4934
- return handleError$1(res, {
4935
- message: `Parameter ${name} is required, but it was not included.`,
4936
- code: ReactKitErrorCode$1.MissingParameter,
4937
- status: 422,
4938
- });
4939
- }
4940
- }
4941
- else {
4942
- // Value exists
4943
- // Parse
4944
- try {
4945
- output[name] = JSON.parse(String(value));
4946
- }
4947
- catch (err) {
4948
- return handleError$1(res, {
4949
- message: `Request data was malformed: ${name} was not a valid JSON payload.`,
4950
- code: ReactKitErrorCode$1.InvalidParameter,
4951
- status: 422,
4952
- });
4953
- }
4954
- }
4955
- }
4956
- else if (type === ParamType$1.String || type === ParamType$1.StringOptional) {
4957
- // String
4958
- // Handle case where value doesn't exist
4959
- if (value === undefined) {
4960
- if (type === ParamType$1.StringOptional) {
4961
- output[name] = undefined;
4962
- }
4963
- else {
4964
- return handleError$1(res, {
4965
- message: `Parameter ${name} is required, but it was not included.`,
4966
- code: ReactKitErrorCode$1.MissingParameter,
4967
- status: 422,
4968
- });
4969
- }
4970
- }
4971
- else {
4972
- // Value exists
4973
- // Leave as is
4974
- output[name] = value;
4975
- }
4976
- }
4977
- else {
4978
- // No valid data type
4979
- return handleError$1(res, {
4980
- message: `An internal error occurred: we could not determine the type of ${name}.`,
4981
- code: ReactKitErrorCode$1.InvalidParameter,
4982
- status: 422,
4983
- });
4984
- }
4985
- }
4986
- /*----------------------------------------*/
4987
- /* Launch Info */
4988
- /*----------------------------------------*/
4989
- // Get launch info
4990
- const { launched, launchInfo } = cacclGetLaunchInfo$1(req);
4991
- if (!launched || !launchInfo) {
4992
- return handleError$1(res, {
4993
- message: 'Your session has expired. Please refresh the page and try again.',
4994
- code: ReactKitErrorCode$1.SessionExpired,
4995
- status: 440,
4996
- });
4997
- }
4998
- // Error if user info cannot be found
4999
- if (!launchInfo.userId
5000
- || !launchInfo.userFirstName
5001
- || !launchInfo.userLastName
5002
- || (launchInfo.notInCourse
5003
- && !launchInfo.isAdmin)
5004
- || (!launchInfo.isTTM
5005
- && !launchInfo.isLearner
5006
- && !launchInfo.isAdmin)) {
5007
- return handleError$1(res, {
5008
- message: 'Your session was invalid. Please refresh the page and try again.',
5009
- code: ReactKitErrorCode$1.SessionExpired,
5010
- status: 440,
5011
- });
5012
- }
5013
- // Add launch info to output
5014
- output.userId = launchInfo.userId;
5015
- output.userFirstName = launchInfo.userFirstName;
5016
- output.userLastName = launchInfo.userLastName;
5017
- output.userEmail = launchInfo.userEmail;
5018
- output.isLearner = !!launchInfo.isLearner;
5019
- output.isTTM = !!launchInfo.isTTM;
5020
- output.isAdmin = !!launchInfo.isAdmin;
5021
- output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
5022
- output.courseName = launchInfo.contextLabel;
5023
- // Add other session variables
5024
- Object.keys(req.session).forEach((propName) => {
5025
- // Skip if prop already in output
5026
- if (output[propName] !== undefined) {
5027
- return;
5028
- }
5029
- // Add to output
5030
- const value = req.session[propName];
5031
- if (typeof value === 'string'
5032
- || typeof value === 'boolean'
5033
- || typeof value === 'number') {
5034
- output[propName] = value;
5035
- }
5036
- });
5037
- /*----------------------------------------*/
5038
- /* Require Course Consistency */
5039
- /*----------------------------------------*/
5040
- // Make sure the user actually launched from the appropriate course
5041
- if (output.courseId
5042
- && launchInfo.courseId
5043
- && output.courseId !== launchInfo.courseId
5044
- && !output.isTTM
5045
- && !output.isAdmin) {
5046
- // Course of interest is not the launch course
5047
- return handleError$1(res, {
5048
- message: 'You switched sessions by opening this app in another tab. Please refresh the page and try again.',
5049
- code: ReactKitErrorCode$1.WrongCourse,
5050
- status: 401,
5051
- });
5052
- }
5053
- /*----------------------------------------*/
5054
- /* Require Proper Permissions */
5055
- /*----------------------------------------*/
5056
- // Add TTM endpoint security
5057
- if (
5058
- // This is a TTM endpoint
5059
- req.path.startsWith('/api/ttm')
5060
- // User is not a TTM
5061
- && (
5062
- // User is not a TTM
5063
- !output.isTTM
5064
- // User is not an admin
5065
- && !output.isAdmin)) {
5066
- // User does not have access
5067
- return handleError$1(res, {
5068
- message: 'This action is only allowed if you are a teaching team member for the course. Please go back to Canvas, log in as a teaching team member, and try again.',
5069
- code: ReactKitErrorCode$1.NotTTM,
5070
- status: 401,
5071
- });
5072
- }
5073
- // Add Admin endpoint security
5074
- if (
5075
- // This is an admin endpoint
5076
- req.path.startsWith('/api/admin')
5077
- // User is not an admin
5078
- && !output.isAdmin) {
5079
- // User does not have access
5080
- return handleError$1(res, {
5081
- message: 'This action is only allowed if you are a Canvas admin. Please go back to Canvas, log in as an admin, and try again.',
5082
- code: ReactKitErrorCode$1.NotAdmin,
5083
- status: 401,
5084
- });
5085
- }
5086
- /*------------------------------------------------------------------------*/
5087
- /* Call handler */
5088
- /*------------------------------------------------------------------------*/
5089
- try {
5090
- const results = yield opts.handler({
5091
- params: output,
5092
- req,
5093
- res,
5094
- next,
5095
- });
5096
- // Send results to client
5097
- handleSuccess$1(res, results !== null && results !== void 0 ? results : undefined);
5098
- }
5099
- catch (err) {
5100
- // Send error to client
5101
- handleError$1(res, err);
5102
- }
5103
- });
5104
- };
5105
-
5106
- /**
5107
- * Days of the week
5108
- * @author Gabe Abrams
5109
- */
5110
- var DayOfWeek$2;
5111
- (function (DayOfWeek) {
5112
- DayOfWeek["Monday"] = "m";
5113
- DayOfWeek["Tuesday"] = "t";
5114
- DayOfWeek["Wednesday"] = "w";
5115
- DayOfWeek["Thursday"] = "r";
5116
- DayOfWeek["Friday"] = "f";
5117
- DayOfWeek["Saturday"] = "s";
5118
- DayOfWeek["Sunday"] = "u";
5119
- })(DayOfWeek$2 || (DayOfWeek$2 = {}));
5120
-
5121
- /**
5122
- * Options for field types
5123
- * @author Yuen Ler Chow
5124
- */
5125
- var DBEntryFieldType;
5126
- (function (DBEntryFieldType) {
5127
- // A string input field
5128
- DBEntryFieldType["String"] = "String";
5129
- // A number input field
5130
- DBEntryFieldType["Number"] = "Number";
5131
- // input field with subfields that are also DBEntryFields
5132
- DBEntryFieldType["Object"] = "Object";
5133
- // list of strings input field
5134
- DBEntryFieldType["StringArray"] = "StringArray";
5135
- // list of numbers input field
5136
- DBEntryFieldType["NumberArray"] = "NumberArray";
5137
- })(DBEntryFieldType || (DBEntryFieldType = {}));
5138
- var DBEntryFieldType$1 = DBEntryFieldType;
5139
-
5140
- function _extends() {
5141
- _extends = Object.assign ? Object.assign.bind() : function (target) {
5142
- for (var i = 1; i < arguments.length; i++) {
5143
- var source = arguments[i];
5144
- for (var key in source) {
5145
- if (Object.prototype.hasOwnProperty.call(source, key)) {
5146
- target[key] = source[key];
5147
- }
5148
- }
5149
- }
5150
- return target;
5151
- };
5152
- return _extends.apply(this, arguments);
5153
- }
5154
-
5155
- function _typeof(obj) {
5156
- "@babel/helpers - typeof";
5157
-
5158
- return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
5159
- return typeof obj;
5160
- } : function (obj) {
5161
- return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
5162
- }, _typeof(obj);
5163
- }
5164
-
5165
- function _toPrimitive(input, hint) {
5166
- if (_typeof(input) !== "object" || input === null) return input;
5167
- var prim = input[Symbol.toPrimitive];
5168
- if (prim !== undefined) {
5169
- var res = prim.call(input, hint || "default");
5170
- if (_typeof(res) !== "object") return res;
5171
- throw new TypeError("@@toPrimitive must return a primitive value.");
5172
- }
5173
- return (hint === "string" ? String : Number)(input);
5174
- }
5175
-
5176
- function _toPropertyKey(arg) {
5177
- var key = _toPrimitive(arg, "string");
5178
- return _typeof(key) === "symbol" ? key : String(key);
5179
- }
5180
-
5181
- function _defineProperty(obj, key, value) {
5182
- key = _toPropertyKey(key);
5183
- if (key in obj) {
5184
- Object.defineProperty(obj, key, {
5185
- value: value,
5186
- enumerable: true,
5187
- configurable: true,
5188
- writable: true
5189
- });
5190
- } else {
5191
- obj[key] = value;
5192
- }
5193
- return obj;
5194
- }
5195
-
5196
- function ownKeys(object, enumerableOnly) {
5197
- var keys = Object.keys(object);
5198
- if (Object.getOwnPropertySymbols) {
5199
- var symbols = Object.getOwnPropertySymbols(object);
5200
- enumerableOnly && (symbols = symbols.filter(function (sym) {
5201
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
5202
- })), keys.push.apply(keys, symbols);
5203
- }
5204
- return keys;
5205
- }
5206
- function _objectSpread2(target) {
5207
- for (var i = 1; i < arguments.length; i++) {
5208
- var source = null != arguments[i] ? arguments[i] : {};
5209
- i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
5210
- _defineProperty(target, key, source[key]);
5211
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
5212
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
5213
- });
5214
- }
5215
- return target;
5216
- }
5217
-
5218
- function _classCallCheck(instance, Constructor) {
5219
- if (!(instance instanceof Constructor)) {
5220
- throw new TypeError("Cannot call a class as a function");
5221
- }
5222
- }
5223
-
5224
- function _defineProperties(target, props) {
5225
- for (var i = 0; i < props.length; i++) {
5226
- var descriptor = props[i];
5227
- descriptor.enumerable = descriptor.enumerable || false;
5228
- descriptor.configurable = true;
5229
- if ("value" in descriptor) descriptor.writable = true;
5230
- Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
5231
- }
5232
- }
5233
- function _createClass(Constructor, protoProps, staticProps) {
5234
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
5235
- if (staticProps) _defineProperties(Constructor, staticProps);
5236
- Object.defineProperty(Constructor, "prototype", {
5237
- writable: false
5238
- });
5239
- return Constructor;
5240
- }
5241
-
5242
- function _setPrototypeOf(o, p) {
5243
- _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
5244
- o.__proto__ = p;
5245
- return o;
5246
- };
5247
- return _setPrototypeOf(o, p);
5248
- }
5249
-
5250
- function _inherits(subClass, superClass) {
5251
- if (typeof superClass !== "function" && superClass !== null) {
5252
- throw new TypeError("Super expression must either be null or a function");
5253
- }
5254
- subClass.prototype = Object.create(superClass && superClass.prototype, {
5255
- constructor: {
5256
- value: subClass,
5257
- writable: true,
5258
- configurable: true
5259
- }
5260
- });
5261
- Object.defineProperty(subClass, "prototype", {
5262
- writable: false
5263
- });
5264
- if (superClass) _setPrototypeOf(subClass, superClass);
5265
- }
5266
-
5267
- function _getPrototypeOf(o) {
5268
- _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
5269
- return o.__proto__ || Object.getPrototypeOf(o);
5270
- };
5271
- return _getPrototypeOf(o);
5272
- }
5273
-
5274
- function _isNativeReflectConstruct() {
5275
- if (typeof Reflect === "undefined" || !Reflect.construct) return false;
5276
- if (Reflect.construct.sham) return false;
5277
- if (typeof Proxy === "function") return true;
5278
- try {
5279
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
5280
- return true;
5281
- } catch (e) {
5282
- return false;
5283
- }
5284
- }
5285
-
5286
- function _assertThisInitialized(self) {
5287
- if (self === void 0) {
5288
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
5289
- }
5290
- return self;
5291
- }
5292
-
5293
- function _possibleConstructorReturn(self, call) {
5294
- if (call && (_typeof(call) === "object" || typeof call === "function")) {
5295
- return call;
5296
- } else if (call !== void 0) {
5297
- throw new TypeError("Derived constructors may only return object or undefined");
5298
- }
5299
- return _assertThisInitialized(self);
5300
- }
5301
-
5302
- function _createSuper(Derived) {
5303
- var hasNativeReflectConstruct = _isNativeReflectConstruct();
5304
- return function _createSuperInternal() {
5305
- var Super = _getPrototypeOf(Derived),
5306
- result;
5307
- if (hasNativeReflectConstruct) {
5308
- var NewTarget = _getPrototypeOf(this).constructor;
5309
- result = Reflect.construct(Super, arguments, NewTarget);
5310
- } else {
5311
- result = Super.apply(this, arguments);
5312
- }
5313
- return _possibleConstructorReturn(this, result);
5314
- };
5315
- }
5316
-
5317
- function _arrayLikeToArray(arr, len) {
5318
- if (len == null || len > arr.length) len = arr.length;
5319
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
5320
- return arr2;
5321
- }
5322
-
5323
- function _arrayWithoutHoles(arr) {
5324
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
5325
- }
5326
-
5327
- function _iterableToArray(iter) {
5328
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
5329
- }
5330
-
5331
- function _unsupportedIterableToArray(o, minLen) {
5332
- if (!o) return;
5333
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
5334
- var n = Object.prototype.toString.call(o).slice(8, -1);
5335
- if (n === "Object" && o.constructor) n = o.constructor.name;
5336
- if (n === "Map" || n === "Set") return Array.from(o);
5337
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
5338
- }
5339
-
5340
- function _nonIterableSpread() {
5341
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5342
- }
5343
-
5344
- function _toConsumableArray(arr) {
5345
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
5346
- }
5347
-
5348
- /*
5349
-
5350
- Based off glamor's StyleSheet, thanks Sunil ❤️
5351
-
5352
- high performance StyleSheet for css-in-js systems
5353
-
5354
- - uses multiple style tags behind the scenes for millions of rules
5355
- - uses `insertRule` for appending in production for *much* faster performance
5356
-
5357
- // usage
5358
-
5359
- import { StyleSheet } from '@emotion/sheet'
5360
-
5361
- let styleSheet = new StyleSheet({ key: '', container: document.head })
5362
-
5363
- styleSheet.insert('#box { border: 1px solid red; }')
5364
- - appends a css rule into the stylesheet
5365
-
5366
- styleSheet.flush()
5367
- - empties the stylesheet of all its contents
5368
-
5369
- */
5370
- // $FlowFixMe
5371
- function sheetForTag(tag) {
5372
- if (tag.sheet) {
5373
- // $FlowFixMe
5374
- return tag.sheet;
5375
- } // this weirdness brought to you by firefox
5376
-
5377
- /* istanbul ignore next */
5378
-
5379
-
5380
- for (var i = 0; i < document.styleSheets.length; i++) {
5381
- if (document.styleSheets[i].ownerNode === tag) {
5382
- // $FlowFixMe
5383
- return document.styleSheets[i];
5384
- }
5385
- }
5386
- }
5387
-
5388
- function createStyleElement(options) {
5389
- var tag = document.createElement('style');
5390
- tag.setAttribute('data-emotion', options.key);
5391
-
5392
- if (options.nonce !== undefined) {
5393
- tag.setAttribute('nonce', options.nonce);
5394
- }
5395
-
5396
- tag.appendChild(document.createTextNode(''));
5397
- tag.setAttribute('data-s', '');
5398
- return tag;
5399
- }
5400
-
5401
- var StyleSheet = /*#__PURE__*/function () {
5402
- // Using Node instead of HTMLElement since container may be a ShadowRoot
5403
- function StyleSheet(options) {
5404
- var _this = this;
5405
-
5406
- this._insertTag = function (tag) {
5407
- var before;
5408
-
5409
- if (_this.tags.length === 0) {
5410
- if (_this.insertionPoint) {
5411
- before = _this.insertionPoint.nextSibling;
5412
- } else if (_this.prepend) {
5413
- before = _this.container.firstChild;
5414
- } else {
5415
- before = _this.before;
5416
- }
5417
- } else {
5418
- before = _this.tags[_this.tags.length - 1].nextSibling;
5419
- }
5420
-
5421
- _this.container.insertBefore(tag, before);
5422
-
5423
- _this.tags.push(tag);
5424
- };
5425
-
5426
- this.isSpeedy = options.speedy === undefined ? process.env.NODE_ENV === 'production' : options.speedy;
5427
- this.tags = [];
5428
- this.ctr = 0;
5429
- this.nonce = options.nonce; // key is the value of the data-emotion attribute, it's used to identify different sheets
5430
-
5431
- this.key = options.key;
5432
- this.container = options.container;
5433
- this.prepend = options.prepend;
5434
- this.insertionPoint = options.insertionPoint;
5435
- this.before = null;
5436
- }
5437
-
5438
- var _proto = StyleSheet.prototype;
5439
-
5440
- _proto.hydrate = function hydrate(nodes) {
5441
- nodes.forEach(this._insertTag);
5442
- };
5443
-
5444
- _proto.insert = function insert(rule) {
5445
- // the max length is how many rules we have per style tag, it's 65000 in speedy mode
5446
- // it's 1 in dev because we insert source maps that map a single rule to a location
5447
- // and you can only have one source map per style tag
5448
- if (this.ctr % (this.isSpeedy ? 65000 : 1) === 0) {
5449
- this._insertTag(createStyleElement(this));
5450
- }
5451
-
5452
- var tag = this.tags[this.tags.length - 1];
5453
-
5454
- if (process.env.NODE_ENV !== 'production') {
5455
- var isImportRule = rule.charCodeAt(0) === 64 && rule.charCodeAt(1) === 105;
5456
-
5457
- if (isImportRule && this._alreadyInsertedOrderInsensitiveRule) {
5458
- // this would only cause problem in speedy mode
5459
- // but we don't want enabling speedy to affect the observable behavior
5460
- // so we report this error at all times
5461
- console.error("You're attempting to insert the following rule:\n" + rule + '\n\n`@import` rules must be before all other types of rules in a stylesheet but other rules have already been inserted. Please ensure that `@import` rules are before all other rules.');
5462
- }
5463
- this._alreadyInsertedOrderInsensitiveRule = this._alreadyInsertedOrderInsensitiveRule || !isImportRule;
5464
- }
5465
-
5466
- if (this.isSpeedy) {
5467
- var sheet = sheetForTag(tag);
5468
-
5469
- try {
5470
- // this is the ultrafast version, works across browsers
5471
- // the big drawback is that the css won't be editable in devtools
5472
- sheet.insertRule(rule, sheet.cssRules.length);
5473
- } catch (e) {
5474
- if (process.env.NODE_ENV !== 'production' && !/:(-moz-placeholder|-moz-focus-inner|-moz-focusring|-ms-input-placeholder|-moz-read-write|-moz-read-only|-ms-clear|-ms-expand|-ms-reveal){/.test(rule)) {
5475
- console.error("There was a problem inserting the following rule: \"" + rule + "\"", e);
5476
- }
5477
- }
5478
- } else {
5479
- tag.appendChild(document.createTextNode(rule));
5480
- }
5481
-
5482
- this.ctr++;
5483
- };
5484
-
5485
- _proto.flush = function flush() {
5486
- // $FlowFixMe
5487
- this.tags.forEach(function (tag) {
5488
- return tag.parentNode && tag.parentNode.removeChild(tag);
5489
- });
5490
- this.tags = [];
5491
- this.ctr = 0;
5492
-
5493
- if (process.env.NODE_ENV !== 'production') {
5494
- this._alreadyInsertedOrderInsensitiveRule = false;
5495
- }
5496
- };
5497
-
5498
- return StyleSheet;
5499
- }();
5500
-
5501
- var MS = '-ms-';
5502
- var MOZ = '-moz-';
5503
- var WEBKIT = '-webkit-';
5504
-
5505
- var COMMENT = 'comm';
5506
- var RULESET = 'rule';
5507
- var DECLARATION = 'decl';
5508
- var IMPORT = '@import';
5509
- var KEYFRAMES = '@keyframes';
5510
- var LAYER = '@layer';
5511
-
5512
- /**
5513
- * @param {number}
5514
- * @return {number}
5515
- */
5516
- var abs = Math.abs;
5517
-
5518
- /**
5519
- * @param {number}
5520
- * @return {string}
5521
- */
5522
- var from = String.fromCharCode;
5523
-
5524
- /**
5525
- * @param {object}
5526
- * @return {object}
5527
- */
5528
- var assign = Object.assign;
5529
-
5530
- /**
5531
- * @param {string} value
5532
- * @param {number} length
5533
- * @return {number}
5534
- */
5535
- function hash (value, length) {
5536
- return charat(value, 0) ^ 45 ? (((((((length << 2) ^ charat(value, 0)) << 2) ^ charat(value, 1)) << 2) ^ charat(value, 2)) << 2) ^ charat(value, 3) : 0
5537
- }
5538
-
5539
- /**
5540
- * @param {string} value
5541
- * @return {string}
5542
- */
5543
- function trim (value) {
5544
- return value.trim()
5545
- }
5546
-
5547
- /**
5548
- * @param {string} value
5549
- * @param {RegExp} pattern
5550
- * @return {string?}
5551
- */
5552
- function match (value, pattern) {
5553
- return (value = pattern.exec(value)) ? value[0] : value
5554
- }
5555
-
5556
- /**
5557
- * @param {string} value
5558
- * @param {(string|RegExp)} pattern
5559
- * @param {string} replacement
5560
- * @return {string}
5561
- */
5562
- function replace (value, pattern, replacement) {
5563
- return value.replace(pattern, replacement)
5564
- }
5565
-
5566
- /**
5567
- * @param {string} value
5568
- * @param {string} search
5569
- * @return {number}
5570
- */
5571
- function indexof (value, search) {
5572
- return value.indexOf(search)
5573
- }
5574
-
5575
- /**
5576
- * @param {string} value
5577
- * @param {number} index
5578
- * @return {number}
4613
+ * @param {string} value
4614
+ * @param {number} index
4615
+ * @return {number}
5579
4616
  */
5580
4617
  function charat (value, index) {
5581
4618
  return value.charCodeAt(index) | 0
@@ -40428,11 +39465,11 @@ var CreatableSelect$1 = CreatableSelect;
40428
39465
  // Import React
40429
39466
  /* ------------- Actions ------------ */
40430
39467
  // Types of actions
40431
- var ActionType$2;
39468
+ var ActionType$4;
40432
39469
  (function (ActionType) {
40433
39470
  // Update the input value
40434
39471
  ActionType["SetInputValue"] = "SetInputValue";
40435
- })(ActionType$2 || (ActionType$2 = {}));
39472
+ })(ActionType$4 || (ActionType$4 = {}));
40436
39473
  /**
40437
39474
  * Reducer that executes actions
40438
39475
  * @author Yuen Ler Chow
@@ -40441,7 +39478,7 @@ var ActionType$2;
40441
39478
  */
40442
39479
  const reducer$2 = (state, action) => {
40443
39480
  switch (action.type) {
40444
- case ActionType$2.SetInputValue: {
39481
+ case ActionType$4.SetInputValue: {
40445
39482
  return Object.assign(Object.assign({}, state), { inputValue: action.value });
40446
39483
  }
40447
39484
  default: {
@@ -40532,7 +39569,7 @@ const CreatableMultiselect = (props) => {
40532
39569
  }
40533
39570
  // resets text field to empty because the values have been added
40534
39571
  dispatch({
40535
- type: ActionType$2.SetInputValue,
39572
+ type: ActionType$4.SetInputValue,
40536
39573
  value: '',
40537
39574
  });
40538
39575
  };
@@ -40571,7 +39608,7 @@ const CreatableMultiselect = (props) => {
40571
39608
  else {
40572
39609
  // simply update the input value to the new input value
40573
39610
  dispatch({
40574
- type: ActionType$2.SetInputValue,
39611
+ type: ActionType$4.SetInputValue,
40575
39612
  value: newValue,
40576
39613
  });
40577
39614
  }
@@ -40622,13 +39659,13 @@ const style = `
40622
39659
  `;
40623
39660
  /* ------------- Actions ------------ */
40624
39661
  // Types of actions
40625
- var ActionType$1;
39662
+ var ActionType$3;
40626
39663
  (function (ActionType) {
40627
39664
  // Update the DBEntry
40628
39665
  ActionType["UpdateDBEntry"] = "UpdateDBEntry";
40629
39666
  // Start the save spinner
40630
39667
  ActionType["StartSave"] = "StartSave";
40631
- })(ActionType$1 || (ActionType$1 = {}));
39668
+ })(ActionType$3 || (ActionType$3 = {}));
40632
39669
  /**
40633
39670
  * Reducer that executes actions
40634
39671
  * @author Yuen Ler Chow
@@ -40637,10 +39674,10 @@ var ActionType$1;
40637
39674
  */
40638
39675
  const reducer$1 = (state, action) => {
40639
39676
  switch (action.type) {
40640
- case ActionType$1.UpdateDBEntry: {
39677
+ case ActionType$3.UpdateDBEntry: {
40641
39678
  return Object.assign(Object.assign({}, state), { entry: action.dbEntry });
40642
39679
  }
40643
- case ActionType$1.StartSave: {
39680
+ case ActionType$3.StartSave: {
40644
39681
  return Object.assign(Object.assign({}, state), { saving: true });
40645
39682
  }
40646
39683
  default: {
@@ -40677,7 +39714,7 @@ const AddOrEditDBEntry = (props) => {
40677
39714
  */
40678
39715
  const save = () => __awaiter$1(void 0, void 0, void 0, function* () {
40679
39716
  // Start the save loading indicator
40680
- dispatch({ type: ActionType$1.StartSave });
39717
+ dispatch({ type: ActionType$3.StartSave });
40681
39718
  // add all default values to the entry
40682
39719
  entryFields.forEach((field) => {
40683
39720
  if (field.defaultValue && !entry[field.objectKey]) {
@@ -40838,7 +39875,7 @@ const AddOrEditDBEntry = (props) => {
40838
39875
  return (React__default["default"].createElement(RadioButton, { key: choice.value, text: choice.title, selected: entry[field.objectKey] === choice.value, onSelected: () => {
40839
39876
  entry[field.objectKey] = choice.value;
40840
39877
  dispatch({
40841
- type: ActionType$1.UpdateDBEntry,
39878
+ type: ActionType$3.UpdateDBEntry,
40842
39879
  dbEntry: entry,
40843
39880
  });
40844
39881
  }, ariaLabel: choice.title }));
@@ -40850,7 +39887,7 @@ const AddOrEditDBEntry = (props) => {
40850
39887
  React__default["default"].createElement("input", { disabled: disabled, type: "text", className: "form-control", placeholder: field.placeholder, "aria-describedby": "AddOrEditDBEntry-form-name-label", value: entry[field.objectKey] || '', onChange: (e) => {
40851
39888
  entry[field.objectKey] = (e.target.value);
40852
39889
  dispatch({
40853
- type: ActionType$1.UpdateDBEntry,
39890
+ type: ActionType$3.UpdateDBEntry,
40854
39891
  dbEntry: entry,
40855
39892
  });
40856
39893
  } }))));
@@ -40863,7 +39900,7 @@ const AddOrEditDBEntry = (props) => {
40863
39900
  entry[field.objectKey] = (e.target.value
40864
39901
  .replace(/[^0-9]/g, ''));
40865
39902
  dispatch({
40866
- type: ActionType$1.UpdateDBEntry,
39903
+ type: ActionType$3.UpdateDBEntry,
40867
39904
  dbEntry: entry,
40868
39905
  });
40869
39906
  } }))));
@@ -40893,7 +39930,7 @@ const AddOrEditDBEntry = (props) => {
40893
39930
  }
40894
39931
  // Save
40895
39932
  dispatch({
40896
- type: ActionType$1.UpdateDBEntry,
39933
+ type: ActionType$3.UpdateDBEntry,
40897
39934
  dbEntry: entry,
40898
39935
  });
40899
39936
  }, ariaLabel: choice.title }));
@@ -40908,7 +39945,7 @@ const AddOrEditDBEntry = (props) => {
40908
39945
  // Update entry and save
40909
39946
  entry[field.objectKey] = values;
40910
39947
  dispatch({
40911
- type: ActionType$1.UpdateDBEntry,
39948
+ type: ActionType$3.UpdateDBEntry,
40912
39949
  dbEntry: entry,
40913
39950
  });
40914
39951
  } })))));
@@ -40921,7 +39958,7 @@ const AddOrEditDBEntry = (props) => {
40921
39958
  React__default["default"].createElement(CreatableMultiselect, { disabled: disabled, type: DBEntryFieldType$1.NumberArray, values: entry[field.objectKey] || [], onChange: (values) => {
40922
39959
  entry[field.objectKey] = values;
40923
39960
  dispatch({
40924
- type: ActionType$1.UpdateDBEntry,
39961
+ type: ActionType$3.UpdateDBEntry,
40925
39962
  dbEntry: entry,
40926
39963
  });
40927
39964
  } })))));
@@ -40976,6 +40013,7 @@ const AddOrEditDBEntry = (props) => {
40976
40013
  * @author Yuen Ler Chow
40977
40014
  * @param collectionName the name of the collection
40978
40015
  * @param [adminsOnly] true if the endpoint is for admins only
40016
+ * @returns the endpoint path
40979
40017
  */
40980
40018
  const generateEndpointPath = (collectionName, adminsOnly) => {
40981
40019
  // Determine prefix based on whether the endpoint is for admins only
@@ -40990,7 +40028,7 @@ const generateEndpointPath = (collectionName, adminsOnly) => {
40990
40028
  */
40991
40029
  /* ------------- Actions ------------ */
40992
40030
  // Types of actions
40993
- var ActionType;
40031
+ var ActionType$2;
40994
40032
  (function (ActionType) {
40995
40033
  // Show adder
40996
40034
  ActionType["ShowAdder"] = "ShowAdder";
@@ -41004,7 +40042,7 @@ var ActionType;
41004
40042
  ActionType["StartDelete"] = "StartDelete";
41005
40043
  // Finish deletion process
41006
40044
  ActionType["FinishDelete"] = "FinishDelete";
41007
- })(ActionType || (ActionType = {}));
40045
+ })(ActionType$2 || (ActionType$2 = {}));
41008
40046
  /**
41009
40047
  * Reducer that executes actions
41010
40048
  * @author Yuen Ler Chow
@@ -41013,16 +40051,16 @@ var ActionType;
41013
40051
  */
41014
40052
  const reducer = (state, action) => {
41015
40053
  switch (action.type) {
41016
- case ActionType.FinishLoading: {
40054
+ case ActionType$2.FinishLoading: {
41017
40055
  return Object.assign(Object.assign({}, state), { loading: false, dbEntries: action.dbEntries });
41018
40056
  }
41019
- case ActionType.ShowAdder: {
40057
+ case ActionType$2.ShowAdder: {
41020
40058
  return Object.assign(Object.assign({}, state), { adding: true, dbEntryToEdit: undefined });
41021
40059
  }
41022
- case ActionType.ShowEditor: {
40060
+ case ActionType$2.ShowEditor: {
41023
40061
  return Object.assign(Object.assign({}, state), { adding: false, dbEntryToEdit: action.dbEntry });
41024
40062
  }
41025
- case ActionType.FinishAdd: {
40063
+ case ActionType$2.FinishAdd: {
41026
40064
  // Handle cancel
41027
40065
  const finishedEntry = action.dbEntry;
41028
40066
  if (!finishedEntry) {
@@ -41046,10 +40084,10 @@ const reducer = (state, action) => {
41046
40084
  // Update the state
41047
40085
  return Object.assign(Object.assign({}, state), { adding: false, dbEntryToEdit: undefined, dbEntries: updatedDbEntries });
41048
40086
  }
41049
- case ActionType.StartDelete: {
40087
+ case ActionType$2.StartDelete: {
41050
40088
  return Object.assign(Object.assign({}, state), { loading: true });
41051
40089
  }
41052
- case ActionType.FinishDelete: {
40090
+ case ActionType$2.FinishDelete: {
41053
40091
  return Object.assign(Object.assign({}, state), { loading: false,
41054
40092
  // Remove the deleted entry from the list
41055
40093
  dbEntries: state.dbEntries.filter((entry) => {
@@ -41101,22 +40139,22 @@ const DBEntryManagerPanel = (props) => {
41101
40139
  try {
41102
40140
  // Start loader
41103
40141
  dispatch({
41104
- type: ActionType.StartDelete,
40142
+ type: ActionType$2.StartDelete,
41105
40143
  });
41106
40144
  // Perform deletion
41107
- yield visitServerEndpoint$1({
40145
+ yield visitServerEndpoint({
41108
40146
  path: `${endpoint}/${entry[idPropName]}`,
41109
40147
  method: 'DELETE',
41110
40148
  });
41111
40149
  // Finish loader
41112
40150
  dispatch({
41113
- type: ActionType.FinishDelete,
40151
+ type: ActionType$2.FinishDelete,
41114
40152
  dbEntry: entry,
41115
40153
  idPropName,
41116
40154
  });
41117
40155
  }
41118
40156
  catch (err) {
41119
- return showFatalError$1(err);
40157
+ return showFatalError(err);
41120
40158
  }
41121
40159
  });
41122
40160
  /*------------------------------------------------------------------------*/
@@ -41130,7 +40168,7 @@ const DBEntryManagerPanel = (props) => {
41130
40168
  (() => __awaiter$1(void 0, void 0, void 0, function* () {
41131
40169
  // Load list of database entries
41132
40170
  try {
41133
- const data = yield visitServerEndpoint$1({
40171
+ const data = yield visitServerEndpoint({
41134
40172
  path: endpoint,
41135
40173
  method: 'GET',
41136
40174
  params: {
@@ -41139,12 +40177,12 @@ const DBEntryManagerPanel = (props) => {
41139
40177
  });
41140
40178
  // Save loaded data
41141
40179
  dispatch({
41142
- type: ActionType.FinishLoading,
40180
+ type: ActionType$2.FinishLoading,
41143
40181
  dbEntries: data,
41144
40182
  });
41145
40183
  }
41146
40184
  catch (err) {
41147
- return showFatalError$1(err);
40185
+ return showFatalError(err);
41148
40186
  }
41149
40187
  }))();
41150
40188
  }, []);
@@ -41157,7 +40195,7 @@ const DBEntryManagerPanel = (props) => {
41157
40195
  let body;
41158
40196
  /* ------------- Loading ------------ */
41159
40197
  if (loading) {
41160
- body = (React__default["default"].createElement(LoadingSpinner$1, null));
40198
+ body = (React__default["default"].createElement(LoadingSpinner, null));
41161
40199
  }
41162
40200
  /* ------------- List of entries ------------ */
41163
40201
  if (!loading && !adding && !dbEntryToEdit) {
@@ -41182,7 +40220,7 @@ const DBEntryManagerPanel = (props) => {
41182
40220
  React__default["default"].createElement("span", { className: "d-none d-md-inline ms-1" }, "Remove")),
41183
40221
  !disableEdit && (React__default["default"].createElement("button", { type: "button", id: `DBEntryManagerPanel-edit-with-id-${entry[idPropName]}`, className: "btn btn-primary", "aria-label": `edit db entry: ${entry[titlePropName]}`, onClick: () => {
41184
40222
  dispatch({
41185
- type: ActionType.ShowEditor,
40223
+ type: ActionType$2.ShowEditor,
41186
40224
  dbEntry: entry,
41187
40225
  });
41188
40226
  } },
@@ -41192,7 +40230,7 @@ const DBEntryManagerPanel = (props) => {
41192
40230
  React__default["default"].createElement("div", { className: "d-grid" },
41193
40231
  React__default["default"].createElement("button", { type: "button", id: "DBEntryManagerPanel-add-entry", className: "btn btn-lg btn-primary", "aria-label": `add a new ${itemName} entry to the list of entries`, onClick: () => {
41194
40232
  dispatch({
41195
- type: ActionType.ShowAdder,
40233
+ type: ActionType$2.ShowAdder,
41196
40234
  });
41197
40235
  } },
41198
40236
  React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faPlus, className: "me-2" }),
@@ -41204,7 +40242,7 @@ const DBEntryManagerPanel = (props) => {
41204
40242
  if (!loading && (adding || dbEntryToEdit)) {
41205
40243
  body = (React__default["default"].createElement(AddOrEditDBEntry, { saveEndpointPath: endpoint, validateEntry: validateEntry, modifyEntry: modifyEntry, entryFields: entryFields, dbEntryToEdit: dbEntryToEdit, idPropName: idPropName, entries: dbEntries, onFinished: (entry) => {
41206
40244
  dispatch({
41207
- type: ActionType.FinishAdd,
40245
+ type: ActionType$2.FinishAdd,
41208
40246
  dbEntry: entry,
41209
40247
  idPropName,
41210
40248
  });
@@ -41427,7 +40465,7 @@ const padZerosLeft = (num, numDigits) => {
41427
40465
  const LOG_REVIEW_STATUS_ROUTE = `${ROUTE_PATH_PREFIX}/logs/access_allowed`;
41428
40466
 
41429
40467
  // Stored copy of caccl functions
41430
- let _cacclGetLaunchInfo;
40468
+ let _cacclGetLaunchInfo$1;
41431
40469
  // Stored copy of dce-mango log collection
41432
40470
  let _logCollection;
41433
40471
  /*------------------------------------------------------------------------*/
@@ -41439,11 +40477,11 @@ let _logCollection;
41439
40477
  * @param req express request object
41440
40478
  * @returns object { launched, launchInfo }
41441
40479
  */
41442
- const cacclGetLaunchInfo = (req) => {
41443
- if (!_cacclGetLaunchInfo) {
40480
+ const cacclGetLaunchInfo$1 = (req) => {
40481
+ if (!_cacclGetLaunchInfo$1) {
41444
40482
  throw new ErrorWithCode$1('Could not get launch info because server was not initialized with dce-reactkit\'s initServer function', ReactKitErrorCode$3.NoCACCLGetLaunchInfoFunction);
41445
40483
  }
41446
- return _cacclGetLaunchInfo(req);
40484
+ return _cacclGetLaunchInfo$1(req);
41447
40485
  };
41448
40486
  /**
41449
40487
  * Get log collection
@@ -41475,7 +40513,7 @@ const internalGetLogCollection = () => {
41475
40513
  * to review logs
41476
40514
  */
41477
40515
  const initServer = (opts) => {
41478
- _cacclGetLaunchInfo = opts.getLaunchInfo;
40516
+ _cacclGetLaunchInfo$1 = opts.getLaunchInfo;
41479
40517
  _logCollection = opts.logCollection;
41480
40518
  /*----------------------------------------*/
41481
40519
  /* Logging */
@@ -41499,7 +40537,7 @@ const initServer = (opts) => {
41499
40537
  * @param {LogAction} [action] the type of action performed on the target
41500
40538
  * @returns {Log}
41501
40539
  */
41502
- opts.app.post(LOG_ROUTE_PATH, genRouteHandler({
40540
+ opts.app.post(LOG_ROUTE_PATH, genRouteHandler$1({
41503
40541
  paramTypes: {
41504
40542
  context: ParamType$3.String,
41505
40543
  subcontext: ParamType$3.String,
@@ -41588,7 +40626,7 @@ const initServer = (opts) => {
41588
40626
  * @author Gabe Abrams
41589
40627
  * @returns {boolean} true if user has access
41590
40628
  */
41591
- opts.app.get(LOG_REVIEW_STATUS_ROUTE, genRouteHandler({
40629
+ opts.app.get(LOG_REVIEW_STATUS_ROUTE, genRouteHandler$1({
41592
40630
  handler: ({ params }) => __awaiter$1(void 0, void 0, void 0, function* () {
41593
40631
  const { userId, isAdmin } = params;
41594
40632
  const canReview = yield canReviewLogs(userId, isAdmin);
@@ -41602,7 +40640,7 @@ const initServer = (opts) => {
41602
40640
  * @param {number} month the month to query (e.g. 1 = January)
41603
40641
  * @returns {Log[]} list of logs from the given month
41604
40642
  */
41605
- opts.app.get(`${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`, genRouteHandler({
40643
+ opts.app.get(`${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`, genRouteHandler$1({
41606
40644
  paramTypes: {
41607
40645
  year: ParamType$3.Int,
41608
40646
  month: ParamType$3.Int,
@@ -41639,7 +40677,7 @@ const initServer = (opts) => {
41639
40677
  * @param [opts.status=500] the https status code to use
41640
40678
  * defined)
41641
40679
  */
41642
- const handleError = (res, error) => {
40680
+ const handleError$1 = (res, error) => {
41643
40681
  // Get the error message
41644
40682
  let message;
41645
40683
  if (error && error.message) {
@@ -41679,7 +40717,7 @@ const handleError = (res, error) => {
41679
40717
  * @param res express response
41680
40718
  * @param body the body of the response to send to the client
41681
40719
  */
41682
- const handleSuccess = (res, body) => {
40720
+ const handleSuccess$1 = (res, body) => {
41683
40721
  // Send a http 200 json response
41684
40722
  res.json({
41685
40723
  // Include the body as a parameter
@@ -41945,7 +40983,7 @@ const parseUserAgent = (userAgent) => {
41945
40983
  * userLastName, isLearner, isTTM, isAdmin, and any other variables that
41946
40984
  * are directly added to the session, if the user does have a session.
41947
40985
  */
41948
- const genRouteHandler = (opts) => {
40986
+ const genRouteHandler$1 = (opts) => {
41949
40987
  // Return a route handler
41950
40988
  return (req, res, next) => __awaiter$1(void 0, void 0, void 0, function* () {
41951
40989
  var _a, _b;
@@ -41971,7 +41009,7 @@ const genRouteHandler = (opts) => {
41971
41009
  output[name] = undefined;
41972
41010
  }
41973
41011
  else {
41974
- return handleError(res, {
41012
+ return handleError$1(res, {
41975
41013
  message: `Parameter ${name} is required, but it was not included.`,
41976
41014
  code: ReactKitErrorCode$3.MissingParameter,
41977
41015
  status: 422,
@@ -42002,7 +41040,7 @@ const genRouteHandler = (opts) => {
42002
41040
  output[name] = undefined;
42003
41041
  }
42004
41042
  else {
42005
- return handleError(res, {
41043
+ return handleError$1(res, {
42006
41044
  message: `Parameter ${name} is required, but it was not included.`,
42007
41045
  code: ReactKitErrorCode$3.MissingParameter,
42008
41046
  status: 422,
@@ -42015,7 +41053,7 @@ const genRouteHandler = (opts) => {
42015
41053
  }
42016
41054
  else {
42017
41055
  // Issue!
42018
- return handleError(res, {
41056
+ return handleError$1(res, {
42019
41057
  message: `Request data was malformed: ${name} was not a valid float.`,
42020
41058
  code: ReactKitErrorCode$3.InvalidParameter,
42021
41059
  status: 422,
@@ -42030,7 +41068,7 @@ const genRouteHandler = (opts) => {
42030
41068
  output[name] = undefined;
42031
41069
  }
42032
41070
  else {
42033
- return handleError(res, {
41071
+ return handleError$1(res, {
42034
41072
  message: `Parameter ${name} is required, but it was not included.`,
42035
41073
  code: ReactKitErrorCode$3.MissingParameter,
42036
41074
  status: 422,
@@ -42043,7 +41081,7 @@ const genRouteHandler = (opts) => {
42043
41081
  }
42044
41082
  else {
42045
41083
  // Issue!
42046
- return handleError(res, {
41084
+ return handleError$1(res, {
42047
41085
  message: `Request data was malformed: ${name} was not a valid int.`,
42048
41086
  code: ReactKitErrorCode$3.InvalidParameter,
42049
41087
  status: 422,
@@ -42058,7 +41096,7 @@ const genRouteHandler = (opts) => {
42058
41096
  output[name] = undefined;
42059
41097
  }
42060
41098
  else {
42061
- return handleError(res, {
41099
+ return handleError$1(res, {
42062
41100
  message: `Parameter ${name} is required, but it was not included.`,
42063
41101
  code: ReactKitErrorCode$3.MissingParameter,
42064
41102
  status: 422,
@@ -42072,7 +41110,7 @@ const genRouteHandler = (opts) => {
42072
41110
  output[name] = JSON.parse(String(value));
42073
41111
  }
42074
41112
  catch (err) {
42075
- return handleError(res, {
41113
+ return handleError$1(res, {
42076
41114
  message: `Request data was malformed: ${name} was not a valid JSON payload.`,
42077
41115
  code: ReactKitErrorCode$3.InvalidParameter,
42078
41116
  status: 422,
@@ -42088,7 +41126,7 @@ const genRouteHandler = (opts) => {
42088
41126
  output[name] = undefined;
42089
41127
  }
42090
41128
  else {
42091
- return handleError(res, {
41129
+ return handleError$1(res, {
42092
41130
  message: `Parameter ${name} is required, but it was not included.`,
42093
41131
  code: ReactKitErrorCode$3.MissingParameter,
42094
41132
  status: 422,
@@ -42103,7 +41141,7 @@ const genRouteHandler = (opts) => {
42103
41141
  }
42104
41142
  else {
42105
41143
  // No valid data type
42106
- return handleError(res, {
41144
+ return handleError$1(res, {
42107
41145
  message: `An internal error occurred: we could not determine the type of ${name}.`,
42108
41146
  code: ReactKitErrorCode$3.InvalidParameter,
42109
41147
  status: 422,
@@ -42114,13 +41152,13 @@ const genRouteHandler = (opts) => {
42114
41152
  /* Launch Info */
42115
41153
  /*----------------------------------------*/
42116
41154
  // Get launch info
42117
- const { launched, launchInfo } = cacclGetLaunchInfo(req);
41155
+ const { launched, launchInfo } = cacclGetLaunchInfo$1(req);
42118
41156
  if (
42119
41157
  // Not launched
42120
41158
  (!launched || !launchInfo)
42121
41159
  // Not skipping the session check
42122
41160
  && !opts.skipSessionCheck) {
42123
- return handleError(res, {
41161
+ return handleError$1(res, {
42124
41162
  message: 'Your session has expired. Please refresh the page and try again.',
42125
41163
  code: ReactKitErrorCode$3.SessionExpired,
42126
41164
  status: 401,
@@ -42140,7 +41178,7 @@ const genRouteHandler = (opts) => {
42140
41178
  && !launchInfo.isAdmin))
42141
41179
  // Not skipping the session check
42142
41180
  && !opts.skipSessionCheck) {
42143
- return handleError(res, {
41181
+ return handleError$1(res, {
42144
41182
  message: 'Your session was invalid. Please refresh the page and try again.',
42145
41183
  code: ReactKitErrorCode$3.SessionExpired,
42146
41184
  status: 401,
@@ -42199,7 +41237,7 @@ const genRouteHandler = (opts) => {
42199
41237
  && !output.isTTM
42200
41238
  && !output.isAdmin) {
42201
41239
  // Course of interest is not the launch course
42202
- return handleError(res, {
41240
+ return handleError$1(res, {
42203
41241
  message: 'You switched sessions by opening this app in another tab. Please refresh the page and try again.',
42204
41242
  code: ReactKitErrorCode$3.WrongCourse,
42205
41243
  status: 401,
@@ -42219,7 +41257,7 @@ const genRouteHandler = (opts) => {
42219
41257
  // User is not an admin
42220
41258
  && !output.isAdmin)) {
42221
41259
  // User does not have access
42222
- return handleError(res, {
41260
+ return handleError$1(res, {
42223
41261
  message: 'This action is only allowed if you are a teaching team member for the course. Please go back to Canvas, log in as a teaching team member, and try again.',
42224
41262
  code: ReactKitErrorCode$3.NotTTM,
42225
41263
  status: 401,
@@ -42232,7 +41270,7 @@ const genRouteHandler = (opts) => {
42232
41270
  // User is not an admin
42233
41271
  && !output.isAdmin) {
42234
41272
  // User does not have access
42235
- return handleError(res, {
41273
+ return handleError$1(res, {
42236
41274
  message: 'This action is only allowed if you are a Canvas admin. Please go back to Canvas, log in as an admin, and try again.',
42237
41275
  code: ReactKitErrorCode$3.NotAdmin,
42238
41276
  status: 401,
@@ -42450,13 +41488,13 @@ const genRouteHandler = (opts) => {
42450
41488
  });
42451
41489
  // Send results to client (only if next wasn't called)
42452
41490
  if (!responseSent) {
42453
- return handleSuccess(res, results !== null && results !== void 0 ? results : undefined);
41491
+ return handleSuccess$1(res, results !== null && results !== void 0 ? results : undefined);
42454
41492
  }
42455
41493
  }
42456
41494
  catch (err) {
42457
41495
  // Send error to client (only if next wasn't called)
42458
41496
  if (!responseSent) {
42459
- handleError(res, err);
41497
+ handleError$1(res, err);
42460
41498
  // Log server-side error
42461
41499
  logServerEvent({
42462
41500
  context: LogBuiltInMetadata.Context.ServerEndpointError,
@@ -42622,143 +41660,786 @@ const parallelLimit = (taskFunctions, limit) => __awaiter$1(void 0, void 0, void
42622
41660
  });
42623
41661
 
42624
41662
  /**
42625
- * Initialize a log collection given the dce-mango Collection class
41663
+ * Initialize a log collection given the dce-mango Collection class
41664
+ * @author Gabe Abrams
41665
+ * @param Collection the Collection class from dce-mango
41666
+ * @returns initialized logCollection
41667
+ */
41668
+ const initLogCollection = (Collection) => {
41669
+ return new Collection('Log', {
41670
+ uniqueIndexKey: 'id',
41671
+ indexKeys: [
41672
+ 'courseId',
41673
+ 'context',
41674
+ 'subcontext',
41675
+ 'tags',
41676
+ ],
41677
+ });
41678
+ };
41679
+
41680
+ // Cache user's ability
41681
+ let canReview = undefined;
41682
+ /**
41683
+ * Check if the current user can review logs
41684
+ * @author Gabe Abrams
41685
+ * @returns true if current user can review logs
41686
+ */
41687
+ const canReviewLogs = () => __awaiter$1(void 0, void 0, void 0, function* () {
41688
+ // If cached, use that value
41689
+ if (canReview !== undefined) {
41690
+ return canReview;
41691
+ }
41692
+ // Ask on server
41693
+ try {
41694
+ canReview = !!(yield visitServerEndpoint({
41695
+ path: LOG_REVIEW_STATUS_ROUTE,
41696
+ method: 'GET',
41697
+ }));
41698
+ }
41699
+ catch (err) {
41700
+ canReview = false;
41701
+ }
41702
+ return canReview;
41703
+ });
41704
+
41705
+ /**
41706
+ * For every element in an array, extract the value of a prop
41707
+ * (e.g. for all user objects, extract their ages and put that into a new
41708
+ * ages array)
41709
+ * @author Gabe Abrams
41710
+ * @param arr the array of objects to operate on
41711
+ * @param prop the property to extract from each object
41712
+ * @returns new array containing the corresponding values, in order, of each
41713
+ * object in the original array
41714
+ */
41715
+ const extractProp = (arr, prop) => {
41716
+ return arr.map((item) => {
41717
+ return item[prop];
41718
+ });
41719
+ };
41720
+
41721
+ // Import shared helpers
41722
+ /**
41723
+ * Compare two arrays of objects by only comparing the values in a specific
41724
+ * property (e.g. compare user arrays by comparing their user.id values)
41725
+ * @author Gabe Abrams
41726
+ * @param a the first array
41727
+ * @param b the second array
41728
+ * @param prop the property to compare with
41729
+ * @returns true if the arrays contain the same objects as determined by
41730
+ * the values associated with each object's prop
41731
+ */
41732
+ const compareArraysByProp = (a, b, prop) => {
41733
+ // Extract values for comparison
41734
+ const aVals = new Set(extractProp(a, prop));
41735
+ const bVals = new Set(extractProp(b, prop));
41736
+ // Compare sizes first
41737
+ if (aVals.size !== bVals.size) {
41738
+ return false;
41739
+ }
41740
+ // Same number of items. Make sure every object in aVals appears in bVals
41741
+ // (if so, they should be equivalent since the sizes are the same)
41742
+ // > Create map of items in bVals
41743
+ const inBVals = {}; // item => true if in bVals
41744
+ Array.from(bVals.values()).forEach((item) => {
41745
+ inBVals[item] = true;
41746
+ });
41747
+ // > Loop through aVals and make sure every item is in bVals
41748
+ return Array.from(aVals.values()).every((item) => {
41749
+ return inBVals[item];
41750
+ });
41751
+ };
41752
+
41753
+ /**
41754
+ * Get current time info in local time
41755
+ * @author Gabe Abrams
41756
+ * @param [dateOrTimestamp=now] the date to get info on or a ms since epoch timestamp
41757
+ * @returns object with timestamp (ms since epoch) and numbers
41758
+ * corresponding to time values for year, month, day, hour, hour12, minute, isPM
41759
+ * where hour is in 24hr time and hour12 is in 12hr time.
41760
+ */
41761
+ const getLocalTimeInfo = (dateOrTimestamp) => {
41762
+ // Create a time string
41763
+ let d;
41764
+ if (!dateOrTimestamp) {
41765
+ // Use now
41766
+ d = new Date();
41767
+ }
41768
+ else if (typeof dateOrTimestamp === 'number') {
41769
+ // Convert to date
41770
+ d = new Date(dateOrTimestamp);
41771
+ }
41772
+ else {
41773
+ // Already a date
41774
+ d = dateOrTimestamp;
41775
+ }
41776
+ // Create all time numbers
41777
+ const timestamp = d.getTime();
41778
+ const year = d.getFullYear();
41779
+ const month = d.getMonth() + 1;
41780
+ const day = d.getDate();
41781
+ const hour = d.getHours();
41782
+ const isPM = hour >= 12;
41783
+ let hour12 = hour % 12;
41784
+ if (hour12 === 0) {
41785
+ hour12 = 12;
41786
+ }
41787
+ const minute = d.getMinutes();
41788
+ // Return
41789
+ return {
41790
+ timestamp,
41791
+ year,
41792
+ month,
41793
+ day,
41794
+ hour,
41795
+ hour12,
41796
+ isPM,
41797
+ minute,
41798
+ };
41799
+ };
41800
+
41801
+ /******************************************************************************
41802
+ Copyright (c) Microsoft Corporation.
41803
+
41804
+ Permission to use, copy, modify, and/or distribute this software for any
41805
+ purpose with or without fee is hereby granted.
41806
+
41807
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
41808
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
41809
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
41810
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
41811
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
41812
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41813
+ PERFORMANCE OF THIS SOFTWARE.
41814
+ ***************************************************************************** */
41815
+
41816
+ function __awaiter(thisArg, _arguments, P, generator) {
41817
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
41818
+ return new (P || (P = Promise))(function (resolve, reject) {
41819
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
41820
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41821
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41822
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
41823
+ });
41824
+ }
41825
+
41826
+ // Highest error code = DRK10
41827
+ /**
41828
+ * List of error codes built into the react kit
41829
+ * @author Gabe Abrams
41830
+ */
41831
+ var ReactKitErrorCode;
41832
+ (function (ReactKitErrorCode) {
41833
+ ReactKitErrorCode["NoResponse"] = "DRK1";
41834
+ ReactKitErrorCode["NoCode"] = "DRK2";
41835
+ ReactKitErrorCode["SessionExpired"] = "DRK3";
41836
+ ReactKitErrorCode["MissingParameter"] = "DRK4";
41837
+ ReactKitErrorCode["InvalidParameter"] = "DRK5";
41838
+ ReactKitErrorCode["WrongCourse"] = "DRK6";
41839
+ ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
41840
+ ReactKitErrorCode["NoCACCLGetLaunchInfoFunction"] = "DRK8";
41841
+ ReactKitErrorCode["NotTTM"] = "DRK9";
41842
+ ReactKitErrorCode["NotAdmin"] = "DRK10";
41843
+ })(ReactKitErrorCode || (ReactKitErrorCode = {}));
41844
+ var ReactKitErrorCode$1 = ReactKitErrorCode;
41845
+
41846
+ /**
41847
+ * Types of buttons in the modal
41848
+ * @author Gabe Abrams
41849
+ */
41850
+ var ModalButtonType;
41851
+ (function (ModalButtonType) {
41852
+ ModalButtonType["Okay"] = "okay";
41853
+ ModalButtonType["Cancel"] = "cancel";
41854
+ ModalButtonType["Yes"] = "yes";
41855
+ ModalButtonType["No"] = "no";
41856
+ ModalButtonType["Abandon"] = "abandon";
41857
+ ModalButtonType["GoBack"] = "goBack";
41858
+ ModalButtonType["Continue"] = "continue";
41859
+ ModalButtonType["ImSure"] = "imSure";
41860
+ ModalButtonType["Delete"] = "delete";
41861
+ ModalButtonType["Confirm"] = "confirm";
41862
+ })(ModalButtonType || (ModalButtonType = {}));
41863
+ var ModalButtonType$1 = ModalButtonType;
41864
+
41865
+ /**
41866
+ * Types of modals
41867
+ * @author Gabe Abrams
41868
+ */
41869
+ var ModalType;
41870
+ (function (ModalType) {
41871
+ ModalType["Okay"] = "okay";
41872
+ ModalType["OkayCancel"] = "okay-cancel";
41873
+ ModalType["YesNo"] = "yes-no";
41874
+ ModalType["YesNoCancel"] = "yes-no-cancel";
41875
+ ModalType["AbandonGoBack"] = "abandon-goBack";
41876
+ ModalType["ImSureCancel"] = "imSure-cancel";
41877
+ ModalType["DeleteCancel"] = "delete-cancel";
41878
+ ModalType["ConfirmCancel"] = "confirm-cancel";
41879
+ ModalType["NoButtons"] = "-";
41880
+ })(ModalType || (ModalType = {}));
41881
+ var ModalType$1 = ModalType;
41882
+
41883
+ /**
41884
+ * Bootstrap variants
41885
+ * @author Gabe Abrams
41886
+ */
41887
+ var Variant;
41888
+ (function (Variant) {
41889
+ Variant["Primary"] = "primary";
41890
+ Variant["Secondary"] = "secondary";
41891
+ Variant["Success"] = "success";
41892
+ Variant["Warning"] = "warning";
41893
+ Variant["Info"] = "info";
41894
+ Variant["Danger"] = "danger";
41895
+ Variant["Light"] = "light";
41896
+ Variant["Dark"] = "dark";
41897
+ })(Variant || (Variant = {}));
41898
+ var Variant$1 = Variant;
41899
+
41900
+ /**
41901
+ * Modal sizes
41902
+ * @author Gabe Abrams
41903
+ */
41904
+ var ModalSize;
41905
+ (function (ModalSize) {
41906
+ ModalSize["Small"] = "sm";
41907
+ ModalSize["Medium"] = "md";
41908
+ ModalSize["Large"] = "lg";
41909
+ ModalSize["ExtraLarge"] = "xl";
41910
+ })(ModalSize || (ModalSize = {}));
41911
+ // Modal type to list of buttons
41912
+ ({
41913
+ [ModalType$1.Okay]: [
41914
+ ModalButtonType$1.Okay,
41915
+ ],
41916
+ [ModalType$1.OkayCancel]: [
41917
+ ModalButtonType$1.Okay,
41918
+ ModalButtonType$1.Cancel,
41919
+ ],
41920
+ [ModalType$1.YesNo]: [
41921
+ ModalButtonType$1.Yes,
41922
+ ModalButtonType$1.No,
41923
+ ],
41924
+ [ModalType$1.YesNoCancel]: [
41925
+ ModalButtonType$1.Yes,
41926
+ ModalButtonType$1.No,
41927
+ ModalButtonType$1.Cancel,
41928
+ ],
41929
+ [ModalType$1.AbandonGoBack]: [
41930
+ ModalButtonType$1.Abandon,
41931
+ ModalButtonType$1.GoBack,
41932
+ ],
41933
+ [ModalType$1.ImSureCancel]: [
41934
+ ModalButtonType$1.ImSure,
41935
+ ModalButtonType$1.Cancel,
41936
+ ],
41937
+ [ModalType$1.DeleteCancel]: [
41938
+ ModalButtonType$1.Delete,
41939
+ ModalButtonType$1.Cancel,
41940
+ ],
41941
+ [ModalType$1.ConfirmCancel]: [
41942
+ ModalButtonType$1.Confirm,
41943
+ ModalButtonType$1.Cancel,
41944
+ ],
41945
+ });
41946
+ // Button type styling and labels
41947
+ ({
41948
+ [ModalButtonType$1.Okay]: {
41949
+ label: 'Okay',
41950
+ variant: Variant$1.Dark,
41951
+ },
41952
+ [ModalButtonType$1.Cancel]: {
41953
+ label: 'Cancel',
41954
+ variant: Variant$1.Secondary,
41955
+ },
41956
+ [ModalButtonType$1.Yes]: {
41957
+ label: 'Yes',
41958
+ variant: Variant$1.Dark,
41959
+ },
41960
+ [ModalButtonType$1.No]: {
41961
+ label: 'No',
41962
+ variant: Variant$1.Secondary,
41963
+ },
41964
+ [ModalButtonType$1.Abandon]: {
41965
+ label: 'Abandon Changes',
41966
+ variant: Variant$1.Warning,
41967
+ },
41968
+ [ModalButtonType$1.GoBack]: {
41969
+ label: 'Go Back',
41970
+ variant: Variant$1.Secondary,
41971
+ },
41972
+ [ModalButtonType$1.Continue]: {
41973
+ label: 'Continue',
41974
+ variant: Variant$1.Dark,
41975
+ },
41976
+ [ModalButtonType$1.ImSure]: {
41977
+ label: 'I am sure',
41978
+ variant: Variant$1.Warning,
41979
+ },
41980
+ [ModalButtonType$1.Delete]: {
41981
+ label: 'Yes, Delete',
41982
+ variant: Variant$1.Danger,
41983
+ },
41984
+ [ModalButtonType$1.Confirm]: {
41985
+ label: 'Confirm',
41986
+ variant: Variant$1.Dark,
41987
+ },
41988
+ });
41989
+
41990
+ /**
41991
+ * An error with a code
41992
+ * @author Gabe Abrams
41993
+ */
41994
+ class ErrorWithCode extends Error {
41995
+ constructor(message, code) {
41996
+ super(message);
41997
+ this.name = 'ErrorWithCode';
41998
+ this.code = code;
41999
+ }
42000
+ }
42001
+
42002
+ /**
42003
+ * Copiable text box
42004
+ * @author Gabe Abrams
42005
+ */
42006
+ /* ------------- Actions ------------ */
42007
+ // Types of actions
42008
+ var ActionType$1;
42009
+ (function (ActionType) {
42010
+ // Indicate that the text was recently copied
42011
+ ActionType["IndicateRecentlyCopied"] = "indicate-recently-copied";
42012
+ // Clear the status
42013
+ ActionType["ClearRecentlyCopiedStatus"] = "clear-recently-copied-status";
42014
+ })(ActionType$1 || (ActionType$1 = {}));
42015
+
42016
+ /**
42017
+ * Reusable nested item picker
42018
+ * @author Yuen Ler Chow
42019
+ */
42020
+ /* ------------- Actions ------------ */
42021
+ // Types of actions
42022
+ var ActionType;
42023
+ (function (ActionType) {
42024
+ // Toggle whether the children are being shown
42025
+ ActionType["ToggleItems"] = "toggle-items";
42026
+ })(ActionType || (ActionType = {}));
42027
+
42028
+ // Import custom error
42029
+ // Stored copy of caccl functions
42030
+ let _cacclGetLaunchInfo;
42031
+ /*------------------------------------------------------------------------*/
42032
+ /* Helpers */
42033
+ /*------------------------------------------------------------------------*/
42034
+ /**
42035
+ * Get launch info via CACCL
42626
42036
  * @author Gabe Abrams
42627
- * @param Collection the Collection class from dce-mango
42628
- * @returns initialized logCollection
42037
+ * @param req express request object
42038
+ * @returns object { launched, launchInfo }
42629
42039
  */
42630
- const initLogCollection = (Collection) => {
42631
- return new Collection('Log', {
42632
- uniqueIndexKey: 'id',
42633
- indexKeys: [
42634
- 'courseId',
42635
- 'context',
42636
- 'subcontext',
42637
- 'tags',
42638
- ],
42639
- });
42040
+ const cacclGetLaunchInfo = (req) => {
42041
+ {
42042
+ throw new ErrorWithCode('Could not get launch info because server was not initialized with dce-reactkit\'s initServer function', ReactKitErrorCode$1.NoCACCLGetLaunchInfoFunction);
42043
+ }
42640
42044
  };
42641
42045
 
42642
- // Cache user's ability
42643
- let canReview = undefined;
42644
42046
  /**
42645
- * Check if the current user can review logs
42047
+ * Server-side API param types
42646
42048
  * @author Gabe Abrams
42647
- * @returns true if current user can review logs
42648
42049
  */
42649
- const canReviewLogs = () => __awaiter$1(void 0, void 0, void 0, function* () {
42650
- // If cached, use that value
42651
- if (canReview !== undefined) {
42652
- return canReview;
42050
+ var ParamType;
42051
+ (function (ParamType) {
42052
+ ParamType["Boolean"] = "boolean";
42053
+ ParamType["BooleanOptional"] = "boolean-optional";
42054
+ ParamType["Float"] = "float";
42055
+ ParamType["FloatOptional"] = "float-optional";
42056
+ ParamType["Int"] = "int";
42057
+ ParamType["IntOptional"] = "int-optional";
42058
+ ParamType["JSON"] = "json";
42059
+ ParamType["JSONOptional"] = "json-optional";
42060
+ ParamType["String"] = "string";
42061
+ ParamType["StringOptional"] = "string-optional";
42062
+ })(ParamType || (ParamType = {}));
42063
+ var ParamType$1 = ParamType;
42064
+
42065
+ // Import shared types
42066
+ /**
42067
+ * Handle an error and respond to the client
42068
+ * @author Gabe Abrams
42069
+ * @param res express response
42070
+ * @param error error info
42071
+ * @param opts.err the error to send to the client
42072
+ * or the error message
42073
+ * @param [opts.code] an error code (only used if err.code is not
42074
+ * included)
42075
+ * @param [opts.status=500] the https status code to use
42076
+ * defined)
42077
+ */
42078
+ const handleError = (res, error) => {
42079
+ // Get the error message
42080
+ let message;
42081
+ if (error && error.message) {
42082
+ message = (error.message || 'An unknown error occurred.');
42653
42083
  }
42654
- // Ask on server
42655
- try {
42656
- canReview = !!(yield visitServerEndpoint$1({
42657
- path: LOG_REVIEW_STATUS_ROUTE,
42658
- method: 'GET',
42659
- }));
42084
+ else if (typeof error === 'string') {
42085
+ message = (error.trim().length > 0
42086
+ ? error
42087
+ : 'An unknown error occurred.');
42660
42088
  }
42661
- catch (err) {
42662
- canReview = false;
42089
+ else {
42090
+ message = 'An unknown error occurred.';
42663
42091
  }
42664
- return canReview;
42665
- });
42092
+ // Get the error code
42093
+ const code = (error.code || ReactKitErrorCode$1.NoCode);
42094
+ // Get the status code
42095
+ const status = (error.status || 500);
42096
+ // Respond to user
42097
+ res
42098
+ // Set the http status code
42099
+ .status(status)
42100
+ // Send a JSON response
42101
+ .json({
42102
+ // Error message
42103
+ message,
42104
+ // Error code
42105
+ code,
42106
+ // Success = false flag so client can detect server-side errors
42107
+ success: false,
42108
+ });
42109
+ return undefined;
42110
+ };
42666
42111
 
42667
42112
  /**
42668
- * For every element in an array, extract the value of a prop
42669
- * (e.g. for all user objects, extract their ages and put that into a new
42670
- * ages array)
42113
+ * Send successful API response
42671
42114
  * @author Gabe Abrams
42672
- * @param arr the array of objects to operate on
42673
- * @param prop the property to extract from each object
42674
- * @returns new array containing the corresponding values, in order, of each
42675
- * object in the original array
42115
+ * @param res express response
42116
+ * @param body the body of the response to send to the client
42676
42117
  */
42677
- const extractProp = (arr, prop) => {
42678
- return arr.map((item) => {
42679
- return item[prop];
42118
+ const handleSuccess = (res, body) => {
42119
+ // Send a http 200 json response
42120
+ res.json({
42121
+ // Include the body as a parameter
42122
+ body,
42123
+ // Success = true flag so client can detect successful responses
42124
+ success: true,
42680
42125
  });
42126
+ return undefined;
42681
42127
  };
42682
42128
 
42683
- // Import shared helpers
42684
42129
  /**
42685
- * Compare two arrays of objects by only comparing the values in a specific
42686
- * property (e.g. compare user arrays by comparing their user.id values)
42130
+ * Generate an express API route handler
42687
42131
  * @author Gabe Abrams
42688
- * @param a the first array
42689
- * @param b the second array
42690
- * @param prop the property to compare with
42691
- * @returns true if the arrays contain the same objects as determined by
42692
- * the values associated with each object's prop
42132
+ * @param opts object containing all arguments
42133
+ * @param opts.paramTypes map containing the types for each parameter that is
42134
+ * included in the request (map: param name => type)
42135
+ * @param opts.handler function that processes the request
42136
+ * @returns express route handler that takes the following arguments:
42137
+ * params (map: param name => value), handleSuccess (function for handling
42138
+ * successful requests), handleError (function for handling failed requests),
42139
+ * req (express request object), res (express response object),
42140
+ * next (express next function). Params also has userId, userFirstName,
42141
+ * userLastName, isLearner, isTTM, isAdmin, and any other variables that
42142
+ * are directly added to the session
42693
42143
  */
42694
- const compareArraysByProp = (a, b, prop) => {
42695
- // Extract values for comparison
42696
- const aVals = new Set(extractProp(a, prop));
42697
- const bVals = new Set(extractProp(b, prop));
42698
- // Compare sizes first
42699
- if (aVals.size !== bVals.size) {
42700
- return false;
42701
- }
42702
- // Same number of items. Make sure every object in aVals appears in bVals
42703
- // (if so, they should be equivalent since the sizes are the same)
42704
- // > Create map of items in bVals
42705
- const inBVals = {}; // item => true if in bVals
42706
- Array.from(bVals.values()).forEach((item) => {
42707
- inBVals[item] = true;
42708
- });
42709
- // > Loop through aVals and make sure every item is in bVals
42710
- return Array.from(aVals.values()).every((item) => {
42711
- return inBVals[item];
42144
+ const genRouteHandler = (opts) => {
42145
+ // Return a route handler
42146
+ return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
42147
+ var _a, _b;
42148
+ // Output params
42149
+ const output = {};
42150
+ /*----------------------------------------*/
42151
+ /* Parse Params */
42152
+ /*----------------------------------------*/
42153
+ // Process items one by one
42154
+ const paramList = Object.entries((_a = opts.paramTypes) !== null && _a !== void 0 ? _a : {});
42155
+ for (let i = 0; i < paramList.length; i++) {
42156
+ const [name, type] = paramList[i];
42157
+ // Find the value as a string
42158
+ const value = (req.params[name]
42159
+ || req.query[name]
42160
+ || req.body[name]);
42161
+ // Parse
42162
+ if (type === ParamType$1.Boolean || type === ParamType$1.BooleanOptional) {
42163
+ // Boolean
42164
+ // Handle case where value doesn't exist
42165
+ if (value === undefined) {
42166
+ if (type === ParamType$1.BooleanOptional) {
42167
+ output[name] = undefined;
42168
+ }
42169
+ else {
42170
+ return handleError(res, {
42171
+ message: `Parameter ${name} is required, but it was not included.`,
42172
+ code: ReactKitErrorCode$1.MissingParameter,
42173
+ status: 422,
42174
+ });
42175
+ }
42176
+ }
42177
+ else {
42178
+ // Value exists
42179
+ // Simplify value
42180
+ const simpleVal = (String(value)
42181
+ .trim()
42182
+ .toLowerCase());
42183
+ // Parse
42184
+ output[name] = ([
42185
+ 'true',
42186
+ 'yes',
42187
+ 'y',
42188
+ '1',
42189
+ 't',
42190
+ ].indexOf(simpleVal) >= 0);
42191
+ }
42192
+ }
42193
+ else if (type === ParamType$1.Float || type === ParamType$1.FloatOptional) {
42194
+ // Float
42195
+ // Handle case where value doesn't exist
42196
+ if (value === undefined) {
42197
+ if (type === ParamType$1.FloatOptional) {
42198
+ output[name] = undefined;
42199
+ }
42200
+ else {
42201
+ return handleError(res, {
42202
+ message: `Parameter ${name} is required, but it was not included.`,
42203
+ code: ReactKitErrorCode$1.MissingParameter,
42204
+ status: 422,
42205
+ });
42206
+ }
42207
+ }
42208
+ else if (!Number.isNaN(Number.parseFloat(String(value)))) {
42209
+ // Value is a number
42210
+ output[name] = Number.parseFloat(String(value));
42211
+ }
42212
+ else {
42213
+ // Issue!
42214
+ return handleError(res, {
42215
+ message: `Request data was malformed: ${name} was not a valid float.`,
42216
+ code: ReactKitErrorCode$1.InvalidParameter,
42217
+ status: 422,
42218
+ });
42219
+ }
42220
+ }
42221
+ else if (type === ParamType$1.Int || type === ParamType$1.IntOptional) {
42222
+ // Int
42223
+ // Handle case where value doesn't exist
42224
+ if (value === undefined) {
42225
+ if (type === ParamType$1.IntOptional) {
42226
+ output[name] = undefined;
42227
+ }
42228
+ else {
42229
+ return handleError(res, {
42230
+ message: `Parameter ${name} is required, but it was not included.`,
42231
+ code: ReactKitErrorCode$1.MissingParameter,
42232
+ status: 422,
42233
+ });
42234
+ }
42235
+ }
42236
+ else if (!Number.isNaN(Number.parseInt(String(value), 10))) {
42237
+ // Value is a number
42238
+ output[name] = Number.parseInt(String(value), 10);
42239
+ }
42240
+ else {
42241
+ // Issue!
42242
+ return handleError(res, {
42243
+ message: `Request data was malformed: ${name} was not a valid int.`,
42244
+ code: ReactKitErrorCode$1.InvalidParameter,
42245
+ status: 422,
42246
+ });
42247
+ }
42248
+ }
42249
+ else if (type === ParamType$1.JSON || type === ParamType$1.JSONOptional) {
42250
+ // Stringified JSON
42251
+ // Handle case where value doesn't exist
42252
+ if (value === undefined) {
42253
+ if (type === ParamType$1.JSONOptional) {
42254
+ output[name] = undefined;
42255
+ }
42256
+ else {
42257
+ return handleError(res, {
42258
+ message: `Parameter ${name} is required, but it was not included.`,
42259
+ code: ReactKitErrorCode$1.MissingParameter,
42260
+ status: 422,
42261
+ });
42262
+ }
42263
+ }
42264
+ else {
42265
+ // Value exists
42266
+ // Parse
42267
+ try {
42268
+ output[name] = JSON.parse(String(value));
42269
+ }
42270
+ catch (err) {
42271
+ return handleError(res, {
42272
+ message: `Request data was malformed: ${name} was not a valid JSON payload.`,
42273
+ code: ReactKitErrorCode$1.InvalidParameter,
42274
+ status: 422,
42275
+ });
42276
+ }
42277
+ }
42278
+ }
42279
+ else if (type === ParamType$1.String || type === ParamType$1.StringOptional) {
42280
+ // String
42281
+ // Handle case where value doesn't exist
42282
+ if (value === undefined) {
42283
+ if (type === ParamType$1.StringOptional) {
42284
+ output[name] = undefined;
42285
+ }
42286
+ else {
42287
+ return handleError(res, {
42288
+ message: `Parameter ${name} is required, but it was not included.`,
42289
+ code: ReactKitErrorCode$1.MissingParameter,
42290
+ status: 422,
42291
+ });
42292
+ }
42293
+ }
42294
+ else {
42295
+ // Value exists
42296
+ // Leave as is
42297
+ output[name] = value;
42298
+ }
42299
+ }
42300
+ else {
42301
+ // No valid data type
42302
+ return handleError(res, {
42303
+ message: `An internal error occurred: we could not determine the type of ${name}.`,
42304
+ code: ReactKitErrorCode$1.InvalidParameter,
42305
+ status: 422,
42306
+ });
42307
+ }
42308
+ }
42309
+ /*----------------------------------------*/
42310
+ /* Launch Info */
42311
+ /*----------------------------------------*/
42312
+ // Get launch info
42313
+ const { launched, launchInfo } = cacclGetLaunchInfo(req);
42314
+ if (!launched || !launchInfo) {
42315
+ return handleError(res, {
42316
+ message: 'Your session has expired. Please refresh the page and try again.',
42317
+ code: ReactKitErrorCode$1.SessionExpired,
42318
+ status: 440,
42319
+ });
42320
+ }
42321
+ // Error if user info cannot be found
42322
+ if (!launchInfo.userId
42323
+ || !launchInfo.userFirstName
42324
+ || !launchInfo.userLastName
42325
+ || (launchInfo.notInCourse
42326
+ && !launchInfo.isAdmin)
42327
+ || (!launchInfo.isTTM
42328
+ && !launchInfo.isLearner
42329
+ && !launchInfo.isAdmin)) {
42330
+ return handleError(res, {
42331
+ message: 'Your session was invalid. Please refresh the page and try again.',
42332
+ code: ReactKitErrorCode$1.SessionExpired,
42333
+ status: 440,
42334
+ });
42335
+ }
42336
+ // Add launch info to output
42337
+ output.userId = launchInfo.userId;
42338
+ output.userFirstName = launchInfo.userFirstName;
42339
+ output.userLastName = launchInfo.userLastName;
42340
+ output.userEmail = launchInfo.userEmail;
42341
+ output.isLearner = !!launchInfo.isLearner;
42342
+ output.isTTM = !!launchInfo.isTTM;
42343
+ output.isAdmin = !!launchInfo.isAdmin;
42344
+ output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
42345
+ output.courseName = launchInfo.contextLabel;
42346
+ // Add other session variables
42347
+ Object.keys(req.session).forEach((propName) => {
42348
+ // Skip if prop already in output
42349
+ if (output[propName] !== undefined) {
42350
+ return;
42351
+ }
42352
+ // Add to output
42353
+ const value = req.session[propName];
42354
+ if (typeof value === 'string'
42355
+ || typeof value === 'boolean'
42356
+ || typeof value === 'number') {
42357
+ output[propName] = value;
42358
+ }
42359
+ });
42360
+ /*----------------------------------------*/
42361
+ /* Require Course Consistency */
42362
+ /*----------------------------------------*/
42363
+ // Make sure the user actually launched from the appropriate course
42364
+ if (output.courseId
42365
+ && launchInfo.courseId
42366
+ && output.courseId !== launchInfo.courseId
42367
+ && !output.isTTM
42368
+ && !output.isAdmin) {
42369
+ // Course of interest is not the launch course
42370
+ return handleError(res, {
42371
+ message: 'You switched sessions by opening this app in another tab. Please refresh the page and try again.',
42372
+ code: ReactKitErrorCode$1.WrongCourse,
42373
+ status: 401,
42374
+ });
42375
+ }
42376
+ /*----------------------------------------*/
42377
+ /* Require Proper Permissions */
42378
+ /*----------------------------------------*/
42379
+ // Add TTM endpoint security
42380
+ if (
42381
+ // This is a TTM endpoint
42382
+ req.path.startsWith('/api/ttm')
42383
+ // User is not a TTM
42384
+ && (
42385
+ // User is not a TTM
42386
+ !output.isTTM
42387
+ // User is not an admin
42388
+ && !output.isAdmin)) {
42389
+ // User does not have access
42390
+ return handleError(res, {
42391
+ message: 'This action is only allowed if you are a teaching team member for the course. Please go back to Canvas, log in as a teaching team member, and try again.',
42392
+ code: ReactKitErrorCode$1.NotTTM,
42393
+ status: 401,
42394
+ });
42395
+ }
42396
+ // Add Admin endpoint security
42397
+ if (
42398
+ // This is an admin endpoint
42399
+ req.path.startsWith('/api/admin')
42400
+ // User is not an admin
42401
+ && !output.isAdmin) {
42402
+ // User does not have access
42403
+ return handleError(res, {
42404
+ message: 'This action is only allowed if you are a Canvas admin. Please go back to Canvas, log in as an admin, and try again.',
42405
+ code: ReactKitErrorCode$1.NotAdmin,
42406
+ status: 401,
42407
+ });
42408
+ }
42409
+ /*------------------------------------------------------------------------*/
42410
+ /* Call handler */
42411
+ /*------------------------------------------------------------------------*/
42412
+ try {
42413
+ const results = yield opts.handler({
42414
+ params: output,
42415
+ req,
42416
+ res,
42417
+ next,
42418
+ });
42419
+ // Send results to client
42420
+ handleSuccess(res, results !== null && results !== void 0 ? results : undefined);
42421
+ }
42422
+ catch (err) {
42423
+ // Send error to client
42424
+ handleError(res, err);
42425
+ }
42712
42426
  });
42713
42427
  };
42714
42428
 
42715
42429
  /**
42716
- * Get current time info in local time
42430
+ * Days of the week
42717
42431
  * @author Gabe Abrams
42718
- * @param [dateOrTimestamp=now] the date to get info on or a ms since epoch timestamp
42719
- * @returns object with timestamp (ms since epoch) and numbers
42720
- * corresponding to time values for year, month, day, hour, hour12, minute, isPM
42721
- * where hour is in 24hr time and hour12 is in 12hr time.
42722
42432
  */
42723
- const getLocalTimeInfo = (dateOrTimestamp) => {
42724
- // Create a time string
42725
- let d;
42726
- if (!dateOrTimestamp) {
42727
- // Use now
42728
- d = new Date();
42729
- }
42730
- else if (typeof dateOrTimestamp === 'number') {
42731
- // Convert to date
42732
- d = new Date(dateOrTimestamp);
42733
- }
42734
- else {
42735
- // Already a date
42736
- d = dateOrTimestamp;
42737
- }
42738
- // Create all time numbers
42739
- const timestamp = d.getTime();
42740
- const year = d.getFullYear();
42741
- const month = d.getMonth() + 1;
42742
- const day = d.getDate();
42743
- const hour = d.getHours();
42744
- const isPM = hour >= 12;
42745
- let hour12 = hour % 12;
42746
- if (hour12 === 0) {
42747
- hour12 = 12;
42748
- }
42749
- const minute = d.getMinutes();
42750
- // Return
42751
- return {
42752
- timestamp,
42753
- year,
42754
- month,
42755
- day,
42756
- hour,
42757
- hour12,
42758
- isPM,
42759
- minute,
42760
- };
42761
- };
42433
+ var DayOfWeek$2;
42434
+ (function (DayOfWeek) {
42435
+ DayOfWeek["Monday"] = "m";
42436
+ DayOfWeek["Tuesday"] = "t";
42437
+ DayOfWeek["Wednesday"] = "w";
42438
+ DayOfWeek["Thursday"] = "r";
42439
+ DayOfWeek["Friday"] = "f";
42440
+ DayOfWeek["Saturday"] = "s";
42441
+ DayOfWeek["Sunday"] = "u";
42442
+ })(DayOfWeek$2 || (DayOfWeek$2 = {}));
42762
42443
 
42763
42444
  /**
42764
42445
  * Add all routes for the DBEditor
@@ -42776,7 +42457,7 @@ const addDBEditorEndpoints = (opts) => {
42776
42457
  * @author Yuen Ler Chow
42777
42458
  * @returns {any[]} the list of items in the collection
42778
42459
  */
42779
- app.get(endpointPath, genRouteHandler$1({
42460
+ app.get(endpointPath, genRouteHandler({
42780
42461
  paramTypes: {
42781
42462
  filterQuery: ParamType$1.JSONOptional,
42782
42463
  },
@@ -42792,7 +42473,7 @@ const addDBEditorEndpoints = (opts) => {
42792
42473
  * @author Yuen Ler Chow
42793
42474
  * @param {any} item the item to create
42794
42475
  */
42795
- app.post(endpointPath, genRouteHandler$1({
42476
+ app.post(endpointPath, genRouteHandler({
42796
42477
  paramTypes: {
42797
42478
  item: ParamType$1.JSON,
42798
42479
  },
@@ -42806,7 +42487,7 @@ const addDBEditorEndpoints = (opts) => {
42806
42487
  * Remove an item from the collection by id
42807
42488
  * @author Yuen Ler Chow
42808
42489
  */
42809
- app.delete(`${endpointPath}/:id`, genRouteHandler$1({
42490
+ app.delete(`${endpointPath}/:id`, genRouteHandler({
42810
42491
  paramTypes: {
42811
42492
  id: ParamType$1.String,
42812
42493
  },
@@ -42835,9 +42516,9 @@ var DayOfWeek;
42835
42516
  var DayOfWeek$1 = DayOfWeek;
42836
42517
 
42837
42518
  exports.AppWrapper = AppWrapper;
42838
- exports.ButtonInputGroup = ButtonInputGroup$1;
42519
+ exports.ButtonInputGroup = ButtonInputGroup;
42839
42520
  exports.CSVDownloadButton = CSVDownloadButton;
42840
- exports.CheckboxButton = CheckboxButton$1;
42521
+ exports.CheckboxButton = CheckboxButton;
42841
42522
  exports.CopiableBox = CopiableBox;
42842
42523
  exports.DAY_IN_MS = DAY_IN_MS;
42843
42524
  exports.DBEntryFieldType = DBEntryFieldType$1;
@@ -42850,7 +42531,7 @@ exports.ErrorWithCode = ErrorWithCode$1;
42850
42531
  exports.HOUR_IN_MS = HOUR_IN_MS;
42851
42532
  exports.IntelliTable = IntelliTable;
42852
42533
  exports.ItemPicker = ItemPicker;
42853
- exports.LoadingSpinner = LoadingSpinner$1;
42534
+ exports.LoadingSpinner = LoadingSpinner;
42854
42535
  exports.LogAction = LogAction$1;
42855
42536
  exports.LogBuiltInMetadata = LogBuiltInMetadata;
42856
42537
  exports.LogReviewer = LogReviewer;
@@ -42865,14 +42546,14 @@ exports.ParamType = ParamType$3;
42865
42546
  exports.PopFailureMark = PopFailureMark;
42866
42547
  exports.PopPendingMark = PopPendingMark;
42867
42548
  exports.PopSuccessMark = PopSuccessMark;
42868
- exports.RadioButton = RadioButton$1;
42549
+ exports.RadioButton = RadioButton;
42869
42550
  exports.ReactKitErrorCode = ReactKitErrorCode$3;
42870
42551
  exports.SimpleDateChooser = SimpleDateChooser;
42871
42552
  exports.TabBox = TabBox;
42872
42553
  exports.Variant = Variant$3;
42873
42554
  exports.abbreviate = abbreviate;
42874
42555
  exports.addDBEditorEndpoints = addDBEditorEndpoints;
42875
- exports.alert = alert$2;
42556
+ exports.alert = alert$1;
42876
42557
  exports.avg = avg;
42877
42558
  exports.canReviewLogs = canReviewLogs;
42878
42559
  exports.ceilToNumDecimals = ceilToNumDecimals;
@@ -42882,15 +42563,15 @@ exports.extractProp = extractProp;
42882
42563
  exports.floorToNumDecimals = floorToNumDecimals;
42883
42564
  exports.forceNumIntoBounds = forceNumIntoBounds;
42884
42565
  exports.genCSV = genCSV;
42885
- exports.genRouteHandler = genRouteHandler;
42566
+ exports.genRouteHandler = genRouteHandler$1;
42886
42567
  exports.getHumanReadableDate = getHumanReadableDate;
42887
42568
  exports.getLocalTimeInfo = getLocalTimeInfo;
42888
42569
  exports.getMonthName = getMonthName;
42889
42570
  exports.getOrdinal = getOrdinal;
42890
42571
  exports.getPartOfDay = getPartOfDay;
42891
42572
  exports.getTimeInfoInET = getTimeInfoInET;
42892
- exports.handleError = handleError;
42893
- exports.handleSuccess = handleSuccess;
42573
+ exports.handleError = handleError$1;
42574
+ exports.handleSuccess = handleSuccess$1;
42894
42575
  exports.initClient = initClient;
42895
42576
  exports.initLogCollection = initLogCollection;
42896
42577
  exports.initServer = initServer;
@@ -42901,11 +42582,11 @@ exports.padDecimalZeros = padDecimalZeros;
42901
42582
  exports.padZerosLeft = padZerosLeft;
42902
42583
  exports.parallelLimit = parallelLimit;
42903
42584
  exports.roundToNumDecimals = roundToNumDecimals;
42904
- exports.showFatalError = showFatalError$1;
42585
+ exports.showFatalError = showFatalError;
42905
42586
  exports.startMinWait = startMinWait;
42906
42587
  exports.stringsToHumanReadableList = stringsToHumanReadableList;
42907
42588
  exports.stubServerEndpoint = stubServerEndpoint;
42908
42589
  exports.sum = sum;
42909
- exports.visitServerEndpoint = visitServerEndpoint$1;
42590
+ exports.visitServerEndpoint = visitServerEndpoint;
42910
42591
  exports.waitMs = waitMs;
42911
42592
  //# sourceMappingURL=index.js.map