dce-reactkit 3.9.4-beta-logreviewer.6 → 3.9.4-beta-logreviewer.8
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 +426 -204
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/client/initClient.d.ts +16 -2
- package/dist/cjs/types/components/AppWrapper.d.ts +32 -0
- package/dist/cjs/types/components/CheckboxButton.d.ts +1 -0
- package/dist/cjs/types/components/Pagination.d.ts +9 -0
- package/dist/cjs/types/components/RadioButton.d.ts +2 -0
- package/dist/cjs/types/constants/LOG_REVIEW_PAGE_SIZE.d.ts +6 -0
- package/dist/cjs/types/index.d.ts +2 -2
- package/dist/cjs/types/types/ModalType.d.ts +1 -0
- package/dist/esm/index.js +426 -205
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/client/initClient.d.ts +16 -2
- package/dist/esm/types/components/AppWrapper.d.ts +32 -0
- package/dist/esm/types/components/CheckboxButton.d.ts +1 -0
- package/dist/esm/types/components/Pagination.d.ts +9 -0
- package/dist/esm/types/components/RadioButton.d.ts +2 -0
- package/dist/esm/types/constants/LOG_REVIEW_PAGE_SIZE.d.ts +6 -0
- package/dist/esm/types/index.d.ts +2 -2
- package/dist/esm/types/types/ModalType.d.ts +1 -0
- package/dist/index.d.ts +47 -3
- package/package.json +1 -1
- package/src/client/initClient.tsx +49 -11
- package/src/components/AppWrapper.tsx +258 -2
- package/src/components/CheckboxButton.tsx +24 -6
- package/src/components/LogReviewer.tsx +271 -221
- package/src/components/Modal/index.tsx +3 -0
- package/src/components/Pagination.tsx +147 -0
- package/src/components/RadioButton.tsx +33 -6
- package/src/components/SimpleDateChooser.tsx +8 -2
- package/src/constants/LOG_REVIEW_PAGE_SIZE.ts +7 -0
- package/src/helpers/genRouteHandler.ts +7 -7
- package/src/helpers/logClientEvent.tsx +8 -0
- package/src/helpers/visitServerEndpoint.tsx +1 -0
- package/src/index.ts +2 -0
- package/src/server/initLogCollection.ts +5 -0
- package/src/server/initServer.ts +3 -2
- package/src/types/ModalType.tsx +1 -0
package/dist/cjs/index.js
CHANGED
|
@@ -186,6 +186,7 @@ var ModalButtonType$1 = ModalButtonType;
|
|
|
186
186
|
var ModalType;
|
|
187
187
|
(function (ModalType) {
|
|
188
188
|
ModalType["Okay"] = "okay";
|
|
189
|
+
ModalType["Cancel"] = "cancel";
|
|
189
190
|
ModalType["OkayCancel"] = "okay-cancel";
|
|
190
191
|
ModalType["YesNo"] = "yes-no";
|
|
191
192
|
ModalType["YesNoCancel"] = "yes-no-cancel";
|
|
@@ -316,11 +317,23 @@ const isDarkModeOn = () => {
|
|
|
316
317
|
* @param opts object containing all arguments
|
|
317
318
|
* @param opts.sendRequest caccl send request functions
|
|
318
319
|
* @param [opts.sessionExpiredMessage] a custom session expired message
|
|
320
|
+
* @param [opts.darkModeOn] if true, dark mode is enabled
|
|
321
|
+
* @param [opts.noServer] if true, there is no server for this app
|
|
319
322
|
*/
|
|
320
323
|
const initClient = (opts) => {
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
|
|
324
|
+
// Handle separately if there is no server
|
|
325
|
+
if (opts.noServer) {
|
|
326
|
+
// Store values
|
|
327
|
+
storedSendRequest = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
328
|
+
throw new Error('Cannot send requests because there is no server');
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
// Store values
|
|
333
|
+
storedSendRequest = opts.sendRequest;
|
|
334
|
+
sessionExpiredMessage = opts.sessionExpiredMessage;
|
|
335
|
+
}
|
|
336
|
+
// Handle universal parts
|
|
324
337
|
darkModeOn = !!opts.darkModeOn;
|
|
325
338
|
// Mark as initialized
|
|
326
339
|
onInitialized(null);
|
|
@@ -340,6 +353,9 @@ const modalTypeToModalButtonTypes = {
|
|
|
340
353
|
[ModalType$1.Okay]: [
|
|
341
354
|
ModalButtonType$1.Okay,
|
|
342
355
|
],
|
|
356
|
+
[ModalType$1.Cancel]: [
|
|
357
|
+
ModalButtonType$1.Cancel,
|
|
358
|
+
],
|
|
343
359
|
[ModalType$1.OkayCancel]: [
|
|
344
360
|
ModalButtonType$1.Okay,
|
|
345
361
|
ModalButtonType$1.Cancel,
|
|
@@ -781,6 +797,7 @@ const _setStubResponse = (opts) => {
|
|
|
781
797
|
*/
|
|
782
798
|
const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
783
799
|
var _a, _b, _c;
|
|
800
|
+
// Set default method
|
|
784
801
|
const method = ((_a = opts.method) !== null && _a !== void 0 ? _a : 'GET');
|
|
785
802
|
// Handle stubs
|
|
786
803
|
const stubResponse = (_b = stubResponses[method]) === null || _b === void 0 ? void 0 : _b[opts.path];
|
|
@@ -1080,6 +1097,92 @@ const confirm = (title, text, opts) => __awaiter(void 0, void 0, void 0, functio
|
|
|
1080
1097
|
});
|
|
1081
1098
|
});
|
|
1082
1099
|
/*----------------------------------------*/
|
|
1100
|
+
/* --------------- Prompt -------------- */
|
|
1101
|
+
/*----------------------------------------*/
|
|
1102
|
+
// Stored copies of setters
|
|
1103
|
+
let setPromptInfo;
|
|
1104
|
+
// Function to call when prompt is closed
|
|
1105
|
+
let onPromptClosed;
|
|
1106
|
+
/**
|
|
1107
|
+
* Show a prompt modal asking the user for input
|
|
1108
|
+
* @author Yuen Ler Chow
|
|
1109
|
+
* @param title the title text to display at the top of the prompt
|
|
1110
|
+
* @param [opts={}] additional options for the prompt dialog
|
|
1111
|
+
* @param [opts.textAboveInputField] the text to display in the prompt
|
|
1112
|
+
* @param [opts.defaultText] the default text for the input field
|
|
1113
|
+
* @param [opts.placeholder] the placeholder text for the input field
|
|
1114
|
+
* @param [opts.confirmButtonText=Okay] the text of the confirm button
|
|
1115
|
+
* @param [opts.confirmButtonVariant=Variant.Dark] the variant of the confirm button
|
|
1116
|
+
* @param [opts.cancelButtonText=Cancel] the text of the cancel button
|
|
1117
|
+
* @param [opts.cancelButtonVariant=Variant.Secondary] the variant of the cancel button
|
|
1118
|
+
* @param [opts.minNumChars] the minimum number of characters required for
|
|
1119
|
+
* the input to be valid
|
|
1120
|
+
* @param [opts.findValidationError] a function that takes the input text and
|
|
1121
|
+
* returns an error message if the input is invalid, returns undefined if the
|
|
1122
|
+
* input is valid
|
|
1123
|
+
* @param [opts.ariaLabel] the aria label for the input field
|
|
1124
|
+
* @returns Promise that resolves with the input string or null if canceled
|
|
1125
|
+
*/
|
|
1126
|
+
const prompt = (title, opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1127
|
+
var _a, _b;
|
|
1128
|
+
// Wait for helper to exist
|
|
1129
|
+
yield waitForHelper(() => {
|
|
1130
|
+
return !!setPromptInfo;
|
|
1131
|
+
});
|
|
1132
|
+
// Fallback if prompt is not available
|
|
1133
|
+
if (!setPromptInfo) {
|
|
1134
|
+
const resultPassesValidation = false;
|
|
1135
|
+
while (!resultPassesValidation) {
|
|
1136
|
+
// eslint-disable-next-line no-alert
|
|
1137
|
+
const result = window.prompt(`${title}\n\n${(_a = opts === null || opts === void 0 ? void 0 : opts.textAboveInputField) !== null && _a !== void 0 ? _a : ''}`, (_b = opts === null || opts === void 0 ? void 0 : opts.defaultText) !== null && _b !== void 0 ? _b : '');
|
|
1138
|
+
// Exit loop if user cancels
|
|
1139
|
+
if (result === null) {
|
|
1140
|
+
return null;
|
|
1141
|
+
}
|
|
1142
|
+
// Validate min num chars
|
|
1143
|
+
const minNumCharsValidationError = (((opts === null || opts === void 0 ? void 0 : opts.minNumChars) && result.length < opts.minNumChars)
|
|
1144
|
+
? `Please enter at least ${opts.minNumChars} characters.`
|
|
1145
|
+
: undefined);
|
|
1146
|
+
// Run custom validation
|
|
1147
|
+
const customValidationError = ((opts === null || opts === void 0 ? void 0 : opts.findValidationError)
|
|
1148
|
+
&& opts.findValidationError(result));
|
|
1149
|
+
// Show validation issue
|
|
1150
|
+
if (minNumCharsValidationError || customValidationError) {
|
|
1151
|
+
// Create error message
|
|
1152
|
+
const errorMessage = ([
|
|
1153
|
+
minNumCharsValidationError,
|
|
1154
|
+
customValidationError,
|
|
1155
|
+
]
|
|
1156
|
+
// Filter out undefined messages
|
|
1157
|
+
.filter((msg) => {
|
|
1158
|
+
return !!msg;
|
|
1159
|
+
})
|
|
1160
|
+
// Join messages with newlines
|
|
1161
|
+
.join('\n'));
|
|
1162
|
+
// Show alert
|
|
1163
|
+
alert('Invalid Input', errorMessage);
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
return result;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
// Return promise that resolves with result of prompt
|
|
1171
|
+
return new Promise((resolve) => {
|
|
1172
|
+
var _a;
|
|
1173
|
+
// Setup handler
|
|
1174
|
+
onPromptClosed = (result) => {
|
|
1175
|
+
resolve(result);
|
|
1176
|
+
};
|
|
1177
|
+
// Show the prompt
|
|
1178
|
+
setPromptInfo({
|
|
1179
|
+
title,
|
|
1180
|
+
currentInputFieldText: ((_a = opts === null || opts === void 0 ? void 0 : opts.defaultText) !== null && _a !== void 0 ? _a : ''),
|
|
1181
|
+
opts: (opts !== null && opts !== void 0 ? opts : {}),
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
});
|
|
1185
|
+
/*----------------------------------------*/
|
|
1083
1186
|
/* ------------- Fatal Error ------------ */
|
|
1084
1187
|
/*----------------------------------------*/
|
|
1085
1188
|
// Stored copies of setters
|
|
@@ -1095,14 +1198,14 @@ const fatalErrorHandlers = [];
|
|
|
1095
1198
|
* @param [errorTitle] title of the error box
|
|
1096
1199
|
*/
|
|
1097
1200
|
const showFatalError = (error, errorTitle = 'An Error Occurred') => __awaiter(void 0, void 0, void 0, function* () {
|
|
1098
|
-
var
|
|
1201
|
+
var _c, _d;
|
|
1099
1202
|
// Determine message and code
|
|
1100
1203
|
const message = (typeof error === 'string'
|
|
1101
1204
|
? error.trim()
|
|
1102
|
-
: String((
|
|
1205
|
+
: String((_c = error.message) !== null && _c !== void 0 ? _c : 'An unknown error occurred.'));
|
|
1103
1206
|
const code = (typeof error === 'string'
|
|
1104
1207
|
? ReactKitErrorCode$1.NoCode
|
|
1105
|
-
: String((
|
|
1208
|
+
: String((_d = error.code) !== null && _d !== void 0 ? _d : ReactKitErrorCode$1.NoCode));
|
|
1106
1209
|
// Call all fatal error listeners
|
|
1107
1210
|
try {
|
|
1108
1211
|
fatalErrorHandlers.forEach((handler) => {
|
|
@@ -1229,6 +1332,9 @@ const AppWrapper = (props) => {
|
|
|
1229
1332
|
// Confirm
|
|
1230
1333
|
const [confirmInfo, setConfirmInfoInner,] = React.useState(undefined);
|
|
1231
1334
|
setConfirmInfo = setConfirmInfoInner;
|
|
1335
|
+
// Prompt
|
|
1336
|
+
const [promptInfo, setPromptInfoInner] = React.useState(undefined);
|
|
1337
|
+
setPromptInfo = setPromptInfoInner;
|
|
1232
1338
|
// Session expired
|
|
1233
1339
|
const [sessionHasExpired, setSessionHasExpiredInner,] = React.useState(false);
|
|
1234
1340
|
setSessionHasExpired = setSessionHasExpiredInner;
|
|
@@ -1259,6 +1365,42 @@ const AppWrapper = (props) => {
|
|
|
1259
1365
|
}
|
|
1260
1366
|
}, onTopOfOtherModals: true, dontAllowBackdropExit: true }, confirmInfo.text));
|
|
1261
1367
|
}
|
|
1368
|
+
/* ------------- Prompt ------------ */
|
|
1369
|
+
if (promptInfo) {
|
|
1370
|
+
// Run min char validation
|
|
1371
|
+
const minNumCharsValidationError = ((promptInfo.opts.minNumChars
|
|
1372
|
+
&& promptInfo.currentInputFieldText.length < promptInfo.opts.minNumChars)
|
|
1373
|
+
? `Please enter at least ${promptInfo.opts.minNumChars} characters.`
|
|
1374
|
+
: undefined);
|
|
1375
|
+
// Run custom validation
|
|
1376
|
+
const customValidationError = (promptInfo.opts.findValidationError
|
|
1377
|
+
&& promptInfo.opts.findValidationError(promptInfo.currentInputFieldText));
|
|
1378
|
+
modal = (React__default["default"].createElement(Modal, { key: `prompt-${promptInfo.title}`, title: promptInfo.title,
|
|
1379
|
+
// Don't show ok button if there is a validation error
|
|
1380
|
+
type: ((customValidationError || minNumCharsValidationError)
|
|
1381
|
+
? ModalType$1.Cancel
|
|
1382
|
+
: ModalType$1.OkayCancel), okayLabel: promptInfo.opts.confirmButtonText, okayVariant: promptInfo.opts.confirmButtonVariant, cancelLabel: promptInfo.opts.cancelButtonText, cancelVariant: promptInfo.opts.cancelButtonVariant, onClose: (buttonType) => {
|
|
1383
|
+
// Get result
|
|
1384
|
+
const result = (buttonType === ModalButtonType$1.Okay
|
|
1385
|
+
? promptInfo.currentInputFieldText
|
|
1386
|
+
: null);
|
|
1387
|
+
// Close prompt
|
|
1388
|
+
setPromptInfo(undefined);
|
|
1389
|
+
// Call handler
|
|
1390
|
+
if (onPromptClosed) {
|
|
1391
|
+
onPromptClosed(result);
|
|
1392
|
+
}
|
|
1393
|
+
}, onTopOfOtherModals: true, dontAllowBackdropExit: true },
|
|
1394
|
+
React__default["default"].createElement("div", null,
|
|
1395
|
+
promptInfo.opts.textAboveInputField && (React__default["default"].createElement("div", null, promptInfo.opts.textAboveInputField)),
|
|
1396
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": promptInfo.opts.ariaLabel, placeholder: promptInfo.opts.placeholder, value: promptInfo.currentInputFieldText, onChange: (e) => {
|
|
1397
|
+
return setPromptInfo(Object.assign(Object.assign({}, promptInfo), { currentInputFieldText: e.target.value }));
|
|
1398
|
+
},
|
|
1399
|
+
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
1400
|
+
autoFocus: true }),
|
|
1401
|
+
minNumCharsValidationError && (React__default["default"].createElement("div", { className: "text-danger fw-bold mt-2" }, minNumCharsValidationError)),
|
|
1402
|
+
customValidationError && (React__default["default"].createElement("div", { className: "text-danger fw-bold mt-2" }, customValidationError)))));
|
|
1403
|
+
}
|
|
1262
1404
|
/* ------ Custom Modal Portals ------ */
|
|
1263
1405
|
// Custom modal portals
|
|
1264
1406
|
const customModalPortals = [];
|
|
@@ -1328,7 +1470,7 @@ const AppWrapper = (props) => {
|
|
|
1328
1470
|
? `
|
|
1329
1471
|
.tooltip-inner {
|
|
1330
1472
|
background-color: white;
|
|
1331
|
-
color: black;
|
|
1473
|
+
color: black !important;
|
|
1332
1474
|
border: 0.1rem solid black;
|
|
1333
1475
|
pointer-events: none;
|
|
1334
1476
|
}
|
|
@@ -1341,7 +1483,7 @@ const AppWrapper = (props) => {
|
|
|
1341
1483
|
: `
|
|
1342
1484
|
.tooltip-inner {
|
|
1343
1485
|
background-color: black;
|
|
1344
|
-
color: white;
|
|
1486
|
+
color: white !important;
|
|
1345
1487
|
border: 0.1rem solid white;
|
|
1346
1488
|
pointer-events: none;
|
|
1347
1489
|
}
|
|
@@ -1560,24 +1702,31 @@ const RadioButton = (props) => {
|
|
|
1560
1702
|
/* -------------------------------- Setup ------------------------------- */
|
|
1561
1703
|
/*------------------------------------------------------------------------*/
|
|
1562
1704
|
/* -------------- Props ------------- */
|
|
1563
|
-
const { text, onSelected, ariaLabel, title, selected, id, noMarginOnRight, selectedVariant = (isDarkModeOn()
|
|
1705
|
+
const { text, onSelected, ariaLabel, title, selected, id, className, noMarginOnRight, selectedVariant = (isDarkModeOn()
|
|
1564
1706
|
? Variant$1.Light
|
|
1565
1707
|
: Variant$1.Secondary), unselectedVariant = (isDarkModeOn()
|
|
1566
1708
|
? Variant$1.Secondary
|
|
1567
|
-
: Variant$1.Light), small, } = props;
|
|
1709
|
+
: Variant$1.Light), small, useComplexFormatting, } = props;
|
|
1568
1710
|
/*------------------------------------------------------------------------*/
|
|
1569
1711
|
/* ------------------------------- Render ------------------------------- */
|
|
1570
1712
|
/*------------------------------------------------------------------------*/
|
|
1571
1713
|
/*----------------------------------------*/
|
|
1572
1714
|
/* --------------- Main UI -------------- */
|
|
1573
1715
|
/*----------------------------------------*/
|
|
1574
|
-
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: () => {
|
|
1716
|
+
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'} ${className !== null && className !== void 0 ? className : ''}`, "aria-label": `${ariaLabel}${selected ? ': currently selected' : ''}`, onClick: () => {
|
|
1575
1717
|
if (!selected) {
|
|
1576
1718
|
onSelected();
|
|
1577
1719
|
}
|
|
1578
1720
|
} },
|
|
1579
|
-
React__default["default"].createElement(
|
|
1580
|
-
|
|
1721
|
+
React__default["default"].createElement("div", { className: "d-flex flex-row align-items-center" },
|
|
1722
|
+
React__default["default"].createElement("div", { className: "me-1" },
|
|
1723
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: selected ? freeSolidSvgIcons.faDotCircle : freeRegularSvgIcons.faCircle })),
|
|
1724
|
+
useComplexFormatting
|
|
1725
|
+
? (React__default["default"].createElement("pre", { className: "ps-1 text-start text-break", style: {
|
|
1726
|
+
whiteSpace: 'pre-wrap',
|
|
1727
|
+
tabSize: 2,
|
|
1728
|
+
} }, text))
|
|
1729
|
+
: (React__default["default"].createElement("div", { className: "flex-grow-1 text-start text-break" }, text)))));
|
|
1581
1730
|
};
|
|
1582
1731
|
|
|
1583
1732
|
/**
|
|
@@ -1596,7 +1745,7 @@ const CheckboxButton = (props) => {
|
|
|
1596
1745
|
? Variant$1.Light
|
|
1597
1746
|
: Variant$1.Secondary), uncheckedVariant = (isDarkModeOn()
|
|
1598
1747
|
? Variant$1.Secondary
|
|
1599
|
-
: Variant$1.Light), small, dashed, } = props;
|
|
1748
|
+
: Variant$1.Light), small, dashed, useComplexFormatting, } = props;
|
|
1600
1749
|
/*------------------------------------------------------------------------*/
|
|
1601
1750
|
/* ------------------------------- Render ------------------------------- */
|
|
1602
1751
|
/*------------------------------------------------------------------------*/
|
|
@@ -1617,10 +1766,15 @@ const CheckboxButton = (props) => {
|
|
|
1617
1766
|
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: () => {
|
|
1618
1767
|
onChanged(!checked);
|
|
1619
1768
|
} },
|
|
1620
|
-
React__default["default"].createElement("div", { className: "d-flex" },
|
|
1621
|
-
React__default["default"].createElement("div", { className: "
|
|
1622
|
-
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: icon
|
|
1623
|
-
|
|
1769
|
+
React__default["default"].createElement("div", { className: "d-flex align-items-center" },
|
|
1770
|
+
React__default["default"].createElement("div", { className: "me-1" },
|
|
1771
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: icon })),
|
|
1772
|
+
useComplexFormatting
|
|
1773
|
+
? (React__default["default"].createElement("pre", { className: "ps-1 text-start text-break", style: {
|
|
1774
|
+
whiteSpace: 'pre-wrap',
|
|
1775
|
+
tabSize: 2,
|
|
1776
|
+
} }, text))
|
|
1777
|
+
: (React__default["default"].createElement("div", { className: "flex-grow-1 text-start text-break" }, text)))));
|
|
1624
1778
|
};
|
|
1625
1779
|
|
|
1626
1780
|
/**
|
|
@@ -1801,7 +1955,13 @@ const SimpleDateChooser = (props) => {
|
|
|
1801
1955
|
}
|
|
1802
1956
|
const monthName = getMonthName(month).full;
|
|
1803
1957
|
// Year is start year +1 for each 12 months
|
|
1804
|
-
|
|
1958
|
+
let yearsToAdd = 0;
|
|
1959
|
+
let monthsOfYearsToAdd = unmoddedMonth;
|
|
1960
|
+
while (monthsOfYearsToAdd > 12) {
|
|
1961
|
+
monthsOfYearsToAdd -= 12;
|
|
1962
|
+
yearsToAdd += 1;
|
|
1963
|
+
}
|
|
1964
|
+
const year = startYear + yearsToAdd;
|
|
1805
1965
|
// Figure out which days are allowed
|
|
1806
1966
|
const days = [];
|
|
1807
1967
|
const numDaysInMonth = (new Date(year, month, 0)).getDate();
|
|
@@ -1852,7 +2012,7 @@ const SimpleDateChooser = (props) => {
|
|
|
1852
2012
|
});
|
|
1853
2013
|
}
|
|
1854
2014
|
});
|
|
1855
|
-
return (React__default["default"].createElement("div", { className: "SimpleDateChooser d-inline-block", "aria-label": `date chooser with selected date: ${month}
|
|
2015
|
+
return (React__default["default"].createElement("div", { className: "SimpleDateChooser d-inline-block", "aria-label": `date chooser with selected date: ${month}/${day}/${year}` },
|
|
1856
2016
|
React__default["default"].createElement("select", { "aria-label": `month for ${ariaLabel}`, className: "custom-select d-inline-block mr-1", style: { width: 'auto' }, id: `SimpleDateChooser-${name}-month`, value: `${month}-${year}`, onChange: (e) => {
|
|
1857
2017
|
const choice = choices[e.target.selectedIndex];
|
|
1858
2018
|
// Change day, month, and year
|
|
@@ -3182,6 +3342,55 @@ const IntelliTable = (props) => {
|
|
|
3182
3342
|
} }, table)));
|
|
3183
3343
|
};
|
|
3184
3344
|
|
|
3345
|
+
/*------------------------------------------------------------------------*/
|
|
3346
|
+
/* ------------------------------ Component ----------------------------- */
|
|
3347
|
+
/*------------------------------------------------------------------------*/
|
|
3348
|
+
const Pagination = ({ currentPage, numPages, loading = false, onPageChanged, }) => {
|
|
3349
|
+
// computes an array of page numbers to display.
|
|
3350
|
+
const getPageNumbers = () => {
|
|
3351
|
+
const pages = [];
|
|
3352
|
+
const delta = 2; // how many pages to show on either side of current
|
|
3353
|
+
let start = Math.max(1, currentPage - delta);
|
|
3354
|
+
let end = Math.min(numPages, currentPage + delta);
|
|
3355
|
+
// If we are too close to the beginning or end, shift the window.
|
|
3356
|
+
if (currentPage - delta < 1) {
|
|
3357
|
+
end = Math.min(numPages, end + (1 - (currentPage - delta)));
|
|
3358
|
+
}
|
|
3359
|
+
if (currentPage + delta > numPages) {
|
|
3360
|
+
start = Math.max(1, start - ((currentPage + delta) - numPages));
|
|
3361
|
+
}
|
|
3362
|
+
for (let i = start; i <= end; i++) {
|
|
3363
|
+
pages.push(i);
|
|
3364
|
+
}
|
|
3365
|
+
return pages;
|
|
3366
|
+
};
|
|
3367
|
+
const pages = getPageNumbers();
|
|
3368
|
+
return (React__default["default"].createElement("nav", { "aria-label": "Page navigation", className: "mt-3" },
|
|
3369
|
+
React__default["default"].createElement("ul", { className: "pagination justify-content-center" },
|
|
3370
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage <= 1 || loading) ? 'disabled' : ''}` },
|
|
3371
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(currentPage - 1); }, disabled: currentPage <= 1 || loading },
|
|
3372
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowLeft }),
|
|
3373
|
+
' ',
|
|
3374
|
+
"Prev")),
|
|
3375
|
+
currentPage > 3 && (React__default["default"].createElement("li", { className: "page-item" },
|
|
3376
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(1); }, disabled: loading }, "1"))),
|
|
3377
|
+
currentPage > 4 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
3378
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
3379
|
+
pages.map((pageNum) => {
|
|
3380
|
+
return (React__default["default"].createElement("li", { key: pageNum, className: `page-item ${pageNum === currentPage ? 'active' : ''}` },
|
|
3381
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(pageNum); }, disabled: loading }, pageNum)));
|
|
3382
|
+
}),
|
|
3383
|
+
currentPage < numPages - 3 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
3384
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
3385
|
+
currentPage < numPages - 2 && (React__default["default"].createElement("li", { className: "page-item" },
|
|
3386
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(numPages); }, disabled: loading }, numPages))),
|
|
3387
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage >= numPages || loading) ? 'disabled' : ''}` },
|
|
3388
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(currentPage + 1); }, disabled: currentPage >= numPages || loading },
|
|
3389
|
+
"Next",
|
|
3390
|
+
' ',
|
|
3391
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowRight }))))));
|
|
3392
|
+
};
|
|
3393
|
+
|
|
3185
3394
|
/**
|
|
3186
3395
|
* Log reviewer panel that allows users (must be approved admins) to
|
|
3187
3396
|
* review logs written by dce-reactkit
|
|
@@ -3561,6 +3770,8 @@ var ActionType$6;
|
|
|
3561
3770
|
ActionType["SetNumPages"] = "set-num-pages";
|
|
3562
3771
|
// Set page number
|
|
3563
3772
|
ActionType["SetPageNumber"] = "set-page-number";
|
|
3773
|
+
// Reset user made filter change indicator
|
|
3774
|
+
ActionType["ResetUserMadeFilterChange"] = "reset-user-made-filter-change";
|
|
3564
3775
|
})(ActionType$6 || (ActionType$6 = {}));
|
|
3565
3776
|
/**
|
|
3566
3777
|
* Reducer that executes actions
|
|
@@ -3585,22 +3796,22 @@ const reducer$7 = (state, action) => {
|
|
|
3585
3796
|
return Object.assign(Object.assign({}, state), { expandedFilterDrawer: undefined });
|
|
3586
3797
|
}
|
|
3587
3798
|
case ActionType$6.ResetFilters: {
|
|
3588
|
-
return Object.assign(Object.assign({}, state), {
|
|
3799
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.initDateFilterState, pendingContextFilterState: action.initContextFilterState, pendingTagFilterState: action.initTagFilterState, pendingActionErrorFilterState: action.initActionErrorFilterState, pendingAdvancedFilterState: action.initAdvancedFilterState, pageNumber: 1 });
|
|
3589
3800
|
}
|
|
3590
3801
|
case ActionType$6.UpdateDateFilterState: {
|
|
3591
|
-
return Object.assign(Object.assign({}, state), {
|
|
3802
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.dateFilterState, userMadeFilterChange: true });
|
|
3592
3803
|
}
|
|
3593
3804
|
case ActionType$6.UpdateContextFilterState: {
|
|
3594
|
-
return Object.assign(Object.assign({}, state), {
|
|
3805
|
+
return Object.assign(Object.assign({}, state), { pendingContextFilterState: action.contextFilterState, userMadeFilterChange: true });
|
|
3595
3806
|
}
|
|
3596
3807
|
case ActionType$6.UpdateTagFilterState: {
|
|
3597
|
-
return Object.assign(Object.assign({}, state), {
|
|
3808
|
+
return Object.assign(Object.assign({}, state), { pendingTagFilterState: action.tagFilterState, userMadeFilterChange: true });
|
|
3598
3809
|
}
|
|
3599
3810
|
case ActionType$6.UpdateActionErrorFilterState: {
|
|
3600
|
-
return Object.assign(Object.assign({}, state), {
|
|
3811
|
+
return Object.assign(Object.assign({}, state), { pendingActionErrorFilterState: action.actionErrorFilterState, userMadeFilterChange: true });
|
|
3601
3812
|
}
|
|
3602
3813
|
case ActionType$6.UpdateAdvancedFilterState: {
|
|
3603
|
-
return Object.assign(Object.assign({}, state), {
|
|
3814
|
+
return Object.assign(Object.assign({}, state), { pendingAdvancedFilterState: action.advancedFilterState, userMadeFilterChange: true });
|
|
3604
3815
|
}
|
|
3605
3816
|
case ActionType$6.SetHasAnotherPage: {
|
|
3606
3817
|
return Object.assign(Object.assign({}, state), { hasAnotherPage: action.hasAnotherPage });
|
|
@@ -3611,6 +3822,9 @@ const reducer$7 = (state, action) => {
|
|
|
3611
3822
|
case ActionType$6.SetPageNumber: {
|
|
3612
3823
|
return Object.assign(Object.assign({}, state), { pageNumber: action.pageNumber });
|
|
3613
3824
|
}
|
|
3825
|
+
case ActionType$6.ResetUserMadeFilterChange: {
|
|
3826
|
+
return Object.assign(Object.assign({}, state), { userMadeFilterChange: false });
|
|
3827
|
+
}
|
|
3614
3828
|
default: {
|
|
3615
3829
|
return state;
|
|
3616
3830
|
}
|
|
@@ -3731,19 +3945,29 @@ const LogReviewer = (props) => {
|
|
|
3731
3945
|
showSpinner: true,
|
|
3732
3946
|
logs: [],
|
|
3733
3947
|
expandedFilterDrawer: undefined,
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3948
|
+
pendingDateFilterState: initDateFilterState,
|
|
3949
|
+
pendingContextFilterState: initContextFilterState,
|
|
3950
|
+
pendingTagFilterState: initTagFilterState,
|
|
3951
|
+
pendingActionErrorFilterState: initActionErrorFilterState,
|
|
3952
|
+
pendingAdvancedFilterState: initAdvancedFilterState,
|
|
3739
3953
|
pageNumber: 1,
|
|
3740
3954
|
hasAnotherPage: false,
|
|
3741
3955
|
numPages: 1,
|
|
3956
|
+
userMadeFilterChange: false,
|
|
3742
3957
|
};
|
|
3743
3958
|
// Initialize state
|
|
3744
3959
|
const [state, dispatch] = React.useReducer(reducer$7, initialState);
|
|
3745
3960
|
// Destructure common state
|
|
3746
|
-
const { loading, showSpinner, logs, expandedFilterDrawer,
|
|
3961
|
+
const { loading, showSpinner, logs, expandedFilterDrawer, pendingDateFilterState, pendingContextFilterState, pendingTagFilterState, pendingActionErrorFilterState, pendingAdvancedFilterState, pageNumber, numPages, userMadeFilterChange, } = state;
|
|
3962
|
+
/* -------------- Refs -------------- */
|
|
3963
|
+
// Initialize refs
|
|
3964
|
+
const activeFiltersRef = React.useRef({
|
|
3965
|
+
dateFilterState: JSON.parse(JSON.stringify(pendingDateFilterState)),
|
|
3966
|
+
contextFilterState: JSON.parse(JSON.stringify(pendingContextFilterState)),
|
|
3967
|
+
tagFilterState: JSON.parse(JSON.stringify(pendingTagFilterState)),
|
|
3968
|
+
actionErrorFilterState: JSON.parse(JSON.stringify(pendingActionErrorFilterState)),
|
|
3969
|
+
advancedFilterState: JSON.parse(JSON.stringify(pendingAdvancedFilterState)),
|
|
3970
|
+
});
|
|
3747
3971
|
/*------------------------------------------------------------------------*/
|
|
3748
3972
|
/* ------------------------- Component Functions ------------------------ */
|
|
3749
3973
|
/*------------------------------------------------------------------------*/
|
|
@@ -3802,11 +4026,11 @@ const LogReviewer = (props) => {
|
|
|
3802
4026
|
React.useEffect(() => {
|
|
3803
4027
|
fetchLogs({
|
|
3804
4028
|
filters: {
|
|
3805
|
-
dateFilterState,
|
|
3806
|
-
contextFilterState,
|
|
3807
|
-
tagFilterState,
|
|
3808
|
-
actionErrorFilterState,
|
|
3809
|
-
advancedFilterState,
|
|
4029
|
+
dateFilterState: pendingDateFilterState,
|
|
4030
|
+
contextFilterState: pendingContextFilterState,
|
|
4031
|
+
tagFilterState: pendingTagFilterState,
|
|
4032
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4033
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
3810
4034
|
},
|
|
3811
4035
|
pageNum: 1,
|
|
3812
4036
|
filtersChanged: true,
|
|
@@ -3829,51 +4053,25 @@ const LogReviewer = (props) => {
|
|
|
3829
4053
|
/*----------------------------------------*/
|
|
3830
4054
|
/* ------------ Pagination -------------- */
|
|
3831
4055
|
/*----------------------------------------*/
|
|
3832
|
-
const paginationControls = logs.length > 0 && (React__default["default"].createElement(
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowLeft, className: "me-2" }),
|
|
3847
|
-
"Previous Page"),
|
|
3848
|
-
React__default["default"].createElement("span", { className: "mx-3" },
|
|
3849
|
-
"Page",
|
|
3850
|
-
' ',
|
|
3851
|
-
pageNumber,
|
|
3852
|
-
' ',
|
|
3853
|
-
"of",
|
|
3854
|
-
' ',
|
|
3855
|
-
numPages),
|
|
3856
|
-
React__default["default"].createElement("button", { type: "button", className: "btn btn-secondary ms-2", disabled: !hasAnotherPage || loading, onClick: () => {
|
|
3857
|
-
fetchLogs({
|
|
3858
|
-
filters: {
|
|
3859
|
-
dateFilterState,
|
|
3860
|
-
contextFilterState,
|
|
3861
|
-
tagFilterState,
|
|
3862
|
-
actionErrorFilterState,
|
|
3863
|
-
advancedFilterState,
|
|
3864
|
-
},
|
|
3865
|
-
pageNum: pageNumber + 1,
|
|
3866
|
-
filtersChanged: false,
|
|
3867
|
-
});
|
|
3868
|
-
} },
|
|
3869
|
-
"Next Page",
|
|
3870
|
-
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowRight, className: "ms-2" }))));
|
|
4056
|
+
const paginationControls = logs.length > 0 && (React__default["default"].createElement(Pagination, { currentPage: pageNumber, numPages: numPages, loading: loading, onPageChanged: (targetPage) => {
|
|
4057
|
+
const { current: activeFilters } = activeFiltersRef;
|
|
4058
|
+
fetchLogs({
|
|
4059
|
+
filters: {
|
|
4060
|
+
dateFilterState: activeFilters.dateFilterState,
|
|
4061
|
+
contextFilterState: activeFilters.contextFilterState,
|
|
4062
|
+
tagFilterState: activeFilters.tagFilterState,
|
|
4063
|
+
actionErrorFilterState: activeFilters.actionErrorFilterState,
|
|
4064
|
+
advancedFilterState: activeFilters.advancedFilterState,
|
|
4065
|
+
},
|
|
4066
|
+
pageNum: targetPage,
|
|
4067
|
+
filtersChanged: false,
|
|
4068
|
+
});
|
|
4069
|
+
} }));
|
|
3871
4070
|
/*----------------------------------------*/
|
|
3872
4071
|
/* --------------- Filters -------------- */
|
|
3873
4072
|
/*----------------------------------------*/
|
|
3874
4073
|
// Filter toggle
|
|
3875
4074
|
const filterToggles = (React__default["default"].createElement("div", { className: "LogReviewer-filter-toggles" },
|
|
3876
|
-
React__default["default"].createElement("h3", { className: "m-0" }, "Filters:"),
|
|
3877
4075
|
React__default["default"].createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
|
|
3878
4076
|
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: () => {
|
|
3879
4077
|
dispatch({
|
|
@@ -3942,17 +4140,29 @@ const LogReviewer = (props) => {
|
|
|
3942
4140
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes }),
|
|
3943
4141
|
' ',
|
|
3944
4142
|
"Reset"),
|
|
3945
|
-
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-submit-filters-button", className: "btn btn-primary ms-2", "aria-label": "submit filters", onClick: () => {
|
|
4143
|
+
userMadeFilterChange && (React__default["default"].createElement("button", { type: "button", id: "LogReviewer-submit-filters-button", className: "btn btn-primary ms-2", "aria-label": "submit filters", onClick: () => {
|
|
3946
4144
|
dispatch({
|
|
3947
4145
|
type: ActionType$6.HideFilterDrawer,
|
|
3948
4146
|
});
|
|
4147
|
+
// Reset user made filter change indicator
|
|
4148
|
+
dispatch({
|
|
4149
|
+
type: ActionType$6.ResetUserMadeFilterChange,
|
|
4150
|
+
});
|
|
4151
|
+
// Save active filters
|
|
4152
|
+
activeFiltersRef.current = {
|
|
4153
|
+
dateFilterState: JSON.parse(JSON.stringify(pendingDateFilterState)),
|
|
4154
|
+
contextFilterState: JSON.parse(JSON.stringify(pendingContextFilterState)),
|
|
4155
|
+
tagFilterState: JSON.parse(JSON.stringify(pendingTagFilterState)),
|
|
4156
|
+
actionErrorFilterState: JSON.parse(JSON.stringify(pendingActionErrorFilterState)),
|
|
4157
|
+
advancedFilterState: JSON.parse(JSON.stringify(pendingAdvancedFilterState)),
|
|
4158
|
+
};
|
|
3949
4159
|
fetchLogs({
|
|
3950
4160
|
filters: {
|
|
3951
|
-
dateFilterState,
|
|
3952
|
-
contextFilterState,
|
|
3953
|
-
tagFilterState,
|
|
3954
|
-
actionErrorFilterState,
|
|
3955
|
-
advancedFilterState,
|
|
4161
|
+
dateFilterState: pendingDateFilterState,
|
|
4162
|
+
contextFilterState: pendingContextFilterState,
|
|
4163
|
+
tagFilterState: pendingTagFilterState,
|
|
4164
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4165
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
3956
4166
|
},
|
|
3957
4167
|
pageNum: 1,
|
|
3958
4168
|
filtersChanged: true,
|
|
@@ -3960,35 +4170,35 @@ const LogReviewer = (props) => {
|
|
|
3960
4170
|
} },
|
|
3961
4171
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faSearch }),
|
|
3962
4172
|
' ',
|
|
3963
|
-
"
|
|
4173
|
+
"Apply Filters")))));
|
|
3964
4174
|
// Filter drawer
|
|
3965
4175
|
let filterDrawer;
|
|
3966
4176
|
if (expandedFilterDrawer) {
|
|
3967
4177
|
if (expandedFilterDrawer === FilterDrawer.Date) {
|
|
3968
4178
|
filterDrawer = (React__default["default"].createElement(TabBox, { title: "Date" },
|
|
3969
|
-
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year:
|
|
3970
|
-
|
|
4179
|
+
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: pendingDateFilterState.startDate.year, month: pendingDateFilterState.startDate.month, day: pendingDateFilterState.startDate.day, chooseFromPast: true, numMonthsToShow: 36, onChange: (month, day, year) => {
|
|
4180
|
+
pendingDateFilterState.startDate = { month, day, year };
|
|
3971
4181
|
dispatch({
|
|
3972
4182
|
type: ActionType$6.UpdateDateFilterState,
|
|
3973
|
-
dateFilterState,
|
|
4183
|
+
dateFilterState: pendingDateFilterState,
|
|
3974
4184
|
});
|
|
3975
4185
|
} }),
|
|
3976
4186
|
' ',
|
|
3977
4187
|
"to",
|
|
3978
4188
|
' ',
|
|
3979
|
-
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year:
|
|
3980
|
-
if (year <
|
|
3981
|
-
|| (year ===
|
|
3982
|
-
&& month <
|
|
3983
|
-
|| (year ===
|
|
3984
|
-
&& month ===
|
|
3985
|
-
&& day <
|
|
4189
|
+
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: pendingDateFilterState.endDate.year, month: pendingDateFilterState.endDate.month, day: pendingDateFilterState.endDate.day, chooseFromPast: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
4190
|
+
if (year < pendingDateFilterState.startDate.year
|
|
4191
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
4192
|
+
&& month < pendingDateFilterState.startDate.month)
|
|
4193
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
4194
|
+
&& month === pendingDateFilterState.startDate.month
|
|
4195
|
+
&& day < pendingDateFilterState.startDate.day)) {
|
|
3986
4196
|
return alert('Invalid Start Date', 'The start date cannot be before the end date.');
|
|
3987
4197
|
}
|
|
3988
|
-
|
|
4198
|
+
pendingDateFilterState.endDate = { month, day, year };
|
|
3989
4199
|
dispatch({
|
|
3990
4200
|
type: ActionType$6.UpdateDateFilterState,
|
|
3991
|
-
dateFilterState,
|
|
4201
|
+
dateFilterState: pendingDateFilterState,
|
|
3992
4202
|
});
|
|
3993
4203
|
} })));
|
|
3994
4204
|
}
|
|
@@ -4010,7 +4220,7 @@ const LogReviewer = (props) => {
|
|
|
4010
4220
|
id: context,
|
|
4011
4221
|
name: genHumanReadableName(context),
|
|
4012
4222
|
isGroup: false,
|
|
4013
|
-
checked: !!
|
|
4223
|
+
checked: !!pendingContextFilterState[context],
|
|
4014
4224
|
};
|
|
4015
4225
|
// Add built-in items to its own folder
|
|
4016
4226
|
const isBuiltIn = context in LogBuiltInMetadata.Context;
|
|
@@ -4036,7 +4246,7 @@ const LogReviewer = (props) => {
|
|
|
4036
4246
|
id: subcontext,
|
|
4037
4247
|
name: genHumanReadableName(subcontext),
|
|
4038
4248
|
isGroup: false,
|
|
4039
|
-
checked:
|
|
4249
|
+
checked: pendingContextFilterState[context][subcontext],
|
|
4040
4250
|
};
|
|
4041
4251
|
}));
|
|
4042
4252
|
const item = {
|
|
@@ -4059,7 +4269,7 @@ const LogReviewer = (props) => {
|
|
|
4059
4269
|
// Built-in
|
|
4060
4270
|
// Treat as if these were top-level contexts
|
|
4061
4271
|
pickableItem.children.forEach((subcontextItem) => {
|
|
4062
|
-
|
|
4272
|
+
pendingContextFilterState[subcontextItem.id] = ('checked' in subcontextItem
|
|
4063
4273
|
&& subcontextItem.checked);
|
|
4064
4274
|
});
|
|
4065
4275
|
}
|
|
@@ -4067,19 +4277,19 @@ const LogReviewer = (props) => {
|
|
|
4067
4277
|
// Not built-in
|
|
4068
4278
|
pickableItem.children.forEach((subcontextItem) => {
|
|
4069
4279
|
if (!subcontextItem.isGroup) {
|
|
4070
|
-
|
|
4280
|
+
pendingContextFilterState[pickableItem.id][subcontextItem.id] = (subcontextItem.checked);
|
|
4071
4281
|
}
|
|
4072
4282
|
});
|
|
4073
4283
|
}
|
|
4074
4284
|
}
|
|
4075
4285
|
else {
|
|
4076
4286
|
// No subcontexts
|
|
4077
|
-
|
|
4287
|
+
pendingContextFilterState[pickableItem.id] = (pickableItem.checked);
|
|
4078
4288
|
}
|
|
4079
4289
|
});
|
|
4080
4290
|
dispatch({
|
|
4081
4291
|
type: ActionType$6.UpdateContextFilterState,
|
|
4082
|
-
contextFilterState,
|
|
4292
|
+
contextFilterState: pendingContextFilterState,
|
|
4083
4293
|
});
|
|
4084
4294
|
} }));
|
|
4085
4295
|
}
|
|
@@ -4090,13 +4300,13 @@ const LogReviewer = (props) => {
|
|
|
4090
4300
|
React__default["default"].createElement("div", { className: "d-flex gap-1 flex-wrap" }, Object.keys((_d = LogMetadata.Tag) !== null && _d !== void 0 ? _d : {})
|
|
4091
4301
|
.map((tag) => {
|
|
4092
4302
|
const description = genHumanReadableName(tag);
|
|
4093
|
-
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:
|
|
4094
|
-
|
|
4303
|
+
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: pendingTagFilterState[tag], onChanged: (checked) => {
|
|
4304
|
+
pendingTagFilterState[tag] = checked;
|
|
4095
4305
|
dispatch({
|
|
4096
4306
|
type: ActionType$6.UpdateTagFilterState,
|
|
4097
|
-
tagFilterState,
|
|
4307
|
+
tagFilterState: pendingTagFilterState,
|
|
4098
4308
|
});
|
|
4099
|
-
} }));
|
|
4309
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
4100
4310
|
}))));
|
|
4101
4311
|
}
|
|
4102
4312
|
else if (expandedFilterDrawer === FilterDrawer.Action) {
|
|
@@ -4104,70 +4314,70 @@ const LogReviewer = (props) => {
|
|
|
4104
4314
|
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
4105
4315
|
React__default["default"].createElement(TabBox, { title: "Log Type" },
|
|
4106
4316
|
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
|
|
4107
|
-
|
|
4317
|
+
pendingActionErrorFilterState.type = undefined;
|
|
4108
4318
|
dispatch({
|
|
4109
4319
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4110
|
-
actionErrorFilterState,
|
|
4320
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4111
4321
|
});
|
|
4112
|
-
}, ariaLabel: "show logs of all types", selected:
|
|
4322
|
+
}, ariaLabel: "show logs of all types", selected: pendingActionErrorFilterState.type === undefined, unselectedVariant: Variant$1.Light }),
|
|
4113
4323
|
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-action-only", text: "Action Logs Only", onSelected: () => {
|
|
4114
|
-
|
|
4324
|
+
pendingActionErrorFilterState.type = LogType$1.Action;
|
|
4115
4325
|
dispatch({
|
|
4116
4326
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4117
|
-
actionErrorFilterState,
|
|
4327
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4118
4328
|
});
|
|
4119
|
-
}, ariaLabel: "only show action logs", selected:
|
|
4329
|
+
}, ariaLabel: "only show action logs", selected: pendingActionErrorFilterState.type === LogType$1.Action, unselectedVariant: Variant$1.Light }),
|
|
4120
4330
|
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-error-only", text: "Action Error Only", onSelected: () => {
|
|
4121
|
-
|
|
4331
|
+
pendingActionErrorFilterState.type = LogType$1.Error;
|
|
4122
4332
|
dispatch({
|
|
4123
4333
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4124
|
-
actionErrorFilterState,
|
|
4334
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4125
4335
|
});
|
|
4126
|
-
}, ariaLabel: "only show error logs", selected:
|
|
4127
|
-
(
|
|
4128
|
-
||
|
|
4336
|
+
}, ariaLabel: "only show error logs", selected: pendingActionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
4337
|
+
(pendingActionErrorFilterState.type === undefined
|
|
4338
|
+
|| pendingActionErrorFilterState.type === LogType$1.Action) && (React__default["default"].createElement(TabBox, { title: "Action Log Details" },
|
|
4129
4339
|
React__default["default"].createElement(ButtonInputGroup, { label: "Action", className: "mb-2", wrapButtonsAndAddGaps: true }, Object.keys(LogAction$1)
|
|
4130
4340
|
.map((action) => {
|
|
4131
4341
|
const description = genHumanReadableName(action);
|
|
4132
|
-
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:
|
|
4133
|
-
|
|
4342
|
+
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: pendingActionErrorFilterState.action[action], onChanged: (checked) => {
|
|
4343
|
+
pendingActionErrorFilterState.action[action] = checked;
|
|
4134
4344
|
dispatch({
|
|
4135
4345
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4136
|
-
actionErrorFilterState,
|
|
4346
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4137
4347
|
});
|
|
4138
|
-
} }));
|
|
4348
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
4139
4349
|
})),
|
|
4140
4350
|
React__default["default"].createElement(ButtonInputGroup, { label: "Target", wrapButtonsAndAddGaps: true }, Object.keys(targetMap)
|
|
4141
4351
|
.map((target) => {
|
|
4142
4352
|
const description = genHumanReadableName(target);
|
|
4143
|
-
return (React__default["default"].createElement(CheckboxButton, { key: target, id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, checked:
|
|
4144
|
-
|
|
4353
|
+
return (React__default["default"].createElement(CheckboxButton, { key: target, id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, checked: pendingActionErrorFilterState.target[target], noMarginOnRight: true, onChanged: (checked) => {
|
|
4354
|
+
pendingActionErrorFilterState.target[target] = checked;
|
|
4145
4355
|
dispatch({
|
|
4146
4356
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4147
|
-
actionErrorFilterState,
|
|
4357
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4148
4358
|
});
|
|
4149
|
-
} }));
|
|
4359
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
4150
4360
|
})))),
|
|
4151
|
-
(
|
|
4152
|
-
||
|
|
4361
|
+
(pendingActionErrorFilterState.type === undefined
|
|
4362
|
+
|| pendingActionErrorFilterState.type === LogType$1.Error) && (React__default["default"].createElement(TabBox, { title: "Error Log Details" },
|
|
4153
4363
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4154
4364
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Message"),
|
|
4155
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error message", value:
|
|
4156
|
-
|
|
4365
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error message", value: pendingActionErrorFilterState.errorMessage, placeholder: "e.g. undefined is not a function", onChange: (e) => {
|
|
4366
|
+
pendingActionErrorFilterState.errorMessage = e.target.value;
|
|
4157
4367
|
dispatch({
|
|
4158
4368
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4159
|
-
actionErrorFilterState,
|
|
4369
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4160
4370
|
});
|
|
4161
4371
|
} })),
|
|
4162
4372
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4163
4373
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Code"),
|
|
4164
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error code", value:
|
|
4165
|
-
|
|
4374
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error code", value: pendingActionErrorFilterState.errorCode, placeholder: "e.g. GC22", onChange: (e) => {
|
|
4375
|
+
pendingActionErrorFilterState.errorCode = ((e.target.value)
|
|
4166
4376
|
.trim()
|
|
4167
4377
|
.toUpperCase());
|
|
4168
4378
|
dispatch({
|
|
4169
4379
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
4170
|
-
actionErrorFilterState,
|
|
4380
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4171
4381
|
});
|
|
4172
4382
|
} }))))));
|
|
4173
4383
|
}
|
|
@@ -4177,157 +4387,157 @@ const LogReviewer = (props) => {
|
|
|
4177
4387
|
React__default["default"].createElement(TabBox, { title: "User" },
|
|
4178
4388
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4179
4389
|
React__default["default"].createElement("span", { className: "input-group-text" }, "User First Name"),
|
|
4180
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user first name", value:
|
|
4181
|
-
|
|
4390
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user first name", value: pendingAdvancedFilterState.userFirstName, placeholder: "e.g. Divardo", onChange: (e) => {
|
|
4391
|
+
pendingAdvancedFilterState.userFirstName = e.target.value;
|
|
4182
4392
|
dispatch({
|
|
4183
4393
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4184
|
-
advancedFilterState,
|
|
4394
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4185
4395
|
});
|
|
4186
4396
|
} })),
|
|
4187
4397
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4188
4398
|
React__default["default"].createElement("span", { className: "input-group-text" }, "User Last Name"),
|
|
4189
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user last name", value:
|
|
4190
|
-
|
|
4399
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user last name", value: pendingAdvancedFilterState.userLastName, placeholder: "e.g. Calicci", onChange: (e) => {
|
|
4400
|
+
pendingAdvancedFilterState.userLastName = e.target.value;
|
|
4191
4401
|
dispatch({
|
|
4192
4402
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4193
|
-
advancedFilterState,
|
|
4403
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4194
4404
|
});
|
|
4195
4405
|
} })),
|
|
4196
4406
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4197
4407
|
React__default["default"].createElement("span", { className: "input-group-text" }, "User Email"),
|
|
4198
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user email", value:
|
|
4199
|
-
|
|
4408
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user email", value: pendingAdvancedFilterState.userEmail, placeholder: "e.g. calicci@fas.harvard.edu", onChange: (e) => {
|
|
4409
|
+
pendingAdvancedFilterState.userEmail = ((e.target.value)
|
|
4200
4410
|
.trim());
|
|
4201
4411
|
dispatch({
|
|
4202
4412
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4203
|
-
advancedFilterState,
|
|
4413
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4204
4414
|
});
|
|
4205
4415
|
} })),
|
|
4206
4416
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4207
4417
|
React__default["default"].createElement("span", { className: "input-group-text" }, "User Canvas Id"),
|
|
4208
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user canvas id", value:
|
|
4418
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user canvas id", value: pendingAdvancedFilterState.userId, placeholder: "e.g. 104985", onChange: (e) => {
|
|
4209
4419
|
const { value } = e.target;
|
|
4210
4420
|
// Only update if value contains only numbers
|
|
4211
4421
|
if (/^\d+$/.test(value) || value === '') {
|
|
4212
|
-
|
|
4422
|
+
pendingAdvancedFilterState.userId = ((e.target.value)
|
|
4213
4423
|
.trim());
|
|
4214
4424
|
}
|
|
4215
4425
|
dispatch({
|
|
4216
4426
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4217
|
-
advancedFilterState,
|
|
4427
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4218
4428
|
});
|
|
4219
4429
|
} })),
|
|
4220
4430
|
React__default["default"].createElement(ButtonInputGroup, { label: "Role" },
|
|
4221
4431
|
React__default["default"].createElement(CheckboxButton, { text: "Students", onChanged: (checked) => {
|
|
4222
|
-
|
|
4432
|
+
pendingAdvancedFilterState.includeLearners = checked;
|
|
4223
4433
|
dispatch({
|
|
4224
4434
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4225
|
-
advancedFilterState,
|
|
4435
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4226
4436
|
});
|
|
4227
|
-
}, checked:
|
|
4437
|
+
}, checked: pendingAdvancedFilterState.includeLearners, ariaLabel: "show logs from students", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
4228
4438
|
React__default["default"].createElement(CheckboxButton, { text: "Teaching Team Members", onChanged: (checked) => {
|
|
4229
|
-
|
|
4439
|
+
pendingAdvancedFilterState.includeTTMs = checked;
|
|
4230
4440
|
dispatch({
|
|
4231
4441
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4232
|
-
advancedFilterState,
|
|
4442
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4233
4443
|
});
|
|
4234
|
-
}, checked:
|
|
4444
|
+
}, checked: pendingAdvancedFilterState.includeTTMs, ariaLabel: "show logs from teaching team members", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
4235
4445
|
React__default["default"].createElement(CheckboxButton, { text: "Admins", onChanged: (checked) => {
|
|
4236
|
-
|
|
4446
|
+
pendingAdvancedFilterState.includeAdmins = checked;
|
|
4237
4447
|
dispatch({
|
|
4238
4448
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4239
|
-
advancedFilterState,
|
|
4449
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4240
4450
|
});
|
|
4241
|
-
}, checked:
|
|
4451
|
+
}, checked: pendingAdvancedFilterState.includeAdmins, ariaLabel: "show logs from admins", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }))),
|
|
4242
4452
|
React__default["default"].createElement(TabBox, { title: "Course" },
|
|
4243
4453
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4244
4454
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Name"),
|
|
4245
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course name", value:
|
|
4246
|
-
|
|
4455
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course name", value: pendingAdvancedFilterState.courseName, placeholder: "e.g. GLC 200", onChange: (e) => {
|
|
4456
|
+
pendingAdvancedFilterState.courseName = e.target.value;
|
|
4247
4457
|
dispatch({
|
|
4248
4458
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4249
|
-
advancedFilterState,
|
|
4459
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4250
4460
|
});
|
|
4251
4461
|
} })),
|
|
4252
4462
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4253
4463
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Canvas Id"),
|
|
4254
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course canvas id", value:
|
|
4464
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course canvas id", value: pendingAdvancedFilterState.courseId, placeholder: "e.g. 15948", onChange: (e) => {
|
|
4255
4465
|
const { value } = e.target;
|
|
4256
4466
|
// Only update if value contains only numbers
|
|
4257
4467
|
if (/^\d+$/.test(value)) {
|
|
4258
|
-
|
|
4468
|
+
pendingAdvancedFilterState.courseId = ((e.target.value)
|
|
4259
4469
|
.trim());
|
|
4260
4470
|
}
|
|
4261
4471
|
dispatch({
|
|
4262
4472
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4263
|
-
advancedFilterState,
|
|
4473
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4264
4474
|
});
|
|
4265
4475
|
} }))),
|
|
4266
4476
|
React__default["default"].createElement(TabBox, { title: "Device" },
|
|
4267
4477
|
React__default["default"].createElement(ButtonInputGroup, { label: "Device Type" },
|
|
4268
|
-
React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected:
|
|
4269
|
-
|
|
4478
|
+
React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected: pendingAdvancedFilterState.isMobile === undefined, onSelected: () => {
|
|
4479
|
+
pendingAdvancedFilterState.isMobile = undefined;
|
|
4270
4480
|
dispatch({
|
|
4271
4481
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4272
|
-
advancedFilterState,
|
|
4482
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4273
4483
|
});
|
|
4274
|
-
} }),
|
|
4275
|
-
React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected:
|
|
4276
|
-
|
|
4484
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
4485
|
+
React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: pendingAdvancedFilterState.isMobile === true, onSelected: () => {
|
|
4486
|
+
pendingAdvancedFilterState.isMobile = true;
|
|
4277
4487
|
dispatch({
|
|
4278
4488
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4279
|
-
advancedFilterState,
|
|
4489
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4280
4490
|
});
|
|
4281
|
-
} }),
|
|
4282
|
-
React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected:
|
|
4283
|
-
|
|
4491
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
4492
|
+
React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: pendingAdvancedFilterState.isMobile === false, onSelected: () => {
|
|
4493
|
+
pendingAdvancedFilterState.isMobile = false;
|
|
4284
4494
|
dispatch({
|
|
4285
4495
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4286
|
-
advancedFilterState,
|
|
4496
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4287
4497
|
});
|
|
4288
|
-
}, noMarginOnRight: true }))),
|
|
4498
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }))),
|
|
4289
4499
|
React__default["default"].createElement(TabBox, { title: "Source" },
|
|
4290
4500
|
React__default["default"].createElement(ButtonInputGroup, { label: "Source Type" },
|
|
4291
|
-
React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected:
|
|
4292
|
-
|
|
4501
|
+
React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected: pendingAdvancedFilterState.source === undefined, onSelected: () => {
|
|
4502
|
+
pendingAdvancedFilterState.source = undefined;
|
|
4293
4503
|
dispatch({
|
|
4294
4504
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4295
|
-
advancedFilterState,
|
|
4505
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4296
4506
|
});
|
|
4297
|
-
} }),
|
|
4298
|
-
React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected:
|
|
4299
|
-
|
|
4507
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
4508
|
+
React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected: pendingAdvancedFilterState.source === LogSource$1.Client, onSelected: () => {
|
|
4509
|
+
pendingAdvancedFilterState.source = LogSource$1.Client;
|
|
4300
4510
|
dispatch({
|
|
4301
4511
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4302
|
-
advancedFilterState,
|
|
4512
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4303
4513
|
});
|
|
4304
|
-
} }),
|
|
4305
|
-
React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected:
|
|
4306
|
-
|
|
4514
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
4515
|
+
React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected: pendingAdvancedFilterState.source === LogSource$1.Server, onSelected: () => {
|
|
4516
|
+
pendingAdvancedFilterState.source = LogSource$1.Server;
|
|
4307
4517
|
dispatch({
|
|
4308
4518
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4309
|
-
advancedFilterState,
|
|
4519
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4310
4520
|
});
|
|
4311
|
-
}, noMarginOnRight: true })),
|
|
4312
|
-
|
|
4521
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
4522
|
+
pendingAdvancedFilterState.source !== LogSource$1.Client && (React__default["default"].createElement("div", { className: "mt-2" },
|
|
4313
4523
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4314
4524
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
4315
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route path", value:
|
|
4316
|
-
|
|
4525
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route path", value: pendingAdvancedFilterState.routePath, placeholder: "e.g. /api/ttm/courses/12345", onChange: (e) => {
|
|
4526
|
+
pendingAdvancedFilterState.courseName = ((e.target.value)
|
|
4317
4527
|
.trim());
|
|
4318
4528
|
dispatch({
|
|
4319
4529
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4320
|
-
advancedFilterState,
|
|
4530
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4321
4531
|
});
|
|
4322
4532
|
} })),
|
|
4323
4533
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
4324
4534
|
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
4325
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route template", value:
|
|
4326
|
-
|
|
4535
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route template", value: pendingAdvancedFilterState.routeTemplate, placeholder: "e.g. /api/ttm/courses/:courseId", onChange: (e) => {
|
|
4536
|
+
pendingAdvancedFilterState.courseName = ((e.target.value)
|
|
4327
4537
|
.trim());
|
|
4328
4538
|
dispatch({
|
|
4329
4539
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
4330
|
-
advancedFilterState,
|
|
4540
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4331
4541
|
});
|
|
4332
4542
|
} })))))));
|
|
4333
4543
|
}
|
|
@@ -4341,10 +4551,10 @@ const LogReviewer = (props) => {
|
|
|
4341
4551
|
body = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
4342
4552
|
filters,
|
|
4343
4553
|
React__default["default"].createElement("div", { className: "mt-2" },
|
|
4344
|
-
React__default["default"].createElement(
|
|
4345
|
-
logs.length === 0 && (React__default["default"].createElement("div", { className: "alert alert-warning text-center mt-2" },
|
|
4554
|
+
logs.length === 0 ? (React__default["default"].createElement("div", { className: "alert alert-warning text-center mt-2" },
|
|
4346
4555
|
React__default["default"].createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
4347
|
-
React__default["default"].createElement("div", null, "Either your filters are too strict or no matching logs have been created yet.")))
|
|
4556
|
+
React__default["default"].createElement("div", null, "Either your filters are too strict or no matching logs have been created yet.")))
|
|
4557
|
+
: (React__default["default"].createElement(IntelliTable, { title: "Matching Logs", csvName: `Logs from ${getHumanReadableDate()}`, id: "logs", data: logs, columns: columns })),
|
|
4348
4558
|
paginationControls)));
|
|
4349
4559
|
}
|
|
4350
4560
|
/* ---------- Wrap in Modal --------- */
|
|
@@ -4353,7 +4563,7 @@ const LogReviewer = (props) => {
|
|
|
4353
4563
|
React__default["default"].createElement("div", { className: "LogReviewer-inner-container" },
|
|
4354
4564
|
React__default["default"].createElement("div", { className: "LogReviewer-header" },
|
|
4355
4565
|
React__default["default"].createElement("div", { className: "LogReviewer-header-title" },
|
|
4356
|
-
React__default["default"].createElement("h3", { className: "text-center
|
|
4566
|
+
React__default["default"].createElement("h3", { className: "text-center" }, "Log Review Dashboard")),
|
|
4357
4567
|
React__default["default"].createElement("div", { style: { width: 0 } },
|
|
4358
4568
|
React__default["default"].createElement("button", { type: "button", className: "LogReviewer-header-close-button btn btn-dark btn-lg pe-0", "aria-label": "close log reviewer panel", onClick: onClose },
|
|
4359
4569
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes })))),
|
|
@@ -13688,6 +13898,12 @@ const padZerosLeft = (num, numDigits) => {
|
|
|
13688
13898
|
*/
|
|
13689
13899
|
const LOG_REVIEW_STATUS_ROUTE = `${ROUTE_PATH_PREFIX}/logs/access_allowed`;
|
|
13690
13900
|
|
|
13901
|
+
/**
|
|
13902
|
+
* Log reviewer page size
|
|
13903
|
+
* @author Yuen Ler Chow
|
|
13904
|
+
*/
|
|
13905
|
+
const LOG_REVIEW_PAGE_SIZE = 100;
|
|
13906
|
+
|
|
13691
13907
|
// Stored copy of caccl functions
|
|
13692
13908
|
let _cacclGetLaunchInfo;
|
|
13693
13909
|
// Stored copy of dce-mango log collection
|
|
@@ -14036,12 +14252,12 @@ const initServer = (opts) => {
|
|
|
14036
14252
|
// Query for logs
|
|
14037
14253
|
const response = yield _logCollection.findPaged({
|
|
14038
14254
|
query,
|
|
14039
|
-
perPage:
|
|
14255
|
+
perPage: LOG_REVIEW_PAGE_SIZE,
|
|
14040
14256
|
pageNumber,
|
|
14041
14257
|
});
|
|
14042
14258
|
// Count documents if requested
|
|
14043
14259
|
if (countDocuments) {
|
|
14044
|
-
response.numPages = Math.ceil((yield _logCollection.count(query)) /
|
|
14260
|
+
response.numPages = Math.ceil((yield _logCollection.count(query)) / LOG_REVIEW_PAGE_SIZE);
|
|
14045
14261
|
}
|
|
14046
14262
|
// Return response
|
|
14047
14263
|
return response;
|
|
@@ -14859,16 +15075,16 @@ const genRouteHandler = (opts) => {
|
|
|
14859
15075
|
const { timestamp, year, month, day, hour, minute, } = getTimeInfoInET();
|
|
14860
15076
|
// Main log info
|
|
14861
15077
|
const mainLogInfo = {
|
|
14862
|
-
id: `${launchInfo ? 'unknown'
|
|
14863
|
-
userFirstName: (launchInfo ? 'unknown'
|
|
14864
|
-
userLastName: (launchInfo ? 'unknown'
|
|
14865
|
-
userEmail: (launchInfo ? 'unknown'
|
|
14866
|
-
userId: (launchInfo ? 'unknown'
|
|
15078
|
+
id: `${launchInfo ? launchInfo.userId : 'unknown'}-${Date.now()}-${Math.floor(Math.random() * 100000)}-${Math.floor(Math.random() * 100000)}`,
|
|
15079
|
+
userFirstName: (launchInfo ? launchInfo.userFirstName : 'unknown'),
|
|
15080
|
+
userLastName: (launchInfo ? launchInfo.userLastName : 'unknown'),
|
|
15081
|
+
userEmail: (launchInfo ? launchInfo.userEmail : 'unknown'),
|
|
15082
|
+
userId: (launchInfo ? launchInfo.userId : 'unknown'),
|
|
14867
15083
|
isLearner: (launchInfo && !!launchInfo.isLearner),
|
|
14868
15084
|
isAdmin: (launchInfo && !!launchInfo.isAdmin),
|
|
14869
15085
|
isTTM: (launchInfo && !!launchInfo.isTTM),
|
|
14870
|
-
courseId: (launchInfo ? 'unknown'
|
|
14871
|
-
courseName: (launchInfo ? 'unknown'
|
|
15086
|
+
courseId: (launchInfo ? launchInfo.courseId : 'unknown'),
|
|
15087
|
+
courseName: (launchInfo ? launchInfo.contextLabel : 'unknown'),
|
|
14872
15088
|
browser,
|
|
14873
15089
|
device,
|
|
14874
15090
|
year,
|
|
@@ -15275,6 +15491,11 @@ const initLogCollection = (Collection) => {
|
|
|
15275
15491
|
'context',
|
|
15276
15492
|
'subcontext',
|
|
15277
15493
|
'tags',
|
|
15494
|
+
'year',
|
|
15495
|
+
'month',
|
|
15496
|
+
'day',
|
|
15497
|
+
'hour',
|
|
15498
|
+
'type',
|
|
15278
15499
|
],
|
|
15279
15500
|
});
|
|
15280
15501
|
};
|
|
@@ -16296,6 +16517,7 @@ exports.padDecimalZeros = padDecimalZeros;
|
|
|
16296
16517
|
exports.padZerosLeft = padZerosLeft;
|
|
16297
16518
|
exports.parallelLimit = parallelLimit;
|
|
16298
16519
|
exports.prefixWithAOrAn = prefixWithAOrAn;
|
|
16520
|
+
exports.prompt = prompt;
|
|
16299
16521
|
exports.roundToNumDecimals = roundToNumDecimals;
|
|
16300
16522
|
exports.setClientEventMetadataPopulator = setClientEventMetadataPopulator;
|
|
16301
16523
|
exports.showFatalError = showFatalError;
|