dce-reactkit 3.2.2-beta.2 → 3.2.2-beta.21
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 +357 -198
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ButtonInputGroup.d.ts +1 -0
- package/dist/cjs/types/components/ItemPicker/NestableItemList.d.ts +1 -0
- package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/types/server/initServer.d.ts +1 -1
- package/dist/cjs/types/types/LogBuiltInMetadata.d.ts +1 -1
- package/dist/esm/index.js +357 -199
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ButtonInputGroup.d.ts +1 -0
- package/dist/esm/types/components/ItemPicker/NestableItemList.d.ts +1 -0
- package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/types/server/initServer.d.ts +1 -1
- package/dist/esm/types/types/LogBuiltInMetadata.d.ts +1 -1
- package/dist/index.d.ts +12 -3
- package/package.json +1 -1
- package/src/components/ButtonInputGroup.tsx +4 -1
- package/src/components/IntelliTable.tsx +4 -4
- package/src/components/ItemPicker/NestableItemList.tsx +32 -14
- package/src/components/ItemPicker/index.tsx +4 -0
- package/src/components/LogReviewer.tsx +281 -131
- package/src/components/SimpleDateChooser.tsx +20 -7
- package/src/constants/LOG_REVIEW_STATUS_ROUTE.ts +1 -1
- package/src/helpers/genRouteHandler.ts +1 -1
- package/src/helpers/logClientEvent.tsx +6 -1
- package/src/index.ts +2 -0
- package/src/server/initServer.ts +93 -73
- package/src/types/LogBuiltInMetadata.ts +5 -5
package/dist/esm/index.js
CHANGED
|
@@ -511,17 +511,29 @@ const LOG_ROUTE_PATH = `${ROUTE_PATH_PREFIX}/log`;
|
|
|
511
511
|
const LogBuiltInMetadata = {
|
|
512
512
|
// Contexts
|
|
513
513
|
Context: {
|
|
514
|
-
Uncategorized: '
|
|
515
|
-
ServerRenderedErrorPage: '
|
|
516
|
-
ServerEndpointError: '
|
|
517
|
-
ClientFatalError: '
|
|
514
|
+
Uncategorized: 'Uncategorized',
|
|
515
|
+
ServerRenderedErrorPage: 'ServerRenderedErrorPage',
|
|
516
|
+
ServerEndpointError: 'ServerEndpointError',
|
|
517
|
+
ClientFatalError: 'ClientFatalError',
|
|
518
518
|
},
|
|
519
519
|
// Targets
|
|
520
520
|
Target: {
|
|
521
|
-
|
|
521
|
+
NoTarget: 'NoTarget',
|
|
522
522
|
},
|
|
523
523
|
};
|
|
524
524
|
|
|
525
|
+
/**
|
|
526
|
+
* Allowed log levels
|
|
527
|
+
* @author Gabe Abrams
|
|
528
|
+
*/
|
|
529
|
+
var LogLevel;
|
|
530
|
+
(function (LogLevel) {
|
|
531
|
+
LogLevel["Warn"] = "Warn";
|
|
532
|
+
LogLevel["Info"] = "Info";
|
|
533
|
+
LogLevel["Debug"] = "Debug";
|
|
534
|
+
})(LogLevel || (LogLevel = {}));
|
|
535
|
+
var LogLevel$1 = LogLevel;
|
|
536
|
+
|
|
525
537
|
// Keep track of whether or not session expiry has already been handled
|
|
526
538
|
let sessionAlreadyExpired = false;
|
|
527
539
|
/*------------------------------------------------------------------------*/
|
|
@@ -640,7 +652,7 @@ const visitServerEndpoint = (opts) => __awaiter(void 0, void 0, void 0, function
|
|
|
640
652
|
* @author Gabe Abrams
|
|
641
653
|
*/
|
|
642
654
|
const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
643
|
-
var _a, _b, _c, _d, _e, _f;
|
|
655
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
644
656
|
return visitServerEndpoint({
|
|
645
657
|
path: LOG_ROUTE_PATH,
|
|
646
658
|
method: 'POST',
|
|
@@ -649,8 +661,9 @@ const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
649
661
|
? opts.context
|
|
650
662
|
: ((_b = ((_a = opts.context) !== null && _a !== void 0 ? _a : {})._) !== null && _b !== void 0 ? _b : LogBuiltInMetadata.Context.Uncategorized)),
|
|
651
663
|
subcontext: ((_c = opts.subcontext) !== null && _c !== void 0 ? _c : LogBuiltInMetadata.Context.Uncategorized),
|
|
652
|
-
|
|
653
|
-
|
|
664
|
+
level: ((_d = opts.level) !== null && _d !== void 0 ? _d : LogLevel$1.Info),
|
|
665
|
+
tags: JSON.stringify((_e = opts.tags) !== null && _e !== void 0 ? _e : []),
|
|
666
|
+
metadata: JSON.stringify((_f = opts.metadata) !== null && _f !== void 0 ? _f : {}),
|
|
654
667
|
errorMessage: (opts.error
|
|
655
668
|
? opts.error.message
|
|
656
669
|
: undefined),
|
|
@@ -661,7 +674,7 @@ const logClientEvent = (opts) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
661
674
|
? opts.error.stack
|
|
662
675
|
: undefined),
|
|
663
676
|
target: (opts.action
|
|
664
|
-
? ((
|
|
677
|
+
? ((_g = opts.target) !== null && _g !== void 0 ? _g : LogBuiltInMetadata.Target.NoTarget)
|
|
665
678
|
: undefined),
|
|
666
679
|
action: (opts.action
|
|
667
680
|
? opts.action
|
|
@@ -1167,14 +1180,14 @@ const ButtonInputGroup = (props) => {
|
|
|
1167
1180
|
/*------------------------------------------------------------------------*/
|
|
1168
1181
|
/* -------------- Props ------------- */
|
|
1169
1182
|
// Destructure all props
|
|
1170
|
-
const { label, minLabelWidth, children, } = props;
|
|
1183
|
+
const { label, minLabelWidth, children, className, } = props;
|
|
1171
1184
|
/*------------------------------------------------------------------------*/
|
|
1172
1185
|
/* Render */
|
|
1173
1186
|
/*------------------------------------------------------------------------*/
|
|
1174
1187
|
/*----------------------------------------*/
|
|
1175
1188
|
/* Main UI */
|
|
1176
1189
|
/*----------------------------------------*/
|
|
1177
|
-
return (React.createElement("div", { className:
|
|
1190
|
+
return (React.createElement("div", { className: `input-group ${className !== null && className !== void 0 ? className : ''}` },
|
|
1178
1191
|
React.createElement("div", { className: "input-group-prepend d-flex w-100" },
|
|
1179
1192
|
React.createElement("span", { className: "input-group-text", style: {
|
|
1180
1193
|
minWidth: (minLabelWidth !== null && minLabelWidth !== void 0 ? minLabelWidth : undefined),
|
|
@@ -1344,12 +1357,25 @@ const SimpleDateChooser = (props) => {
|
|
|
1344
1357
|
// Figure out which days are allowed
|
|
1345
1358
|
const days = [];
|
|
1346
1359
|
const numDaysInMonth = (new Date(year, month, 0)).getDate();
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1360
|
+
if (chooseFromPast) {
|
|
1361
|
+
// Past selection
|
|
1362
|
+
const numDaysToAdd = ((month === today.month)
|
|
1363
|
+
? today.day // Current month, only add up to today
|
|
1364
|
+
: numDaysInMonth // Past month, add all days
|
|
1365
|
+
);
|
|
1366
|
+
for (let day = 1; day <= numDaysToAdd; day++) {
|
|
1367
|
+
days.push(day);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
else {
|
|
1371
|
+
// Future selection: add all remaining days of the month
|
|
1372
|
+
const firstDay = (month === today.month
|
|
1373
|
+
? today.day // Current month: start at current date
|
|
1374
|
+
: 1 // Future month: start at beginning of month
|
|
1375
|
+
);
|
|
1376
|
+
for (let day = firstDay; day <= numDaysInMonth; day++) {
|
|
1377
|
+
days.push(day);
|
|
1378
|
+
}
|
|
1353
1379
|
}
|
|
1354
1380
|
choices.push({
|
|
1355
1381
|
choiceName: `${monthName} ${year}`,
|
|
@@ -1890,24 +1916,25 @@ const CopiableBox = (props) => {
|
|
|
1890
1916
|
/**
|
|
1891
1917
|
* Reusable nested item picker
|
|
1892
1918
|
* @author Yuen Ler Chow
|
|
1919
|
+
* @author Gabe Abrams
|
|
1893
1920
|
*/
|
|
1894
1921
|
/* ------------- Actions ------------ */
|
|
1895
1922
|
// Types of actions
|
|
1896
1923
|
var ActionType$2;
|
|
1897
1924
|
(function (ActionType) {
|
|
1898
|
-
// Toggle whether
|
|
1899
|
-
ActionType["
|
|
1925
|
+
// Toggle whether a child are being shown
|
|
1926
|
+
ActionType["ToggleChild"] = "toggle-child";
|
|
1900
1927
|
})(ActionType$2 || (ActionType$2 = {}));
|
|
1901
1928
|
/**
|
|
1902
1929
|
* Reducer that executes actions
|
|
1903
|
-
* @author
|
|
1930
|
+
* @author Gabe Abrams
|
|
1904
1931
|
* @param state current state
|
|
1905
1932
|
* @param action action to execute
|
|
1906
1933
|
*/
|
|
1907
1934
|
const reducer$2 = (state, action) => {
|
|
1908
1935
|
switch (action.type) {
|
|
1909
|
-
case ActionType$2.
|
|
1910
|
-
return {
|
|
1936
|
+
case ActionType$2.ToggleChild: {
|
|
1937
|
+
return Object.assign(Object.assign({}, state), { childExpanded: Object.assign(Object.assign({}, state.childExpanded), { [String(action.id)]: !state.childExpanded[String(action.id)] }) });
|
|
1911
1938
|
}
|
|
1912
1939
|
default: {
|
|
1913
1940
|
return state;
|
|
@@ -1925,14 +1952,19 @@ const NestableItemList = (props) => {
|
|
|
1925
1952
|
// Destructure all props
|
|
1926
1953
|
const { items, onChanged, } = props;
|
|
1927
1954
|
/* -------------- State ------------- */
|
|
1955
|
+
// Create initial map of child expanded booleans
|
|
1956
|
+
const initChildExpanded = {};
|
|
1957
|
+
items.forEach((item) => {
|
|
1958
|
+
initChildExpanded[String(item.id)] = false;
|
|
1959
|
+
});
|
|
1928
1960
|
// Initial state
|
|
1929
1961
|
const initialState = {
|
|
1930
|
-
|
|
1962
|
+
childExpanded: initChildExpanded,
|
|
1931
1963
|
};
|
|
1932
1964
|
// Initialize state
|
|
1933
1965
|
const [state, dispatch] = useReducer(reducer$2, initialState);
|
|
1934
1966
|
// Destructure common state
|
|
1935
|
-
const {
|
|
1967
|
+
const { childExpanded, } = state;
|
|
1936
1968
|
/*------------------------------------------------------------------------*/
|
|
1937
1969
|
/* Component Functions */
|
|
1938
1970
|
/*------------------------------------------------------------------------*/
|
|
@@ -2020,14 +2052,15 @@ const NestableItemList = (props) => {
|
|
|
2020
2052
|
backgroundColor: 'transparent',
|
|
2021
2053
|
}, type: "button", onClick: () => {
|
|
2022
2054
|
dispatch({
|
|
2023
|
-
type: ActionType$2.
|
|
2055
|
+
type: ActionType$2.ToggleChild,
|
|
2056
|
+
id: item.id,
|
|
2024
2057
|
});
|
|
2025
|
-
}, "aria-label": `${
|
|
2026
|
-
React.createElement(FontAwesomeIcon, { icon:
|
|
2058
|
+
}, "aria-label": `${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${item.name}` },
|
|
2059
|
+
React.createElement(FontAwesomeIcon, { icon: childExpanded[item.id] ? faChevronDown : faChevronRight })))),
|
|
2027
2060
|
React.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) => {
|
|
2028
2061
|
onChanged(changeChecked(item.id, checked, items));
|
|
2029
2062
|
}, ariaLabel: `Select ${item.name}`, checkedVariant: Variant$1.Light }),
|
|
2030
|
-
item.isGroup &&
|
|
2063
|
+
(item.isGroup && childExpanded[item.id]) && (React.createElement("div", { className: "NestableItemList-children-container", style: {
|
|
2031
2064
|
paddingLeft: '2.2rem',
|
|
2032
2065
|
} },
|
|
2033
2066
|
React.createElement(NestableItemList, { items: item.children, onChanged: (updatedItems) => {
|
|
@@ -2049,7 +2082,7 @@ const ItemPicker = (props) => {
|
|
|
2049
2082
|
/*------------------------------------------------------------------------*/
|
|
2050
2083
|
/* -------------- Props ------------- */
|
|
2051
2084
|
// Destructure all props
|
|
2052
|
-
const { title, items, onChanged, } = props;
|
|
2085
|
+
const { title, items, onChanged, noBottomMargin, } = props;
|
|
2053
2086
|
/*------------------------------------------------------------------------*/
|
|
2054
2087
|
/* Component Functions */
|
|
2055
2088
|
/*------------------------------------------------------------------------*/
|
|
@@ -2059,7 +2092,7 @@ const ItemPicker = (props) => {
|
|
|
2059
2092
|
/*----------------------------------------*/
|
|
2060
2093
|
/* Main UI */
|
|
2061
2094
|
/*----------------------------------------*/
|
|
2062
|
-
return (React.createElement(TabBox, { title: title },
|
|
2095
|
+
return (React.createElement(TabBox, { title: title, noBottomMargin: noBottomMargin },
|
|
2063
2096
|
React.createElement("div", { style: { overflowX: 'auto' } },
|
|
2064
2097
|
React.createElement(NestableItemList, { items: items, onChanged: onChanged }))));
|
|
2065
2098
|
};
|
|
@@ -2376,9 +2409,9 @@ const IntelliTable = (props) => {
|
|
|
2376
2409
|
// Create the cell UI
|
|
2377
2410
|
return (React.createElement("th", { key: column.param, scope: "col", id: `IntelliTable-${id}-header-${column.param}` },
|
|
2378
2411
|
React.createElement("div", { className: "d-flex align-items-center justify-content-center flex-row h-100" },
|
|
2379
|
-
React.createElement("
|
|
2412
|
+
React.createElement("span", { className: "text-nowrap" }, column.title),
|
|
2380
2413
|
React.createElement("div", null,
|
|
2381
|
-
React.createElement("button", { type: "button", className: "btn btn-light", "aria-label": sortButtonAriaLabel, onClick: () => {
|
|
2414
|
+
React.createElement("button", { type: "button", className: "btn btn-light btn-sm ms-1", "aria-label": sortButtonAriaLabel, onClick: () => {
|
|
2382
2415
|
dispatch({
|
|
2383
2416
|
type: ActionType$1.ToggleSortColumn,
|
|
2384
2417
|
param: column.param,
|
|
@@ -2526,7 +2559,7 @@ const IntelliTable = (props) => {
|
|
|
2526
2559
|
React.createElement("h3", { className: "m-0" }, title),
|
|
2527
2560
|
React.createElement("div", { className: "flex-grow-1 text-end" },
|
|
2528
2561
|
React.createElement(CSVDownloadButton, { "aria-label": `download data as csv for ${title}`, id: `IntelliTable-${id}-download-as-csv`, filename: `${title}.csv`, csv: csv }),
|
|
2529
|
-
React.createElement("button", { type: "button", className: "btn btn-secondary", "aria-label": `show panel for customizing which columns show in table ${title}`, id: `IntelliTable-${id}-show-column-customization-modal`, onClick: () => {
|
|
2562
|
+
React.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: () => {
|
|
2530
2563
|
dispatch({
|
|
2531
2564
|
type: ActionType$1.ToggleColVisCusModalVisibility,
|
|
2532
2565
|
});
|
|
@@ -2590,6 +2623,11 @@ const style = `
|
|
|
2590
2623
|
border: 0.05rem solid black;
|
|
2591
2624
|
border-radius: 0.5rem;
|
|
2592
2625
|
overflow: hidden;
|
|
2626
|
+
padding: 0.7rem;
|
|
2627
|
+
|
|
2628
|
+
/* Solid background */
|
|
2629
|
+
background-color: white;
|
|
2630
|
+
color: black;
|
|
2593
2631
|
|
|
2594
2632
|
/* Place contents in flex column */
|
|
2595
2633
|
flex-direction: column;
|
|
@@ -2616,6 +2654,27 @@ const style = `
|
|
|
2616
2654
|
/* Vertical scroll */
|
|
2617
2655
|
overflow-y: auto;
|
|
2618
2656
|
}
|
|
2657
|
+
|
|
2658
|
+
.LogReviewer-header-close-button {
|
|
2659
|
+
border: 0 !important;
|
|
2660
|
+
background-color: transparent !important;
|
|
2661
|
+
padding-top: 0 !important;
|
|
2662
|
+
padding-bottom: 0 !important;
|
|
2663
|
+
padding-right: 1em !important;
|
|
2664
|
+
margin: 0 !important;
|
|
2665
|
+
color: #444 !important;
|
|
2666
|
+
|
|
2667
|
+
right: 0 !important;
|
|
2668
|
+
position: absolute !important;
|
|
2669
|
+
}
|
|
2670
|
+
.LogReviewer-header-close-button:hover {
|
|
2671
|
+
border: 0 !important;
|
|
2672
|
+
background-color: transparent !important;
|
|
2673
|
+
padding-top: 0 !important;
|
|
2674
|
+
padding-bottom: 0 !important;
|
|
2675
|
+
margin: 0 !important;
|
|
2676
|
+
color: #000 !important;
|
|
2677
|
+
}
|
|
2619
2678
|
`;
|
|
2620
2679
|
/*------------------------------------------------------------------------*/
|
|
2621
2680
|
/* Static Functions */
|
|
@@ -2635,7 +2694,7 @@ const genHumanReadableName = (machineReadableName) => {
|
|
|
2635
2694
|
// Uppercase! Add a space before
|
|
2636
2695
|
humanReadableName += ' ';
|
|
2637
2696
|
}
|
|
2638
|
-
humanReadableName +=
|
|
2697
|
+
humanReadableName += char;
|
|
2639
2698
|
});
|
|
2640
2699
|
// Trim and return
|
|
2641
2700
|
return humanReadableName.trim();
|
|
@@ -2697,7 +2756,19 @@ const reducer = (state, action) => {
|
|
|
2697
2756
|
return Object.assign(Object.assign({}, state), { contextFilterState: action.contextFilterState });
|
|
2698
2757
|
}
|
|
2699
2758
|
case ActionType.UpdateTagFilterState: {
|
|
2700
|
-
|
|
2759
|
+
const { tagFilterState } = action;
|
|
2760
|
+
// Select all if every tag is deselected
|
|
2761
|
+
const numTagsSelected = (Object.values(tagFilterState)
|
|
2762
|
+
.filter((isSelected) => {
|
|
2763
|
+
return isSelected;
|
|
2764
|
+
})
|
|
2765
|
+
.length);
|
|
2766
|
+
if (numTagsSelected === 0) {
|
|
2767
|
+
Object.keys(tagFilterState).forEach((tag) => {
|
|
2768
|
+
tagFilterState[tag] = true;
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2771
|
+
return Object.assign(Object.assign({}, state), { tagFilterState });
|
|
2701
2772
|
}
|
|
2702
2773
|
case ActionType.UpdateActionErrorFilterState: {
|
|
2703
2774
|
return Object.assign(Object.assign({}, state), { actionErrorFilterState: action.actionErrorFilterState });
|
|
@@ -2717,10 +2788,33 @@ const LogReviewer = (props) => {
|
|
|
2717
2788
|
/*------------------------------------------------------------------------*/
|
|
2718
2789
|
/* Setup */
|
|
2719
2790
|
/*------------------------------------------------------------------------*/
|
|
2720
|
-
var _a, _b, _c, _d, _e;
|
|
2791
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
2721
2792
|
/* -------------- Props ------------- */
|
|
2722
2793
|
// Destructure props
|
|
2723
2794
|
const { LogMetadata, onClose, } = props;
|
|
2795
|
+
// Add built-in LogMetadata
|
|
2796
|
+
// > Add "uncategorized" subcontext to each context
|
|
2797
|
+
Object.keys((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {}).forEach((context) => {
|
|
2798
|
+
if (LogMetadata.Context
|
|
2799
|
+
// Context has children already
|
|
2800
|
+
&& typeof LogMetadata.Context[context] !== 'string') {
|
|
2801
|
+
LogMetadata.Context[context][LogBuiltInMetadata.Context.Uncategorized] = (LogBuiltInMetadata.Context.Uncategorized);
|
|
2802
|
+
}
|
|
2803
|
+
});
|
|
2804
|
+
// > Add built-in contexts
|
|
2805
|
+
LogMetadata.Context = ((_b = LogMetadata.Context) !== null && _b !== void 0 ? _b : {});
|
|
2806
|
+
Object.keys(LogBuiltInMetadata.Context).forEach((context) => {
|
|
2807
|
+
if (LogMetadata.Context) {
|
|
2808
|
+
LogMetadata.Context[context] = context;
|
|
2809
|
+
}
|
|
2810
|
+
});
|
|
2811
|
+
// > Add built-in targets
|
|
2812
|
+
LogMetadata.Target = ((_c = LogMetadata.Target) !== null && _c !== void 0 ? _c : {});
|
|
2813
|
+
Object.keys(LogBuiltInMetadata.Target).forEach((target) => {
|
|
2814
|
+
if (LogMetadata.Target) {
|
|
2815
|
+
LogMetadata.Target[target] = target;
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2724
2818
|
/* -------------- State ------------- */
|
|
2725
2819
|
// Create initial date filter state
|
|
2726
2820
|
const today = getTimeInfoInET();
|
|
@@ -2740,7 +2834,7 @@ const LogReviewer = (props) => {
|
|
|
2740
2834
|
};
|
|
2741
2835
|
// Create initial context filter state
|
|
2742
2836
|
const initContextFilterState = {};
|
|
2743
|
-
Object.keys((
|
|
2837
|
+
Object.keys((_d = LogMetadata.Context) !== null && _d !== void 0 ? _d : {}).forEach((context) => {
|
|
2744
2838
|
var _a, _b;
|
|
2745
2839
|
const contextValue = ((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {})[context];
|
|
2746
2840
|
if (typeof contextValue === 'string') {
|
|
@@ -2758,7 +2852,7 @@ const LogReviewer = (props) => {
|
|
|
2758
2852
|
});
|
|
2759
2853
|
// Create initial tag filter state
|
|
2760
2854
|
const initTagFilterState = {};
|
|
2761
|
-
Object.values((
|
|
2855
|
+
Object.values((_e = LogMetadata.Tag) !== null && _e !== void 0 ? _e : {}).forEach((tagValue) => {
|
|
2762
2856
|
initTagFilterState[tagValue] = true;
|
|
2763
2857
|
});
|
|
2764
2858
|
// Create advanced filter state
|
|
@@ -2785,12 +2879,16 @@ const LogReviewer = (props) => {
|
|
|
2785
2879
|
target: {},
|
|
2786
2880
|
action: {},
|
|
2787
2881
|
};
|
|
2788
|
-
Object.values((
|
|
2882
|
+
Object.values((_f = LogMetadata.Target) !== null && _f !== void 0 ? _f : {}).forEach((target) => {
|
|
2789
2883
|
initActionErrorFilterState.target[target] = true;
|
|
2790
2884
|
});
|
|
2791
2885
|
Object.values(LogAction$1).forEach((action) => {
|
|
2792
2886
|
initActionErrorFilterState.action[action] = true;
|
|
2793
2887
|
});
|
|
2888
|
+
// Add built-in targets
|
|
2889
|
+
Object.values(LogBuiltInMetadata.Target).forEach((target) => {
|
|
2890
|
+
initActionErrorFilterState.target[target] = true;
|
|
2891
|
+
});
|
|
2794
2892
|
// Initial state
|
|
2795
2893
|
const initialState = {
|
|
2796
2894
|
loading: true,
|
|
@@ -2824,15 +2922,18 @@ const LogReviewer = (props) => {
|
|
|
2824
2922
|
let month = newDateFilterState.startDate.month;
|
|
2825
2923
|
while (
|
|
2826
2924
|
// Earlier year
|
|
2827
|
-
(year
|
|
2925
|
+
(year < newDateFilterState.endDate.year)
|
|
2828
2926
|
// Current year but included month
|
|
2829
2927
|
|| (year === newDateFilterState.endDate.year
|
|
2830
2928
|
&& month <= newDateFilterState.endDate.month)) {
|
|
2831
|
-
// Add to list
|
|
2832
|
-
|
|
2833
|
-
year
|
|
2834
|
-
|
|
2835
|
-
|
|
2929
|
+
// Add to list if not already loaded
|
|
2930
|
+
if (!logMap[year]
|
|
2931
|
+
|| !logMap[year][month]) {
|
|
2932
|
+
toLoad.push({
|
|
2933
|
+
year,
|
|
2934
|
+
month,
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2836
2937
|
// Increment
|
|
2837
2938
|
month += 1;
|
|
2838
2939
|
if (month > 12) {
|
|
@@ -2856,6 +2957,7 @@ const LogReviewer = (props) => {
|
|
|
2856
2957
|
});
|
|
2857
2958
|
// Check which year/month combos we need to load
|
|
2858
2959
|
const toLoad = listMonthsToLoad(newDateFilterState);
|
|
2960
|
+
console.log('Filter update:', newDateFilterState, toLoad, logMap);
|
|
2859
2961
|
// If nothing to load, finished
|
|
2860
2962
|
if (toLoad.length === 0) {
|
|
2861
2963
|
return;
|
|
@@ -2920,10 +3022,10 @@ const LogReviewer = (props) => {
|
|
|
2920
3022
|
/* Filters */
|
|
2921
3023
|
/*----------------------------------------*/
|
|
2922
3024
|
// Filter toggle
|
|
2923
|
-
const filterToggles = (React.createElement("div", { className: "LogReviewer-filter-toggles
|
|
3025
|
+
const filterToggles = (React.createElement("div", { className: "LogReviewer-filter-toggles" },
|
|
2924
3026
|
React.createElement("h3", { className: "m-0" }, "Filters:"),
|
|
2925
|
-
React.createElement("div", { className: "LogReviewer-filter-toggle-buttons" },
|
|
2926
|
-
React.createElement("button", { type: "button", id: "LogReviewer-toggle-date-filter-drawer", className: `btn btn-${FilterDrawer.Date === expandedFilterDrawer} me-2`, "aria-label": "toggle date filter drawer", onClick: () => {
|
|
3027
|
+
React.createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
|
|
3028
|
+
React.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: () => {
|
|
2927
3029
|
dispatch({
|
|
2928
3030
|
type: ActionType.ToggleFilterDrawer,
|
|
2929
3031
|
filterDrawer: FilterDrawer.Date,
|
|
@@ -2931,7 +3033,7 @@ const LogReviewer = (props) => {
|
|
|
2931
3033
|
} },
|
|
2932
3034
|
React.createElement(FontAwesomeIcon, { icon: faCalendar, className: "me-2" }),
|
|
2933
3035
|
"Date"),
|
|
2934
|
-
React.createElement("button", { type: "button", id: "LogReviewer-toggle-context-filter-drawer", className: `btn btn-${FilterDrawer.Context === expandedFilterDrawer} me-2`, "aria-label": "toggle context filter drawer", onClick: () => {
|
|
3036
|
+
React.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: () => {
|
|
2935
3037
|
dispatch({
|
|
2936
3038
|
type: ActionType.ToggleFilterDrawer,
|
|
2937
3039
|
filterDrawer: FilterDrawer.Context,
|
|
@@ -2939,15 +3041,15 @@ const LogReviewer = (props) => {
|
|
|
2939
3041
|
} },
|
|
2940
3042
|
React.createElement(FontAwesomeIcon, { icon: faCircle, className: "me-2" }),
|
|
2941
3043
|
"Context"),
|
|
2942
|
-
React.createElement("button", { type: "button", id: "LogReviewer-toggle-tag-filter-drawer", className: `btn btn-${FilterDrawer.Tag === expandedFilterDrawer} me-2`, "aria-label": "toggle tag filter drawer", onClick: () => {
|
|
3044
|
+
(LogMetadata.Tag && Object.keys(LogMetadata.Tag).length > 0) && (React.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: () => {
|
|
2943
3045
|
dispatch({
|
|
2944
3046
|
type: ActionType.ToggleFilterDrawer,
|
|
2945
3047
|
filterDrawer: FilterDrawer.Tag,
|
|
2946
3048
|
});
|
|
2947
3049
|
} },
|
|
2948
3050
|
React.createElement(FontAwesomeIcon, { icon: faTag, className: "me-2" }),
|
|
2949
|
-
"Tag"),
|
|
2950
|
-
React.createElement("button", { type: "button", id: "LogReviewer-toggle-action-filter-drawer", className: `btn btn-${FilterDrawer.Action === expandedFilterDrawer} me-2`, "aria-label": "toggle action and error filter drawer", onClick: () => {
|
|
3051
|
+
"Tag")),
|
|
3052
|
+
React.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: () => {
|
|
2951
3053
|
dispatch({
|
|
2952
3054
|
type: ActionType.ToggleFilterDrawer,
|
|
2953
3055
|
filterDrawer: FilterDrawer.Action,
|
|
@@ -2955,7 +3057,7 @@ const LogReviewer = (props) => {
|
|
|
2955
3057
|
} },
|
|
2956
3058
|
React.createElement(FontAwesomeIcon, { icon: faHammer, className: "me-2" }),
|
|
2957
3059
|
"Action"),
|
|
2958
|
-
React.createElement("button", { type: "button", id: "LogReviewer-toggle-advanced-filter-drawer", className: `btn btn-${FilterDrawer.Advanced === expandedFilterDrawer}`, "aria-label": "toggle advanced filter drawer", onClick: () => {
|
|
3060
|
+
React.createElement("button", { type: "button", id: "LogReviewer-toggle-advanced-filter-drawer", className: `btn btn-${FilterDrawer.Advanced === expandedFilterDrawer ? 'warning' : 'light'}`, "aria-label": "toggle advanced filter drawer", onClick: () => {
|
|
2959
3061
|
dispatch({
|
|
2960
3062
|
type: ActionType.ToggleFilterDrawer,
|
|
2961
3063
|
filterDrawer: FilterDrawer.Advanced,
|
|
@@ -2968,25 +3070,29 @@ const LogReviewer = (props) => {
|
|
|
2968
3070
|
if (expandedFilterDrawer) {
|
|
2969
3071
|
if (expandedFilterDrawer === FilterDrawer.Date) {
|
|
2970
3072
|
filterDrawer = (React.createElement(TabBox, { title: "Date" },
|
|
2971
|
-
React.createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: dateFilterState.startDate.year, month: dateFilterState.startDate.month, day: dateFilterState.startDate.day, onChange: (month, day, year) => {
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
dateFilterState: Object.assign(Object.assign({}, dateFilterState), { startDate: { month, day, year } }),
|
|
2975
|
-
});
|
|
3073
|
+
React.createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: dateFilterState.startDate.year, month: dateFilterState.startDate.month, day: dateFilterState.startDate.day, chooseFromPast: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
3074
|
+
dateFilterState.startDate = { month, day, year };
|
|
3075
|
+
handleDateRangeUpdated(dateFilterState);
|
|
2976
3076
|
} }),
|
|
2977
3077
|
' ',
|
|
2978
3078
|
"to",
|
|
2979
3079
|
' ',
|
|
2980
|
-
React.createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: dateFilterState.endDate.year, month: dateFilterState.endDate.month, day: dateFilterState.endDate.day, onChange: (month, day, year) => {
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
3080
|
+
React.createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: dateFilterState.endDate.year, month: dateFilterState.endDate.month, day: dateFilterState.endDate.day, chooseFromPast: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
3081
|
+
if (year < dateFilterState.startDate.year
|
|
3082
|
+
|| (year === dateFilterState.startDate.year
|
|
3083
|
+
&& month < dateFilterState.startDate.month)
|
|
3084
|
+
|| (year === dateFilterState.startDate.year
|
|
3085
|
+
&& month === dateFilterState.startDate.month
|
|
3086
|
+
&& day < dateFilterState.startDate.day)) {
|
|
3087
|
+
return alert$1('Invalid Start Date', 'The start date cannot be before the end date.');
|
|
3088
|
+
}
|
|
3089
|
+
dateFilterState.endDate = { month, day, year };
|
|
3090
|
+
handleDateRangeUpdated(dateFilterState);
|
|
2985
3091
|
} })));
|
|
2986
3092
|
}
|
|
2987
3093
|
else if (expandedFilterDrawer === FilterDrawer.Context) {
|
|
2988
3094
|
// Create item picker items
|
|
2989
|
-
const pickableItems = (Object.keys((
|
|
3095
|
+
const pickableItems = (Object.keys((_g = LogMetadata.Context) !== null && _g !== void 0 ? _g : {})
|
|
2990
3096
|
.map((context) => {
|
|
2991
3097
|
var _a;
|
|
2992
3098
|
const value = ((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {})[context];
|
|
@@ -3007,7 +3113,7 @@ const LogReviewer = (props) => {
|
|
|
3007
3113
|
})
|
|
3008
3114
|
.map((subcontext) => {
|
|
3009
3115
|
return {
|
|
3010
|
-
id:
|
|
3116
|
+
id: subcontext,
|
|
3011
3117
|
name: genHumanReadableName(subcontext),
|
|
3012
3118
|
isGroup: false,
|
|
3013
3119
|
checked: !!value[subcontext],
|
|
@@ -3015,7 +3121,7 @@ const LogReviewer = (props) => {
|
|
|
3015
3121
|
}));
|
|
3016
3122
|
const item = {
|
|
3017
3123
|
id: context,
|
|
3018
|
-
name: context,
|
|
3124
|
+
name: genHumanReadableName(context),
|
|
3019
3125
|
isGroup: true,
|
|
3020
3126
|
children,
|
|
3021
3127
|
};
|
|
@@ -3023,6 +3129,8 @@ const LogReviewer = (props) => {
|
|
|
3023
3129
|
}));
|
|
3024
3130
|
// Create filter UI
|
|
3025
3131
|
filterDrawer = (React.createElement(ItemPicker, { title: "Context", items: pickableItems, onChanged: (updatedItems) => {
|
|
3132
|
+
console.log('Items before:', pickableItems);
|
|
3133
|
+
console.log('Updated Items:', updatedItems);
|
|
3026
3134
|
// Update our state
|
|
3027
3135
|
updatedItems.forEach((pickableItem) => {
|
|
3028
3136
|
if (pickableItem.isGroup) {
|
|
@@ -3079,7 +3187,7 @@ const LogReviewer = (props) => {
|
|
|
3079
3187
|
}, ariaLabel: "only show error logs", selected: actionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true })),
|
|
3080
3188
|
(actionErrorFilterState.type === undefined
|
|
3081
3189
|
|| actionErrorFilterState.type === LogType$1.Action) && (React.createElement(TabBox, { title: "Action Log Details" },
|
|
3082
|
-
React.createElement(ButtonInputGroup, { label: "Action" }, Object.keys(LogAction$1)
|
|
3190
|
+
React.createElement(ButtonInputGroup, { label: "Action", className: "mb-2" }, Object.keys(LogAction$1)
|
|
3083
3191
|
.map((action, i) => {
|
|
3084
3192
|
const description = genHumanReadableName(action);
|
|
3085
3193
|
return (React.createElement(CheckboxButton, { id: `LogReviewer-action-${action}-checkbox`, text: description, ariaLabel: `include logs with action type "${description}" in results`, noMarginOnRight: i === Object.keys(LogAction$1).length - 1, onChanged: (checked) => {
|
|
@@ -3090,18 +3198,20 @@ const LogReviewer = (props) => {
|
|
|
3090
3198
|
});
|
|
3091
3199
|
} }));
|
|
3092
3200
|
})),
|
|
3093
|
-
React.createElement(ButtonInputGroup, { label: "Target" },
|
|
3094
|
-
.
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3201
|
+
React.createElement(ButtonInputGroup, { label: "Target" },
|
|
3202
|
+
(Object.keys((_h = LogMetadata.Target) !== null && _h !== void 0 ? _h : {}).length === 0) && (React.createElement("div", null, "This app does not have any targets yet.")),
|
|
3203
|
+
Object.keys((_j = LogMetadata.Target) !== null && _j !== void 0 ? _j : {})
|
|
3204
|
+
.map((target, i) => {
|
|
3205
|
+
var _a;
|
|
3206
|
+
const description = genHumanReadableName(target);
|
|
3207
|
+
return (React.createElement(CheckboxButton, { id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, onChanged: (checked) => {
|
|
3208
|
+
actionErrorFilterState.target[target] = checked;
|
|
3209
|
+
dispatch({
|
|
3210
|
+
type: ActionType.UpdateActionErrorFilterState,
|
|
3211
|
+
actionErrorFilterState,
|
|
3212
|
+
});
|
|
3213
|
+
}, noMarginOnRight: i === Object.keys((_a = LogMetadata.Target) !== null && _a !== void 0 ? _a : {}).length - 1 }));
|
|
3214
|
+
})))),
|
|
3105
3215
|
(actionErrorFilterState.type === undefined
|
|
3106
3216
|
|| actionErrorFilterState.type === LogType$1.Error) && (React.createElement(TabBox, { title: "Error Log Details" },
|
|
3107
3217
|
React.createElement("div", { className: "input-group mb-2" },
|
|
@@ -3263,26 +3373,27 @@ const LogReviewer = (props) => {
|
|
|
3263
3373
|
advancedFilterState,
|
|
3264
3374
|
});
|
|
3265
3375
|
}, noMarginOnRight: true })),
|
|
3266
|
-
React.createElement("div", { className: "
|
|
3267
|
-
React.createElement("
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
.
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
React.createElement("
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
.
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3376
|
+
advancedFilterState.source !== LogSource$1.Client && (React.createElement("div", { className: "mt-2" },
|
|
3377
|
+
React.createElement("div", { className: "input-group mb-2" },
|
|
3378
|
+
React.createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
3379
|
+
React.createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route path", placeholder: "e.g. /api/ttm/courses/12345", value: advancedFilterState.routePath, onChange: (e) => {
|
|
3380
|
+
advancedFilterState.courseName = ((e.target.value)
|
|
3381
|
+
.trim());
|
|
3382
|
+
dispatch({
|
|
3383
|
+
type: ActionType.UpdateAdvancedFilterState,
|
|
3384
|
+
advancedFilterState,
|
|
3385
|
+
});
|
|
3386
|
+
} })),
|
|
3387
|
+
React.createElement("div", { className: "input-group mb-2" },
|
|
3388
|
+
React.createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
3389
|
+
React.createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route template", value: advancedFilterState.routeTemplate, placeholder: "e.g. /api/ttm/courses/:courseId", onChange: (e) => {
|
|
3390
|
+
advancedFilterState.courseName = ((e.target.value)
|
|
3391
|
+
.trim());
|
|
3392
|
+
dispatch({
|
|
3393
|
+
type: ActionType.UpdateAdvancedFilterState,
|
|
3394
|
+
advancedFilterState,
|
|
3395
|
+
});
|
|
3396
|
+
} })))))));
|
|
3286
3397
|
}
|
|
3287
3398
|
}
|
|
3288
3399
|
// Filters UI
|
|
@@ -3293,10 +3404,11 @@ const LogReviewer = (props) => {
|
|
|
3293
3404
|
// > Perform filters
|
|
3294
3405
|
const logs = [];
|
|
3295
3406
|
Object.keys(logMap).forEach((year) => {
|
|
3296
|
-
Object.keys(logMap).forEach((month) => {
|
|
3407
|
+
Object.keys(logMap[year]).forEach((month) => {
|
|
3297
3408
|
logMap[year][month].forEach((log) => {
|
|
3298
|
-
/* ----------- Date Filter ---------- */
|
|
3299
3409
|
var _a;
|
|
3410
|
+
/* ----------- Date Filter ---------- */
|
|
3411
|
+
console.log('Log:', log);
|
|
3300
3412
|
// Before start date
|
|
3301
3413
|
if (
|
|
3302
3414
|
// Previous year
|
|
@@ -3308,6 +3420,7 @@ const LogReviewer = (props) => {
|
|
|
3308
3420
|
|| ((log.year === dateFilterState.startDate.year)
|
|
3309
3421
|
&& (log.month === dateFilterState.startDate.month)
|
|
3310
3422
|
&& (log.day < dateFilterState.startDate.day))) {
|
|
3423
|
+
console.log('RULED OUT: START');
|
|
3311
3424
|
return;
|
|
3312
3425
|
}
|
|
3313
3426
|
// After end date
|
|
@@ -3321,6 +3434,7 @@ const LogReviewer = (props) => {
|
|
|
3321
3434
|
|| ((log.year === dateFilterState.endDate.year)
|
|
3322
3435
|
&& (log.month === dateFilterState.endDate.month)
|
|
3323
3436
|
&& (log.day > dateFilterState.endDate.day))) {
|
|
3437
|
+
console.log('RULED OUT: END');
|
|
3324
3438
|
return;
|
|
3325
3439
|
}
|
|
3326
3440
|
/* --------- Context Filter --------- */
|
|
@@ -3333,29 +3447,30 @@ const LogReviewer = (props) => {
|
|
|
3333
3447
|
.every((isSelected) => {
|
|
3334
3448
|
return !isSelected;
|
|
3335
3449
|
}))) {
|
|
3450
|
+
console.log('RULED OUT: CONTEXT');
|
|
3336
3451
|
return;
|
|
3337
3452
|
}
|
|
3338
3453
|
// Subcontext doesn't match
|
|
3339
3454
|
if (
|
|
3340
|
-
// Log
|
|
3341
|
-
log.
|
|
3455
|
+
// Log context is not "uncategorized" (no point in further filters)
|
|
3456
|
+
log.context !== LogBuiltInMetadata.Context.Uncategorized
|
|
3457
|
+
// Log has a subcontext
|
|
3458
|
+
&& log.subcontext
|
|
3342
3459
|
// Context has subcontexts
|
|
3343
3460
|
&& (contextFilterState[log.context]
|
|
3344
3461
|
&& contextFilterState[log.context] !== false
|
|
3345
3462
|
&& contextFilterState[log.context] !== true)
|
|
3346
3463
|
// Subcontext is not selected
|
|
3347
3464
|
&& !contextFilterState[log.context][log.subcontext]) {
|
|
3465
|
+
console.log('RULED OUT: SUBCONTEXT');
|
|
3348
3466
|
return;
|
|
3349
3467
|
}
|
|
3350
3468
|
/* -------------- Tags -------------- */
|
|
3351
3469
|
// No tags match
|
|
3352
|
-
if (
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
&& (log.tags.every((tag) => {
|
|
3357
|
-
return !tagFilterState[tag];
|
|
3358
|
-
}))) {
|
|
3470
|
+
if (log.tags.every((tag) => {
|
|
3471
|
+
return !tagFilterState[tag];
|
|
3472
|
+
})) {
|
|
3473
|
+
console.log('RULED OUT: TAGS');
|
|
3359
3474
|
return;
|
|
3360
3475
|
}
|
|
3361
3476
|
/* ------- Actions and Errors ------- */
|
|
@@ -3365,6 +3480,7 @@ const LogReviewer = (props) => {
|
|
|
3365
3480
|
actionErrorFilterState.type !== undefined
|
|
3366
3481
|
// Log type doesn't match
|
|
3367
3482
|
&& actionErrorFilterState.type !== log.type) {
|
|
3483
|
+
console.log('RULED OUT: TYPE');
|
|
3368
3484
|
return;
|
|
3369
3485
|
}
|
|
3370
3486
|
// Filter errors
|
|
@@ -3377,6 +3493,7 @@ const LogReviewer = (props) => {
|
|
|
3377
3493
|
&& actionErrorFilterState.errorMessage.trim().length > 0
|
|
3378
3494
|
// Message doesn't match
|
|
3379
3495
|
&& log.errorMessage.toLowerCase().includes(actionErrorFilterState.errorMessage.trim().toLowerCase())) {
|
|
3496
|
+
console.log('RULED OUT: ERROR MESSAGE');
|
|
3380
3497
|
return;
|
|
3381
3498
|
}
|
|
3382
3499
|
// Code doesn't match
|
|
@@ -3387,6 +3504,7 @@ const LogReviewer = (props) => {
|
|
|
3387
3504
|
&& actionErrorFilterState.errorCode.trim().length > 0
|
|
3388
3505
|
// Code doesn't match
|
|
3389
3506
|
&& log.errorCode.toUpperCase().includes(actionErrorFilterState.errorCode.trim().toUpperCase())) {
|
|
3507
|
+
console.log('RULED OUT: ERROR CODE');
|
|
3390
3508
|
return;
|
|
3391
3509
|
}
|
|
3392
3510
|
}
|
|
@@ -3398,6 +3516,7 @@ const LogReviewer = (props) => {
|
|
|
3398
3516
|
log.target
|
|
3399
3517
|
// Target isn't selected
|
|
3400
3518
|
&& !actionErrorFilterState.target[log.target]) {
|
|
3519
|
+
console.log('RULED OUT: TARGET');
|
|
3401
3520
|
return;
|
|
3402
3521
|
}
|
|
3403
3522
|
// Action
|
|
@@ -3406,6 +3525,7 @@ const LogReviewer = (props) => {
|
|
|
3406
3525
|
log.action
|
|
3407
3526
|
// Action isn't selected
|
|
3408
3527
|
&& !actionErrorFilterState.action[log.action]) {
|
|
3528
|
+
console.log('RULED OUT: ACTION');
|
|
3409
3529
|
return;
|
|
3410
3530
|
}
|
|
3411
3531
|
}
|
|
@@ -3416,6 +3536,7 @@ const LogReviewer = (props) => {
|
|
|
3416
3536
|
log.userFirstName
|
|
3417
3537
|
// First name query doesn't match
|
|
3418
3538
|
&& !log.userFirstName.toLowerCase().includes(advancedFilterState.userFirstName.toLowerCase().trim())) {
|
|
3539
|
+
console.log('RULED OUT: FIRST');
|
|
3419
3540
|
return;
|
|
3420
3541
|
}
|
|
3421
3542
|
// Last name doesn't match
|
|
@@ -3424,6 +3545,7 @@ const LogReviewer = (props) => {
|
|
|
3424
3545
|
log.userLastName
|
|
3425
3546
|
// Last name query doesn't match
|
|
3426
3547
|
&& !log.userLastName.toLowerCase().includes(advancedFilterState.userLastName.toLowerCase().trim())) {
|
|
3548
|
+
console.log('RULED OUT: LAST');
|
|
3427
3549
|
return;
|
|
3428
3550
|
}
|
|
3429
3551
|
// Email doesn't match
|
|
@@ -3432,6 +3554,7 @@ const LogReviewer = (props) => {
|
|
|
3432
3554
|
log.userEmail
|
|
3433
3555
|
// Email query doesn't match
|
|
3434
3556
|
&& !log.userEmail.toLowerCase().includes(advancedFilterState.userEmail.toLowerCase().trim())) {
|
|
3557
|
+
console.log('RULED OUT: EMAIL');
|
|
3435
3558
|
return;
|
|
3436
3559
|
}
|
|
3437
3560
|
// User id doesn't match
|
|
@@ -3440,6 +3563,7 @@ const LogReviewer = (props) => {
|
|
|
3440
3563
|
log.userId
|
|
3441
3564
|
// User id doesn't match
|
|
3442
3565
|
&& !String(log.userId).includes(advancedFilterState.userId.trim())) {
|
|
3566
|
+
console.log('RULED OUT: USER ID');
|
|
3443
3567
|
return;
|
|
3444
3568
|
}
|
|
3445
3569
|
// Learner not allowed
|
|
@@ -3448,6 +3572,7 @@ const LogReviewer = (props) => {
|
|
|
3448
3572
|
log.isLearner
|
|
3449
3573
|
// Learners aren't included
|
|
3450
3574
|
&& !advancedFilterState.includeLearners) {
|
|
3575
|
+
console.log('RULED OUT: LEARNER');
|
|
3451
3576
|
return;
|
|
3452
3577
|
}
|
|
3453
3578
|
// TTM not allowed
|
|
@@ -3456,6 +3581,7 @@ const LogReviewer = (props) => {
|
|
|
3456
3581
|
log.isTTM
|
|
3457
3582
|
// TTMs aren't included
|
|
3458
3583
|
&& !advancedFilterState.includeTTMs) {
|
|
3584
|
+
console.log('RULED OUT: TTM');
|
|
3459
3585
|
return;
|
|
3460
3586
|
}
|
|
3461
3587
|
// Admin not allowed
|
|
@@ -3464,6 +3590,7 @@ const LogReviewer = (props) => {
|
|
|
3464
3590
|
log.isAdmin
|
|
3465
3591
|
// Admins aren't included
|
|
3466
3592
|
&& !advancedFilterState.includeAdmins) {
|
|
3593
|
+
console.log('RULED OUT: ADMIN');
|
|
3467
3594
|
return;
|
|
3468
3595
|
}
|
|
3469
3596
|
// Course Id doesn't match
|
|
@@ -3472,6 +3599,7 @@ const LogReviewer = (props) => {
|
|
|
3472
3599
|
log.courseId
|
|
3473
3600
|
// Course Id doesn't match
|
|
3474
3601
|
&& !String(log.courseId).includes(advancedFilterState.courseId.trim())) {
|
|
3602
|
+
console.log('RULED OUT: COURSE ID');
|
|
3475
3603
|
return;
|
|
3476
3604
|
}
|
|
3477
3605
|
// Course name doesn't match
|
|
@@ -3480,6 +3608,7 @@ const LogReviewer = (props) => {
|
|
|
3480
3608
|
log.courseName
|
|
3481
3609
|
// Course name doesn't match
|
|
3482
3610
|
&& !String(log.courseName).includes(advancedFilterState.courseName.trim())) {
|
|
3611
|
+
console.log('RULED OUT: COURSE NAME');
|
|
3483
3612
|
return;
|
|
3484
3613
|
}
|
|
3485
3614
|
// Mobile filter doesn't match
|
|
@@ -3490,6 +3619,7 @@ const LogReviewer = (props) => {
|
|
|
3490
3619
|
&& log.device
|
|
3491
3620
|
// Mobile filter doesn't match
|
|
3492
3621
|
&& (advancedFilterState.isMobile === log.device.isMobile)) {
|
|
3622
|
+
console.log('RULED OUT: MOBILE');
|
|
3493
3623
|
return;
|
|
3494
3624
|
}
|
|
3495
3625
|
// Log source doesn't match
|
|
@@ -3500,6 +3630,7 @@ const LogReviewer = (props) => {
|
|
|
3500
3630
|
&& log.source
|
|
3501
3631
|
// Source filter doesn't match
|
|
3502
3632
|
&& (advancedFilterState.source !== log.source)) {
|
|
3633
|
+
console.log('RULED OUT: SOURCE');
|
|
3503
3634
|
return;
|
|
3504
3635
|
}
|
|
3505
3636
|
// Route path doesn't match (Only for server source)
|
|
@@ -3510,6 +3641,7 @@ const LogReviewer = (props) => {
|
|
|
3510
3641
|
&& (advancedFilterState.routePath.trim().length)
|
|
3511
3642
|
// Route path doesn't match
|
|
3512
3643
|
&& !(log.routePath.includes(advancedFilterState.routePath.trim()))) {
|
|
3644
|
+
console.log('RULED OUT: PATH');
|
|
3513
3645
|
return;
|
|
3514
3646
|
}
|
|
3515
3647
|
// Route template doesn't match (Only for server source)
|
|
@@ -3520,6 +3652,7 @@ const LogReviewer = (props) => {
|
|
|
3520
3652
|
&& (advancedFilterState.routeTemplate.trim().length)
|
|
3521
3653
|
// Route template doesn't match
|
|
3522
3654
|
&& !(log.routeTemplate.includes(advancedFilterState.routeTemplate.trim()))) {
|
|
3655
|
+
console.log('RULED OUT: TEMPLATE');
|
|
3523
3656
|
return;
|
|
3524
3657
|
}
|
|
3525
3658
|
/* -------------- Done -------------- */
|
|
@@ -3719,11 +3852,17 @@ const LogReviewer = (props) => {
|
|
|
3719
3852
|
},
|
|
3720
3853
|
];
|
|
3721
3854
|
// Create intelliTable
|
|
3722
|
-
const dataTable = (
|
|
3855
|
+
const dataTable = (logs.length === 0
|
|
3856
|
+
? (React.createElement(React.Fragment, null,
|
|
3857
|
+
React.createElement("h3", { className: "m-0" }, "Matching Logs:"),
|
|
3858
|
+
React.createElement("div", { className: "alert alert-warning text-center" },
|
|
3859
|
+
React.createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
3860
|
+
React.createElement("div", null, "Either your filters are too strict or no matching logs have been created yet."))))
|
|
3861
|
+
: (React.createElement(IntelliTable, { title: "Matching Logs:", id: "logs", data: logs, columns: columns })));
|
|
3723
3862
|
// Main body
|
|
3724
3863
|
body = (React.createElement(React.Fragment, null,
|
|
3725
3864
|
filters,
|
|
3726
|
-
dataTable));
|
|
3865
|
+
React.createElement("div", { className: "mt-2" }, dataTable)));
|
|
3727
3866
|
}
|
|
3728
3867
|
/* ---------- Wrap in Modal --------- */
|
|
3729
3868
|
return (React.createElement("div", { className: "LogReviewer-outer-container" },
|
|
@@ -3731,14 +3870,10 @@ const LogReviewer = (props) => {
|
|
|
3731
3870
|
React.createElement("div", { className: "LogReviewer-inner-container" },
|
|
3732
3871
|
React.createElement("div", { className: "LogReviewer-header" },
|
|
3733
3872
|
React.createElement("div", { className: "LogReviewer-header-title" },
|
|
3734
|
-
React.createElement("
|
|
3735
|
-
React.createElement("
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
padding: 0,
|
|
3739
|
-
margin: 0,
|
|
3740
|
-
} },
|
|
3741
|
-
React.createElement(FontAwesomeIcon, { icon: faTimes }))),
|
|
3873
|
+
React.createElement("h3", { className: "text-center m-0" }, "Log Review Dashboard")),
|
|
3874
|
+
React.createElement("div", { style: { width: 0 } },
|
|
3875
|
+
React.createElement("button", { type: "button", className: "LogReviewer-header-close-button btn btn-dark btn-lg pe-0", "aria-label": "close log reviewer panel", onClick: onClose },
|
|
3876
|
+
React.createElement(FontAwesomeIcon, { icon: faTimes })))),
|
|
3742
3877
|
React.createElement("div", { className: "LogReviewer-contents" }, body))));
|
|
3743
3878
|
};
|
|
3744
3879
|
|
|
@@ -3884,7 +4019,7 @@ const padZerosLeft = (num, numDigits) => {
|
|
|
3884
4019
|
* access to log review
|
|
3885
4020
|
* @author Gabe Abrams
|
|
3886
4021
|
*/
|
|
3887
|
-
const LOG_REVIEW_STATUS_ROUTE =
|
|
4022
|
+
const LOG_REVIEW_STATUS_ROUTE = `${ROUTE_PATH_PREFIX}/logs/access_allowed`;
|
|
3888
4023
|
|
|
3889
4024
|
// Stored copy of caccl functions
|
|
3890
4025
|
let _cacclGetLaunchInfo;
|
|
@@ -3926,7 +4061,7 @@ const internalGetLogCollection = () => {
|
|
|
3926
4061
|
* @param opts.getLaunchInfo CACCL LTI's get launch info function
|
|
3927
4062
|
* @param [opts.logCollection] mongo collection from dce-mango to use for
|
|
3928
4063
|
* storing logs. If none is included, logs are written to the console
|
|
3929
|
-
* @param [opts.logReviewAdmins=all
|
|
4064
|
+
* @param [opts.logReviewAdmins=all] info on which admins can review
|
|
3930
4065
|
* logs from the client. If not included, all Canvas admins are allowed to
|
|
3931
4066
|
* review logs. If null, no Canvas admins are allowed to review logs.
|
|
3932
4067
|
* If an array of Canvas userIds (numbers), only Canvas admins with those
|
|
@@ -4009,71 +4144,81 @@ const initServer = (opts) => {
|
|
|
4009
4144
|
/*----------------------------------------*/
|
|
4010
4145
|
/* Log Reviewer */
|
|
4011
4146
|
/*----------------------------------------*/
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4147
|
+
/**
|
|
4148
|
+
* Check if a given user is allowed to review logs
|
|
4149
|
+
* @author Gabe Abrams
|
|
4150
|
+
* @param userId the id of the user
|
|
4151
|
+
* @param isAdmin if true, the user is an admin
|
|
4152
|
+
* @returns true if the user can review logs
|
|
4153
|
+
*/
|
|
4154
|
+
const canReviewLogs = (userId, isAdmin) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4155
|
+
// Immediately deny access if user is not an admin
|
|
4156
|
+
if (!isAdmin) {
|
|
4157
|
+
return false;
|
|
4158
|
+
}
|
|
4159
|
+
// If all admins are allowed, we're done
|
|
4160
|
+
if (!opts.logReviewAdmins) {
|
|
4161
|
+
return true;
|
|
4162
|
+
}
|
|
4163
|
+
// Do a dynamic check
|
|
4164
|
+
try {
|
|
4165
|
+
// Array of userIds
|
|
4166
|
+
if (Array.isArray(opts.logReviewAdmins)) {
|
|
4167
|
+
return opts.logReviewAdmins.some((allowedId) => {
|
|
4168
|
+
return (userId === allowedId);
|
|
4169
|
+
});
|
|
4031
4170
|
}
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4171
|
+
// Must be a collection
|
|
4172
|
+
const matches = yield opts.logReviewAdmins.find({ userId });
|
|
4173
|
+
// Make sure at least one entry matches
|
|
4174
|
+
return matches.length > 0;
|
|
4175
|
+
}
|
|
4176
|
+
catch (err) {
|
|
4177
|
+
// If an error occurred, simply return false
|
|
4178
|
+
return false;
|
|
4179
|
+
}
|
|
4180
|
+
});
|
|
4181
|
+
/**
|
|
4182
|
+
* Check if the current user has access to logs
|
|
4183
|
+
* @author Gabe Abrams
|
|
4184
|
+
* @returns {boolean} true if user has access
|
|
4185
|
+
*/
|
|
4186
|
+
opts.app.get(LOG_REVIEW_STATUS_ROUTE, genRouteHandler({
|
|
4187
|
+
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4188
|
+
const { userId, isAdmin } = params;
|
|
4189
|
+
const canReview = yield canReviewLogs(userId, isAdmin);
|
|
4190
|
+
return canReview;
|
|
4191
|
+
}),
|
|
4192
|
+
}));
|
|
4193
|
+
/**
|
|
4194
|
+
* Get all logs for a certain month
|
|
4195
|
+
* @author Gabe Abrams
|
|
4196
|
+
* @param {number} year the year to query (e.g. 2022)
|
|
4197
|
+
* @param {number} month the month to query (e.g. 1 = January)
|
|
4198
|
+
* @returns {Log[]} list of logs from the given month
|
|
4199
|
+
*/
|
|
4200
|
+
opts.app.get(`${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`, genRouteHandler({
|
|
4201
|
+
paramTypes: {
|
|
4202
|
+
year: ParamType$1.Int,
|
|
4203
|
+
month: ParamType$1.Int,
|
|
4204
|
+
},
|
|
4205
|
+
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4206
|
+
// Get user info
|
|
4207
|
+
const { year, month, userId, isAdmin, } = params;
|
|
4208
|
+
// Validate user
|
|
4209
|
+
const canReview = yield canReviewLogs(userId, isAdmin);
|
|
4210
|
+
if (!canReview) {
|
|
4211
|
+
throw new ErrorWithCode('You cannot access this resource because you do not have the appropriate permissions.', ReactKitErrorCode$1.NotAllowedToReviewLogs);
|
|
4035
4212
|
}
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
const canReview = yield canReviewLogs(userId);
|
|
4046
|
-
return canReview;
|
|
4047
|
-
}),
|
|
4048
|
-
}));
|
|
4049
|
-
/**
|
|
4050
|
-
* Get all logs for a certain month
|
|
4051
|
-
* @author Gabe Abrams
|
|
4052
|
-
* @param {number} year the year to query (e.g. 2022)
|
|
4053
|
-
* @param {number} month the month to query (e.g. 1 = January)
|
|
4054
|
-
* @returns {Log[]} list of logs from the given month
|
|
4055
|
-
*/
|
|
4056
|
-
opts.app.post(`${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`, genRouteHandler({
|
|
4057
|
-
paramTypes: {
|
|
4058
|
-
year: ParamType$1.Int,
|
|
4059
|
-
month: ParamType$1.Int,
|
|
4060
|
-
},
|
|
4061
|
-
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4062
|
-
// Get user info
|
|
4063
|
-
const { userId } = params;
|
|
4064
|
-
// Validate user
|
|
4065
|
-
// isAdmin is already checked because path starts with '/admin'
|
|
4066
|
-
const canReview = yield canReviewLogs(userId);
|
|
4067
|
-
if (!canReview) {
|
|
4068
|
-
throw new ErrorWithCode('You cannot access this resource because you do not have the appropriate permissions.', ReactKitErrorCode$1.NotAllowedToReviewLogs);
|
|
4069
|
-
}
|
|
4070
|
-
// Query for logs
|
|
4071
|
-
const logs = yield _logCollection.find({ userId });
|
|
4072
|
-
// Return logs
|
|
4073
|
-
return logs;
|
|
4074
|
-
}),
|
|
4075
|
-
}));
|
|
4076
|
-
}
|
|
4213
|
+
// Query for logs
|
|
4214
|
+
const logs = yield _logCollection.find({
|
|
4215
|
+
year,
|
|
4216
|
+
month,
|
|
4217
|
+
});
|
|
4218
|
+
// Return logs
|
|
4219
|
+
return logs;
|
|
4220
|
+
}),
|
|
4221
|
+
}));
|
|
4077
4222
|
};
|
|
4078
4223
|
|
|
4079
4224
|
// Import shared types
|
|
@@ -4373,18 +4518,6 @@ const parseUserAgent = (userAgent) => {
|
|
|
4373
4518
|
};
|
|
4374
4519
|
};
|
|
4375
4520
|
|
|
4376
|
-
/**
|
|
4377
|
-
* Allowed log levels
|
|
4378
|
-
* @author Gabe Abrams
|
|
4379
|
-
*/
|
|
4380
|
-
var LogLevel;
|
|
4381
|
-
(function (LogLevel) {
|
|
4382
|
-
LogLevel["Warn"] = "Warn";
|
|
4383
|
-
LogLevel["Info"] = "Info";
|
|
4384
|
-
LogLevel["Debug"] = "Debug";
|
|
4385
|
-
})(LogLevel || (LogLevel = {}));
|
|
4386
|
-
var LogLevel$1 = LogLevel;
|
|
4387
|
-
|
|
4388
4521
|
/**
|
|
4389
4522
|
* Generate an express API route handler
|
|
4390
4523
|
* @author Gabe Abrams
|
|
@@ -4757,7 +4890,7 @@ const genRouteHandler = (opts) => {
|
|
|
4757
4890
|
}
|
|
4758
4891
|
: {
|
|
4759
4892
|
type: LogType$1.Action,
|
|
4760
|
-
target: ((_m = opts.target) !== null && _m !== void 0 ? _m : LogBuiltInMetadata.Target.
|
|
4893
|
+
target: ((_m = opts.target) !== null && _m !== void 0 ? _m : LogBuiltInMetadata.Target.NoTarget),
|
|
4761
4894
|
action: ((_o = opts.action) !== null && _o !== void 0 ? _o : LogAction$1.Unknown),
|
|
4762
4895
|
});
|
|
4763
4896
|
// Source-specific info
|
|
@@ -5124,6 +5257,31 @@ const initLogCollection = (Collection) => {
|
|
|
5124
5257
|
});
|
|
5125
5258
|
};
|
|
5126
5259
|
|
|
5260
|
+
// Cache user's ability
|
|
5261
|
+
let canReview = undefined;
|
|
5262
|
+
/**
|
|
5263
|
+
* Check if the current user can review logs
|
|
5264
|
+
* @author Gabe Abrams
|
|
5265
|
+
* @returns true if current user can review logs
|
|
5266
|
+
*/
|
|
5267
|
+
const canReviewLogs = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
5268
|
+
// If cached, use that value
|
|
5269
|
+
if (canReview !== undefined) {
|
|
5270
|
+
return canReview;
|
|
5271
|
+
}
|
|
5272
|
+
// Ask on server
|
|
5273
|
+
try {
|
|
5274
|
+
canReview = !!(yield visitServerEndpoint({
|
|
5275
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
5276
|
+
method: 'GET',
|
|
5277
|
+
}));
|
|
5278
|
+
}
|
|
5279
|
+
catch (err) {
|
|
5280
|
+
canReview = false;
|
|
5281
|
+
}
|
|
5282
|
+
return canReview;
|
|
5283
|
+
});
|
|
5284
|
+
|
|
5127
5285
|
/**
|
|
5128
5286
|
* Days of the week
|
|
5129
5287
|
* @author Gabe Abrams
|
|
@@ -5140,5 +5298,5 @@ var DayOfWeek;
|
|
|
5140
5298
|
})(DayOfWeek || (DayOfWeek = {}));
|
|
5141
5299
|
var DayOfWeek$1 = DayOfWeek;
|
|
5142
5300
|
|
|
5143
|
-
export { AppWrapper, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DAY_IN_MS, DayOfWeek$1 as DayOfWeek, Drawer, ErrorBox, ErrorWithCode, HOUR_IN_MS, IntelliTable, ItemPicker, LoadingSpinner, LogAction$1 as LogAction, LogBuiltInMetadata, LogReviewer, LogSource$1 as LogSource, LogType$1 as LogType, MINUTE_IN_MS, Modal, ModalButtonType$1 as ModalButtonType, ModalSize$1 as ModalSize, ModalType$1 as ModalType, ParamType$1 as ParamType, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode$1 as ReactKitErrorCode, SimpleDateChooser, TabBox, Variant$1 as Variant, abbreviate, alert$1 as alert, avg, ceilToNumDecimals, confirm, floorToNumDecimals, forceNumIntoBounds, genCSV, genRouteHandler, getHumanReadableDate, getMonthName, getOrdinal, getPartOfDay, getTimeInfoInET, handleError, handleSuccess, initLogCollection, initServer, logClientEvent, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, roundToNumDecimals, showFatalError, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, visitServerEndpoint, waitMs };
|
|
5301
|
+
export { AppWrapper, ButtonInputGroup, CSVDownloadButton, CheckboxButton, CopiableBox, DAY_IN_MS, DayOfWeek$1 as DayOfWeek, Drawer, ErrorBox, ErrorWithCode, HOUR_IN_MS, IntelliTable, ItemPicker, LoadingSpinner, LogAction$1 as LogAction, LogBuiltInMetadata, LogReviewer, LogSource$1 as LogSource, LogType$1 as LogType, MINUTE_IN_MS, Modal, ModalButtonType$1 as ModalButtonType, ModalSize$1 as ModalSize, ModalType$1 as ModalType, ParamType$1 as ParamType, PopFailureMark, PopPendingMark, PopSuccessMark, RadioButton, ReactKitErrorCode$1 as ReactKitErrorCode, SimpleDateChooser, TabBox, Variant$1 as Variant, abbreviate, alert$1 as alert, avg, canReviewLogs, ceilToNumDecimals, confirm, floorToNumDecimals, forceNumIntoBounds, genCSV, genRouteHandler, getHumanReadableDate, getMonthName, getOrdinal, getPartOfDay, getTimeInfoInET, handleError, handleSuccess, initLogCollection, initServer, logClientEvent, onlyKeepLetters, padDecimalZeros, padZerosLeft, parallelLimit, roundToNumDecimals, showFatalError, startMinWait, stringsToHumanReadableList, stubServerEndpoint, sum, visitServerEndpoint, waitMs };
|
|
5144
5302
|
//# sourceMappingURL=index.js.map
|