dce-reactkit 3.2.2-beta.2 → 3.2.2-beta.20
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 +338 -186
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ButtonInputGroup.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 +338 -187
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ButtonInputGroup.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/index.tsx +4 -0
- package/src/components/LogReviewer.tsx +280 -130
- 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}`,
|
|
@@ -2049,7 +2075,7 @@ const ItemPicker = (props) => {
|
|
|
2049
2075
|
/*------------------------------------------------------------------------*/
|
|
2050
2076
|
/* -------------- Props ------------- */
|
|
2051
2077
|
// Destructure all props
|
|
2052
|
-
const { title, items, onChanged, } = props;
|
|
2078
|
+
const { title, items, onChanged, noBottomMargin, } = props;
|
|
2053
2079
|
/*------------------------------------------------------------------------*/
|
|
2054
2080
|
/* Component Functions */
|
|
2055
2081
|
/*------------------------------------------------------------------------*/
|
|
@@ -2059,7 +2085,7 @@ const ItemPicker = (props) => {
|
|
|
2059
2085
|
/*----------------------------------------*/
|
|
2060
2086
|
/* Main UI */
|
|
2061
2087
|
/*----------------------------------------*/
|
|
2062
|
-
return (React.createElement(TabBox, { title: title },
|
|
2088
|
+
return (React.createElement(TabBox, { title: title, noBottomMargin: noBottomMargin },
|
|
2063
2089
|
React.createElement("div", { style: { overflowX: 'auto' } },
|
|
2064
2090
|
React.createElement(NestableItemList, { items: items, onChanged: onChanged }))));
|
|
2065
2091
|
};
|
|
@@ -2376,9 +2402,9 @@ const IntelliTable = (props) => {
|
|
|
2376
2402
|
// Create the cell UI
|
|
2377
2403
|
return (React.createElement("th", { key: column.param, scope: "col", id: `IntelliTable-${id}-header-${column.param}` },
|
|
2378
2404
|
React.createElement("div", { className: "d-flex align-items-center justify-content-center flex-row h-100" },
|
|
2379
|
-
React.createElement("
|
|
2405
|
+
React.createElement("span", { className: "text-nowrap" }, column.title),
|
|
2380
2406
|
React.createElement("div", null,
|
|
2381
|
-
React.createElement("button", { type: "button", className: "btn btn-light", "aria-label": sortButtonAriaLabel, onClick: () => {
|
|
2407
|
+
React.createElement("button", { type: "button", className: "btn btn-light btn-sm ms-1", "aria-label": sortButtonAriaLabel, onClick: () => {
|
|
2382
2408
|
dispatch({
|
|
2383
2409
|
type: ActionType$1.ToggleSortColumn,
|
|
2384
2410
|
param: column.param,
|
|
@@ -2526,7 +2552,7 @@ const IntelliTable = (props) => {
|
|
|
2526
2552
|
React.createElement("h3", { className: "m-0" }, title),
|
|
2527
2553
|
React.createElement("div", { className: "flex-grow-1 text-end" },
|
|
2528
2554
|
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: () => {
|
|
2555
|
+
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
2556
|
dispatch({
|
|
2531
2557
|
type: ActionType$1.ToggleColVisCusModalVisibility,
|
|
2532
2558
|
});
|
|
@@ -2590,6 +2616,11 @@ const style = `
|
|
|
2590
2616
|
border: 0.05rem solid black;
|
|
2591
2617
|
border-radius: 0.5rem;
|
|
2592
2618
|
overflow: hidden;
|
|
2619
|
+
padding: 0.7rem;
|
|
2620
|
+
|
|
2621
|
+
/* Solid background */
|
|
2622
|
+
background-color: white;
|
|
2623
|
+
color: black;
|
|
2593
2624
|
|
|
2594
2625
|
/* Place contents in flex column */
|
|
2595
2626
|
flex-direction: column;
|
|
@@ -2616,6 +2647,27 @@ const style = `
|
|
|
2616
2647
|
/* Vertical scroll */
|
|
2617
2648
|
overflow-y: auto;
|
|
2618
2649
|
}
|
|
2650
|
+
|
|
2651
|
+
.LogReviewer-header-close-button {
|
|
2652
|
+
border: 0 !important;
|
|
2653
|
+
background-color: transparent !important;
|
|
2654
|
+
padding-top: 0 !important;
|
|
2655
|
+
padding-bottom: 0 !important;
|
|
2656
|
+
padding-right: 1em !important;
|
|
2657
|
+
margin: 0 !important;
|
|
2658
|
+
color: #444 !important;
|
|
2659
|
+
|
|
2660
|
+
right: 0 !important;
|
|
2661
|
+
position: absolute !important;
|
|
2662
|
+
}
|
|
2663
|
+
.LogReviewer-header-close-button:hover {
|
|
2664
|
+
border: 0 !important;
|
|
2665
|
+
background-color: transparent !important;
|
|
2666
|
+
padding-top: 0 !important;
|
|
2667
|
+
padding-bottom: 0 !important;
|
|
2668
|
+
margin: 0 !important;
|
|
2669
|
+
color: #000 !important;
|
|
2670
|
+
}
|
|
2619
2671
|
`;
|
|
2620
2672
|
/*------------------------------------------------------------------------*/
|
|
2621
2673
|
/* Static Functions */
|
|
@@ -2635,7 +2687,7 @@ const genHumanReadableName = (machineReadableName) => {
|
|
|
2635
2687
|
// Uppercase! Add a space before
|
|
2636
2688
|
humanReadableName += ' ';
|
|
2637
2689
|
}
|
|
2638
|
-
humanReadableName +=
|
|
2690
|
+
humanReadableName += char;
|
|
2639
2691
|
});
|
|
2640
2692
|
// Trim and return
|
|
2641
2693
|
return humanReadableName.trim();
|
|
@@ -2697,7 +2749,19 @@ const reducer = (state, action) => {
|
|
|
2697
2749
|
return Object.assign(Object.assign({}, state), { contextFilterState: action.contextFilterState });
|
|
2698
2750
|
}
|
|
2699
2751
|
case ActionType.UpdateTagFilterState: {
|
|
2700
|
-
|
|
2752
|
+
const { tagFilterState } = action;
|
|
2753
|
+
// Select all if every tag is deselected
|
|
2754
|
+
const numTagsSelected = (Object.values(tagFilterState)
|
|
2755
|
+
.filter((isSelected) => {
|
|
2756
|
+
return isSelected;
|
|
2757
|
+
})
|
|
2758
|
+
.length);
|
|
2759
|
+
if (numTagsSelected === 0) {
|
|
2760
|
+
Object.keys(tagFilterState).forEach((tag) => {
|
|
2761
|
+
tagFilterState[tag] = true;
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
return Object.assign(Object.assign({}, state), { tagFilterState });
|
|
2701
2765
|
}
|
|
2702
2766
|
case ActionType.UpdateActionErrorFilterState: {
|
|
2703
2767
|
return Object.assign(Object.assign({}, state), { actionErrorFilterState: action.actionErrorFilterState });
|
|
@@ -2717,10 +2781,33 @@ const LogReviewer = (props) => {
|
|
|
2717
2781
|
/*------------------------------------------------------------------------*/
|
|
2718
2782
|
/* Setup */
|
|
2719
2783
|
/*------------------------------------------------------------------------*/
|
|
2720
|
-
var _a, _b, _c, _d, _e;
|
|
2784
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
2721
2785
|
/* -------------- Props ------------- */
|
|
2722
2786
|
// Destructure props
|
|
2723
2787
|
const { LogMetadata, onClose, } = props;
|
|
2788
|
+
// Add built-in LogMetadata
|
|
2789
|
+
// > Add "uncategorized" subcontext to each context
|
|
2790
|
+
Object.keys((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {}).forEach((context) => {
|
|
2791
|
+
if (LogMetadata.Context
|
|
2792
|
+
// Context has children already
|
|
2793
|
+
&& typeof LogMetadata.Context[context] !== 'string') {
|
|
2794
|
+
LogMetadata.Context[context][LogBuiltInMetadata.Context.Uncategorized] = (LogBuiltInMetadata.Context.Uncategorized);
|
|
2795
|
+
}
|
|
2796
|
+
});
|
|
2797
|
+
// > Add built-in contexts
|
|
2798
|
+
LogMetadata.Context = ((_b = LogMetadata.Context) !== null && _b !== void 0 ? _b : {});
|
|
2799
|
+
Object.keys(LogBuiltInMetadata.Context).forEach((context) => {
|
|
2800
|
+
if (LogMetadata.Context) {
|
|
2801
|
+
LogMetadata.Context[context] = context;
|
|
2802
|
+
}
|
|
2803
|
+
});
|
|
2804
|
+
// > Add built-in targets
|
|
2805
|
+
LogMetadata.Target = ((_c = LogMetadata.Target) !== null && _c !== void 0 ? _c : {});
|
|
2806
|
+
Object.keys(LogBuiltInMetadata.Target).forEach((target) => {
|
|
2807
|
+
if (LogMetadata.Target) {
|
|
2808
|
+
LogMetadata.Target[target] = target;
|
|
2809
|
+
}
|
|
2810
|
+
});
|
|
2724
2811
|
/* -------------- State ------------- */
|
|
2725
2812
|
// Create initial date filter state
|
|
2726
2813
|
const today = getTimeInfoInET();
|
|
@@ -2740,7 +2827,7 @@ const LogReviewer = (props) => {
|
|
|
2740
2827
|
};
|
|
2741
2828
|
// Create initial context filter state
|
|
2742
2829
|
const initContextFilterState = {};
|
|
2743
|
-
Object.keys((
|
|
2830
|
+
Object.keys((_d = LogMetadata.Context) !== null && _d !== void 0 ? _d : {}).forEach((context) => {
|
|
2744
2831
|
var _a, _b;
|
|
2745
2832
|
const contextValue = ((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {})[context];
|
|
2746
2833
|
if (typeof contextValue === 'string') {
|
|
@@ -2758,7 +2845,7 @@ const LogReviewer = (props) => {
|
|
|
2758
2845
|
});
|
|
2759
2846
|
// Create initial tag filter state
|
|
2760
2847
|
const initTagFilterState = {};
|
|
2761
|
-
Object.values((
|
|
2848
|
+
Object.values((_e = LogMetadata.Tag) !== null && _e !== void 0 ? _e : {}).forEach((tagValue) => {
|
|
2762
2849
|
initTagFilterState[tagValue] = true;
|
|
2763
2850
|
});
|
|
2764
2851
|
// Create advanced filter state
|
|
@@ -2785,12 +2872,16 @@ const LogReviewer = (props) => {
|
|
|
2785
2872
|
target: {},
|
|
2786
2873
|
action: {},
|
|
2787
2874
|
};
|
|
2788
|
-
Object.values((
|
|
2875
|
+
Object.values((_f = LogMetadata.Target) !== null && _f !== void 0 ? _f : {}).forEach((target) => {
|
|
2789
2876
|
initActionErrorFilterState.target[target] = true;
|
|
2790
2877
|
});
|
|
2791
2878
|
Object.values(LogAction$1).forEach((action) => {
|
|
2792
2879
|
initActionErrorFilterState.action[action] = true;
|
|
2793
2880
|
});
|
|
2881
|
+
// Add built-in targets
|
|
2882
|
+
Object.values(LogBuiltInMetadata.Target).forEach((target) => {
|
|
2883
|
+
initActionErrorFilterState.target[target] = true;
|
|
2884
|
+
});
|
|
2794
2885
|
// Initial state
|
|
2795
2886
|
const initialState = {
|
|
2796
2887
|
loading: true,
|
|
@@ -2824,15 +2915,18 @@ const LogReviewer = (props) => {
|
|
|
2824
2915
|
let month = newDateFilterState.startDate.month;
|
|
2825
2916
|
while (
|
|
2826
2917
|
// Earlier year
|
|
2827
|
-
(year
|
|
2918
|
+
(year < newDateFilterState.endDate.year)
|
|
2828
2919
|
// Current year but included month
|
|
2829
2920
|
|| (year === newDateFilterState.endDate.year
|
|
2830
2921
|
&& month <= newDateFilterState.endDate.month)) {
|
|
2831
|
-
// Add to list
|
|
2832
|
-
|
|
2833
|
-
year
|
|
2834
|
-
|
|
2835
|
-
|
|
2922
|
+
// Add to list if not already loaded
|
|
2923
|
+
if (!logMap[year]
|
|
2924
|
+
|| !logMap[year][month]) {
|
|
2925
|
+
toLoad.push({
|
|
2926
|
+
year,
|
|
2927
|
+
month,
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2836
2930
|
// Increment
|
|
2837
2931
|
month += 1;
|
|
2838
2932
|
if (month > 12) {
|
|
@@ -2856,6 +2950,7 @@ const LogReviewer = (props) => {
|
|
|
2856
2950
|
});
|
|
2857
2951
|
// Check which year/month combos we need to load
|
|
2858
2952
|
const toLoad = listMonthsToLoad(newDateFilterState);
|
|
2953
|
+
console.log('Filter update:', newDateFilterState, toLoad, logMap);
|
|
2859
2954
|
// If nothing to load, finished
|
|
2860
2955
|
if (toLoad.length === 0) {
|
|
2861
2956
|
return;
|
|
@@ -2920,10 +3015,10 @@ const LogReviewer = (props) => {
|
|
|
2920
3015
|
/* Filters */
|
|
2921
3016
|
/*----------------------------------------*/
|
|
2922
3017
|
// Filter toggle
|
|
2923
|
-
const filterToggles = (React.createElement("div", { className: "LogReviewer-filter-toggles
|
|
3018
|
+
const filterToggles = (React.createElement("div", { className: "LogReviewer-filter-toggles" },
|
|
2924
3019
|
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: () => {
|
|
3020
|
+
React.createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
|
|
3021
|
+
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
3022
|
dispatch({
|
|
2928
3023
|
type: ActionType.ToggleFilterDrawer,
|
|
2929
3024
|
filterDrawer: FilterDrawer.Date,
|
|
@@ -2931,7 +3026,7 @@ const LogReviewer = (props) => {
|
|
|
2931
3026
|
} },
|
|
2932
3027
|
React.createElement(FontAwesomeIcon, { icon: faCalendar, className: "me-2" }),
|
|
2933
3028
|
"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: () => {
|
|
3029
|
+
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
3030
|
dispatch({
|
|
2936
3031
|
type: ActionType.ToggleFilterDrawer,
|
|
2937
3032
|
filterDrawer: FilterDrawer.Context,
|
|
@@ -2939,15 +3034,15 @@ const LogReviewer = (props) => {
|
|
|
2939
3034
|
} },
|
|
2940
3035
|
React.createElement(FontAwesomeIcon, { icon: faCircle, className: "me-2" }),
|
|
2941
3036
|
"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: () => {
|
|
3037
|
+
(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
3038
|
dispatch({
|
|
2944
3039
|
type: ActionType.ToggleFilterDrawer,
|
|
2945
3040
|
filterDrawer: FilterDrawer.Tag,
|
|
2946
3041
|
});
|
|
2947
3042
|
} },
|
|
2948
3043
|
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: () => {
|
|
3044
|
+
"Tag")),
|
|
3045
|
+
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
3046
|
dispatch({
|
|
2952
3047
|
type: ActionType.ToggleFilterDrawer,
|
|
2953
3048
|
filterDrawer: FilterDrawer.Action,
|
|
@@ -2955,7 +3050,7 @@ const LogReviewer = (props) => {
|
|
|
2955
3050
|
} },
|
|
2956
3051
|
React.createElement(FontAwesomeIcon, { icon: faHammer, className: "me-2" }),
|
|
2957
3052
|
"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: () => {
|
|
3053
|
+
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
3054
|
dispatch({
|
|
2960
3055
|
type: ActionType.ToggleFilterDrawer,
|
|
2961
3056
|
filterDrawer: FilterDrawer.Advanced,
|
|
@@ -2968,25 +3063,29 @@ const LogReviewer = (props) => {
|
|
|
2968
3063
|
if (expandedFilterDrawer) {
|
|
2969
3064
|
if (expandedFilterDrawer === FilterDrawer.Date) {
|
|
2970
3065
|
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
|
-
});
|
|
3066
|
+
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) => {
|
|
3067
|
+
dateFilterState.startDate = { month, day, year };
|
|
3068
|
+
handleDateRangeUpdated(dateFilterState);
|
|
2976
3069
|
} }),
|
|
2977
3070
|
' ',
|
|
2978
3071
|
"to",
|
|
2979
3072
|
' ',
|
|
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
|
-
|
|
3073
|
+
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) => {
|
|
3074
|
+
if (year < dateFilterState.startDate.year
|
|
3075
|
+
|| (year === dateFilterState.startDate.year
|
|
3076
|
+
&& month < dateFilterState.startDate.month)
|
|
3077
|
+
|| (year === dateFilterState.startDate.year
|
|
3078
|
+
&& month === dateFilterState.startDate.month
|
|
3079
|
+
&& day < dateFilterState.startDate.day)) {
|
|
3080
|
+
return alert$1('Invalid Start Date', 'The start date cannot be before the end date.');
|
|
3081
|
+
}
|
|
3082
|
+
dateFilterState.endDate = { month, day, year };
|
|
3083
|
+
handleDateRangeUpdated(dateFilterState);
|
|
2985
3084
|
} })));
|
|
2986
3085
|
}
|
|
2987
3086
|
else if (expandedFilterDrawer === FilterDrawer.Context) {
|
|
2988
3087
|
// Create item picker items
|
|
2989
|
-
const pickableItems = (Object.keys((
|
|
3088
|
+
const pickableItems = (Object.keys((_g = LogMetadata.Context) !== null && _g !== void 0 ? _g : {})
|
|
2990
3089
|
.map((context) => {
|
|
2991
3090
|
var _a;
|
|
2992
3091
|
const value = ((_a = LogMetadata.Context) !== null && _a !== void 0 ? _a : {})[context];
|
|
@@ -3015,7 +3114,7 @@ const LogReviewer = (props) => {
|
|
|
3015
3114
|
}));
|
|
3016
3115
|
const item = {
|
|
3017
3116
|
id: context,
|
|
3018
|
-
name: context,
|
|
3117
|
+
name: genHumanReadableName(context),
|
|
3019
3118
|
isGroup: true,
|
|
3020
3119
|
children,
|
|
3021
3120
|
};
|
|
@@ -3023,6 +3122,8 @@ const LogReviewer = (props) => {
|
|
|
3023
3122
|
}));
|
|
3024
3123
|
// Create filter UI
|
|
3025
3124
|
filterDrawer = (React.createElement(ItemPicker, { title: "Context", items: pickableItems, onChanged: (updatedItems) => {
|
|
3125
|
+
console.log('Items before:', pickableItems);
|
|
3126
|
+
console.log('Updated Items:', updatedItems);
|
|
3026
3127
|
// Update our state
|
|
3027
3128
|
updatedItems.forEach((pickableItem) => {
|
|
3028
3129
|
if (pickableItem.isGroup) {
|
|
@@ -3079,7 +3180,7 @@ const LogReviewer = (props) => {
|
|
|
3079
3180
|
}, ariaLabel: "only show error logs", selected: actionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true })),
|
|
3080
3181
|
(actionErrorFilterState.type === undefined
|
|
3081
3182
|
|| actionErrorFilterState.type === LogType$1.Action) && (React.createElement(TabBox, { title: "Action Log Details" },
|
|
3082
|
-
React.createElement(ButtonInputGroup, { label: "Action" }, Object.keys(LogAction$1)
|
|
3183
|
+
React.createElement(ButtonInputGroup, { label: "Action", className: "mb-2" }, Object.keys(LogAction$1)
|
|
3083
3184
|
.map((action, i) => {
|
|
3084
3185
|
const description = genHumanReadableName(action);
|
|
3085
3186
|
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 +3191,20 @@ const LogReviewer = (props) => {
|
|
|
3090
3191
|
});
|
|
3091
3192
|
} }));
|
|
3092
3193
|
})),
|
|
3093
|
-
React.createElement(ButtonInputGroup, { label: "Target" },
|
|
3094
|
-
.
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3194
|
+
React.createElement(ButtonInputGroup, { label: "Target" },
|
|
3195
|
+
(Object.keys((_h = LogMetadata.Target) !== null && _h !== void 0 ? _h : {}).length === 0) && (React.createElement("div", null, "This app does not have any targets yet.")),
|
|
3196
|
+
Object.keys((_j = LogMetadata.Target) !== null && _j !== void 0 ? _j : {})
|
|
3197
|
+
.map((target, i) => {
|
|
3198
|
+
var _a;
|
|
3199
|
+
const description = genHumanReadableName(target);
|
|
3200
|
+
return (React.createElement(CheckboxButton, { id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, onChanged: (checked) => {
|
|
3201
|
+
actionErrorFilterState.target[target] = checked;
|
|
3202
|
+
dispatch({
|
|
3203
|
+
type: ActionType.UpdateActionErrorFilterState,
|
|
3204
|
+
actionErrorFilterState,
|
|
3205
|
+
});
|
|
3206
|
+
}, noMarginOnRight: i === Object.keys((_a = LogMetadata.Target) !== null && _a !== void 0 ? _a : {}).length - 1 }));
|
|
3207
|
+
})))),
|
|
3105
3208
|
(actionErrorFilterState.type === undefined
|
|
3106
3209
|
|| actionErrorFilterState.type === LogType$1.Error) && (React.createElement(TabBox, { title: "Error Log Details" },
|
|
3107
3210
|
React.createElement("div", { className: "input-group mb-2" },
|
|
@@ -3263,26 +3366,27 @@ const LogReviewer = (props) => {
|
|
|
3263
3366
|
advancedFilterState,
|
|
3264
3367
|
});
|
|
3265
3368
|
}, 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
|
-
|
|
3369
|
+
advancedFilterState.source !== LogSource$1.Client && (React.createElement("div", { className: "mt-2" },
|
|
3370
|
+
React.createElement("div", { className: "input-group mb-2" },
|
|
3371
|
+
React.createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
3372
|
+
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) => {
|
|
3373
|
+
advancedFilterState.courseName = ((e.target.value)
|
|
3374
|
+
.trim());
|
|
3375
|
+
dispatch({
|
|
3376
|
+
type: ActionType.UpdateAdvancedFilterState,
|
|
3377
|
+
advancedFilterState,
|
|
3378
|
+
});
|
|
3379
|
+
} })),
|
|
3380
|
+
React.createElement("div", { className: "input-group mb-2" },
|
|
3381
|
+
React.createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
3382
|
+
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) => {
|
|
3383
|
+
advancedFilterState.courseName = ((e.target.value)
|
|
3384
|
+
.trim());
|
|
3385
|
+
dispatch({
|
|
3386
|
+
type: ActionType.UpdateAdvancedFilterState,
|
|
3387
|
+
advancedFilterState,
|
|
3388
|
+
});
|
|
3389
|
+
} })))))));
|
|
3286
3390
|
}
|
|
3287
3391
|
}
|
|
3288
3392
|
// Filters UI
|
|
@@ -3293,10 +3397,11 @@ const LogReviewer = (props) => {
|
|
|
3293
3397
|
// > Perform filters
|
|
3294
3398
|
const logs = [];
|
|
3295
3399
|
Object.keys(logMap).forEach((year) => {
|
|
3296
|
-
Object.keys(logMap).forEach((month) => {
|
|
3400
|
+
Object.keys(logMap[year]).forEach((month) => {
|
|
3297
3401
|
logMap[year][month].forEach((log) => {
|
|
3298
|
-
/* ----------- Date Filter ---------- */
|
|
3299
3402
|
var _a;
|
|
3403
|
+
/* ----------- Date Filter ---------- */
|
|
3404
|
+
console.log('Log:', log);
|
|
3300
3405
|
// Before start date
|
|
3301
3406
|
if (
|
|
3302
3407
|
// Previous year
|
|
@@ -3308,6 +3413,7 @@ const LogReviewer = (props) => {
|
|
|
3308
3413
|
|| ((log.year === dateFilterState.startDate.year)
|
|
3309
3414
|
&& (log.month === dateFilterState.startDate.month)
|
|
3310
3415
|
&& (log.day < dateFilterState.startDate.day))) {
|
|
3416
|
+
console.log('RULED OUT: START');
|
|
3311
3417
|
return;
|
|
3312
3418
|
}
|
|
3313
3419
|
// After end date
|
|
@@ -3321,6 +3427,7 @@ const LogReviewer = (props) => {
|
|
|
3321
3427
|
|| ((log.year === dateFilterState.endDate.year)
|
|
3322
3428
|
&& (log.month === dateFilterState.endDate.month)
|
|
3323
3429
|
&& (log.day > dateFilterState.endDate.day))) {
|
|
3430
|
+
console.log('RULED OUT: END');
|
|
3324
3431
|
return;
|
|
3325
3432
|
}
|
|
3326
3433
|
/* --------- Context Filter --------- */
|
|
@@ -3333,29 +3440,30 @@ const LogReviewer = (props) => {
|
|
|
3333
3440
|
.every((isSelected) => {
|
|
3334
3441
|
return !isSelected;
|
|
3335
3442
|
}))) {
|
|
3443
|
+
console.log('RULED OUT: CONTEXT');
|
|
3336
3444
|
return;
|
|
3337
3445
|
}
|
|
3338
3446
|
// Subcontext doesn't match
|
|
3339
3447
|
if (
|
|
3340
|
-
// Log
|
|
3341
|
-
log.
|
|
3448
|
+
// Log context is not "uncategorized" (no point in further filters)
|
|
3449
|
+
log.context !== LogBuiltInMetadata.Context.Uncategorized
|
|
3450
|
+
// Log has a subcontext
|
|
3451
|
+
&& log.subcontext
|
|
3342
3452
|
// Context has subcontexts
|
|
3343
3453
|
&& (contextFilterState[log.context]
|
|
3344
3454
|
&& contextFilterState[log.context] !== false
|
|
3345
3455
|
&& contextFilterState[log.context] !== true)
|
|
3346
3456
|
// Subcontext is not selected
|
|
3347
3457
|
&& !contextFilterState[log.context][log.subcontext]) {
|
|
3458
|
+
console.log('RULED OUT: SUBCONTEXT');
|
|
3348
3459
|
return;
|
|
3349
3460
|
}
|
|
3350
3461
|
/* -------------- Tags -------------- */
|
|
3351
3462
|
// No tags match
|
|
3352
|
-
if (
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
&& (log.tags.every((tag) => {
|
|
3357
|
-
return !tagFilterState[tag];
|
|
3358
|
-
}))) {
|
|
3463
|
+
if (log.tags.every((tag) => {
|
|
3464
|
+
return !tagFilterState[tag];
|
|
3465
|
+
})) {
|
|
3466
|
+
console.log('RULED OUT: TAGS');
|
|
3359
3467
|
return;
|
|
3360
3468
|
}
|
|
3361
3469
|
/* ------- Actions and Errors ------- */
|
|
@@ -3365,6 +3473,7 @@ const LogReviewer = (props) => {
|
|
|
3365
3473
|
actionErrorFilterState.type !== undefined
|
|
3366
3474
|
// Log type doesn't match
|
|
3367
3475
|
&& actionErrorFilterState.type !== log.type) {
|
|
3476
|
+
console.log('RULED OUT: TYPE');
|
|
3368
3477
|
return;
|
|
3369
3478
|
}
|
|
3370
3479
|
// Filter errors
|
|
@@ -3377,6 +3486,7 @@ const LogReviewer = (props) => {
|
|
|
3377
3486
|
&& actionErrorFilterState.errorMessage.trim().length > 0
|
|
3378
3487
|
// Message doesn't match
|
|
3379
3488
|
&& log.errorMessage.toLowerCase().includes(actionErrorFilterState.errorMessage.trim().toLowerCase())) {
|
|
3489
|
+
console.log('RULED OUT: ERROR MESSAGE');
|
|
3380
3490
|
return;
|
|
3381
3491
|
}
|
|
3382
3492
|
// Code doesn't match
|
|
@@ -3387,6 +3497,7 @@ const LogReviewer = (props) => {
|
|
|
3387
3497
|
&& actionErrorFilterState.errorCode.trim().length > 0
|
|
3388
3498
|
// Code doesn't match
|
|
3389
3499
|
&& log.errorCode.toUpperCase().includes(actionErrorFilterState.errorCode.trim().toUpperCase())) {
|
|
3500
|
+
console.log('RULED OUT: ERROR CODE');
|
|
3390
3501
|
return;
|
|
3391
3502
|
}
|
|
3392
3503
|
}
|
|
@@ -3398,6 +3509,7 @@ const LogReviewer = (props) => {
|
|
|
3398
3509
|
log.target
|
|
3399
3510
|
// Target isn't selected
|
|
3400
3511
|
&& !actionErrorFilterState.target[log.target]) {
|
|
3512
|
+
console.log('RULED OUT: TARGET');
|
|
3401
3513
|
return;
|
|
3402
3514
|
}
|
|
3403
3515
|
// Action
|
|
@@ -3406,6 +3518,7 @@ const LogReviewer = (props) => {
|
|
|
3406
3518
|
log.action
|
|
3407
3519
|
// Action isn't selected
|
|
3408
3520
|
&& !actionErrorFilterState.action[log.action]) {
|
|
3521
|
+
console.log('RULED OUT: ACTION');
|
|
3409
3522
|
return;
|
|
3410
3523
|
}
|
|
3411
3524
|
}
|
|
@@ -3416,6 +3529,7 @@ const LogReviewer = (props) => {
|
|
|
3416
3529
|
log.userFirstName
|
|
3417
3530
|
// First name query doesn't match
|
|
3418
3531
|
&& !log.userFirstName.toLowerCase().includes(advancedFilterState.userFirstName.toLowerCase().trim())) {
|
|
3532
|
+
console.log('RULED OUT: FIRST');
|
|
3419
3533
|
return;
|
|
3420
3534
|
}
|
|
3421
3535
|
// Last name doesn't match
|
|
@@ -3424,6 +3538,7 @@ const LogReviewer = (props) => {
|
|
|
3424
3538
|
log.userLastName
|
|
3425
3539
|
// Last name query doesn't match
|
|
3426
3540
|
&& !log.userLastName.toLowerCase().includes(advancedFilterState.userLastName.toLowerCase().trim())) {
|
|
3541
|
+
console.log('RULED OUT: LAST');
|
|
3427
3542
|
return;
|
|
3428
3543
|
}
|
|
3429
3544
|
// Email doesn't match
|
|
@@ -3432,6 +3547,7 @@ const LogReviewer = (props) => {
|
|
|
3432
3547
|
log.userEmail
|
|
3433
3548
|
// Email query doesn't match
|
|
3434
3549
|
&& !log.userEmail.toLowerCase().includes(advancedFilterState.userEmail.toLowerCase().trim())) {
|
|
3550
|
+
console.log('RULED OUT: EMAIL');
|
|
3435
3551
|
return;
|
|
3436
3552
|
}
|
|
3437
3553
|
// User id doesn't match
|
|
@@ -3440,6 +3556,7 @@ const LogReviewer = (props) => {
|
|
|
3440
3556
|
log.userId
|
|
3441
3557
|
// User id doesn't match
|
|
3442
3558
|
&& !String(log.userId).includes(advancedFilterState.userId.trim())) {
|
|
3559
|
+
console.log('RULED OUT: USER ID');
|
|
3443
3560
|
return;
|
|
3444
3561
|
}
|
|
3445
3562
|
// Learner not allowed
|
|
@@ -3448,6 +3565,7 @@ const LogReviewer = (props) => {
|
|
|
3448
3565
|
log.isLearner
|
|
3449
3566
|
// Learners aren't included
|
|
3450
3567
|
&& !advancedFilterState.includeLearners) {
|
|
3568
|
+
console.log('RULED OUT: LEARNER');
|
|
3451
3569
|
return;
|
|
3452
3570
|
}
|
|
3453
3571
|
// TTM not allowed
|
|
@@ -3456,6 +3574,7 @@ const LogReviewer = (props) => {
|
|
|
3456
3574
|
log.isTTM
|
|
3457
3575
|
// TTMs aren't included
|
|
3458
3576
|
&& !advancedFilterState.includeTTMs) {
|
|
3577
|
+
console.log('RULED OUT: TTM');
|
|
3459
3578
|
return;
|
|
3460
3579
|
}
|
|
3461
3580
|
// Admin not allowed
|
|
@@ -3464,6 +3583,7 @@ const LogReviewer = (props) => {
|
|
|
3464
3583
|
log.isAdmin
|
|
3465
3584
|
// Admins aren't included
|
|
3466
3585
|
&& !advancedFilterState.includeAdmins) {
|
|
3586
|
+
console.log('RULED OUT: ADMIN');
|
|
3467
3587
|
return;
|
|
3468
3588
|
}
|
|
3469
3589
|
// Course Id doesn't match
|
|
@@ -3472,6 +3592,7 @@ const LogReviewer = (props) => {
|
|
|
3472
3592
|
log.courseId
|
|
3473
3593
|
// Course Id doesn't match
|
|
3474
3594
|
&& !String(log.courseId).includes(advancedFilterState.courseId.trim())) {
|
|
3595
|
+
console.log('RULED OUT: COURSE ID');
|
|
3475
3596
|
return;
|
|
3476
3597
|
}
|
|
3477
3598
|
// Course name doesn't match
|
|
@@ -3480,6 +3601,7 @@ const LogReviewer = (props) => {
|
|
|
3480
3601
|
log.courseName
|
|
3481
3602
|
// Course name doesn't match
|
|
3482
3603
|
&& !String(log.courseName).includes(advancedFilterState.courseName.trim())) {
|
|
3604
|
+
console.log('RULED OUT: COURSE NAME');
|
|
3483
3605
|
return;
|
|
3484
3606
|
}
|
|
3485
3607
|
// Mobile filter doesn't match
|
|
@@ -3490,6 +3612,7 @@ const LogReviewer = (props) => {
|
|
|
3490
3612
|
&& log.device
|
|
3491
3613
|
// Mobile filter doesn't match
|
|
3492
3614
|
&& (advancedFilterState.isMobile === log.device.isMobile)) {
|
|
3615
|
+
console.log('RULED OUT: MOBILE');
|
|
3493
3616
|
return;
|
|
3494
3617
|
}
|
|
3495
3618
|
// Log source doesn't match
|
|
@@ -3500,6 +3623,7 @@ const LogReviewer = (props) => {
|
|
|
3500
3623
|
&& log.source
|
|
3501
3624
|
// Source filter doesn't match
|
|
3502
3625
|
&& (advancedFilterState.source !== log.source)) {
|
|
3626
|
+
console.log('RULED OUT: SOURCE');
|
|
3503
3627
|
return;
|
|
3504
3628
|
}
|
|
3505
3629
|
// Route path doesn't match (Only for server source)
|
|
@@ -3510,6 +3634,7 @@ const LogReviewer = (props) => {
|
|
|
3510
3634
|
&& (advancedFilterState.routePath.trim().length)
|
|
3511
3635
|
// Route path doesn't match
|
|
3512
3636
|
&& !(log.routePath.includes(advancedFilterState.routePath.trim()))) {
|
|
3637
|
+
console.log('RULED OUT: PATH');
|
|
3513
3638
|
return;
|
|
3514
3639
|
}
|
|
3515
3640
|
// Route template doesn't match (Only for server source)
|
|
@@ -3520,6 +3645,7 @@ const LogReviewer = (props) => {
|
|
|
3520
3645
|
&& (advancedFilterState.routeTemplate.trim().length)
|
|
3521
3646
|
// Route template doesn't match
|
|
3522
3647
|
&& !(log.routeTemplate.includes(advancedFilterState.routeTemplate.trim()))) {
|
|
3648
|
+
console.log('RULED OUT: TEMPLATE');
|
|
3523
3649
|
return;
|
|
3524
3650
|
}
|
|
3525
3651
|
/* -------------- Done -------------- */
|
|
@@ -3719,11 +3845,17 @@ const LogReviewer = (props) => {
|
|
|
3719
3845
|
},
|
|
3720
3846
|
];
|
|
3721
3847
|
// Create intelliTable
|
|
3722
|
-
const dataTable = (
|
|
3848
|
+
const dataTable = (logs.length === 0
|
|
3849
|
+
? (React.createElement(React.Fragment, null,
|
|
3850
|
+
React.createElement("h3", { className: "m-0" }, "Matching Logs:"),
|
|
3851
|
+
React.createElement("div", { className: "alert alert-warning text-center" },
|
|
3852
|
+
React.createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
3853
|
+
React.createElement("div", null, "Either your filters are too strict or no matching logs have been created yet."))))
|
|
3854
|
+
: (React.createElement(IntelliTable, { title: "Matching Logs:", id: "logs", data: logs, columns: columns })));
|
|
3723
3855
|
// Main body
|
|
3724
3856
|
body = (React.createElement(React.Fragment, null,
|
|
3725
3857
|
filters,
|
|
3726
|
-
dataTable));
|
|
3858
|
+
React.createElement("div", { className: "mt-2" }, dataTable)));
|
|
3727
3859
|
}
|
|
3728
3860
|
/* ---------- Wrap in Modal --------- */
|
|
3729
3861
|
return (React.createElement("div", { className: "LogReviewer-outer-container" },
|
|
@@ -3731,14 +3863,10 @@ const LogReviewer = (props) => {
|
|
|
3731
3863
|
React.createElement("div", { className: "LogReviewer-inner-container" },
|
|
3732
3864
|
React.createElement("div", { className: "LogReviewer-header" },
|
|
3733
3865
|
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 }))),
|
|
3866
|
+
React.createElement("h3", { className: "text-center m-0" }, "Log Review Dashboard")),
|
|
3867
|
+
React.createElement("div", { style: { width: 0 } },
|
|
3868
|
+
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 },
|
|
3869
|
+
React.createElement(FontAwesomeIcon, { icon: faTimes })))),
|
|
3742
3870
|
React.createElement("div", { className: "LogReviewer-contents" }, body))));
|
|
3743
3871
|
};
|
|
3744
3872
|
|
|
@@ -3884,7 +4012,7 @@ const padZerosLeft = (num, numDigits) => {
|
|
|
3884
4012
|
* access to log review
|
|
3885
4013
|
* @author Gabe Abrams
|
|
3886
4014
|
*/
|
|
3887
|
-
const LOG_REVIEW_STATUS_ROUTE =
|
|
4015
|
+
const LOG_REVIEW_STATUS_ROUTE = `${ROUTE_PATH_PREFIX}/logs/access_allowed`;
|
|
3888
4016
|
|
|
3889
4017
|
// Stored copy of caccl functions
|
|
3890
4018
|
let _cacclGetLaunchInfo;
|
|
@@ -3926,7 +4054,7 @@ const internalGetLogCollection = () => {
|
|
|
3926
4054
|
* @param opts.getLaunchInfo CACCL LTI's get launch info function
|
|
3927
4055
|
* @param [opts.logCollection] mongo collection from dce-mango to use for
|
|
3928
4056
|
* storing logs. If none is included, logs are written to the console
|
|
3929
|
-
* @param [opts.logReviewAdmins=all
|
|
4057
|
+
* @param [opts.logReviewAdmins=all] info on which admins can review
|
|
3930
4058
|
* logs from the client. If not included, all Canvas admins are allowed to
|
|
3931
4059
|
* review logs. If null, no Canvas admins are allowed to review logs.
|
|
3932
4060
|
* If an array of Canvas userIds (numbers), only Canvas admins with those
|
|
@@ -4009,71 +4137,81 @@ const initServer = (opts) => {
|
|
|
4009
4137
|
/*----------------------------------------*/
|
|
4010
4138
|
/* Log Reviewer */
|
|
4011
4139
|
/*----------------------------------------*/
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4140
|
+
/**
|
|
4141
|
+
* Check if a given user is allowed to review logs
|
|
4142
|
+
* @author Gabe Abrams
|
|
4143
|
+
* @param userId the id of the user
|
|
4144
|
+
* @param isAdmin if true, the user is an admin
|
|
4145
|
+
* @returns true if the user can review logs
|
|
4146
|
+
*/
|
|
4147
|
+
const canReviewLogs = (userId, isAdmin) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4148
|
+
// Immediately deny access if user is not an admin
|
|
4149
|
+
if (!isAdmin) {
|
|
4150
|
+
return false;
|
|
4151
|
+
}
|
|
4152
|
+
// If all admins are allowed, we're done
|
|
4153
|
+
if (!opts.logReviewAdmins) {
|
|
4154
|
+
return true;
|
|
4155
|
+
}
|
|
4156
|
+
// Do a dynamic check
|
|
4157
|
+
try {
|
|
4158
|
+
// Array of userIds
|
|
4159
|
+
if (Array.isArray(opts.logReviewAdmins)) {
|
|
4160
|
+
return opts.logReviewAdmins.some((allowedId) => {
|
|
4161
|
+
return (userId === allowedId);
|
|
4162
|
+
});
|
|
4031
4163
|
}
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4164
|
+
// Must be a collection
|
|
4165
|
+
const matches = yield opts.logReviewAdmins.find({ userId });
|
|
4166
|
+
// Make sure at least one entry matches
|
|
4167
|
+
return matches.length > 0;
|
|
4168
|
+
}
|
|
4169
|
+
catch (err) {
|
|
4170
|
+
// If an error occurred, simply return false
|
|
4171
|
+
return false;
|
|
4172
|
+
}
|
|
4173
|
+
});
|
|
4174
|
+
/**
|
|
4175
|
+
* Check if the current user has access to logs
|
|
4176
|
+
* @author Gabe Abrams
|
|
4177
|
+
* @returns {boolean} true if user has access
|
|
4178
|
+
*/
|
|
4179
|
+
opts.app.get(LOG_REVIEW_STATUS_ROUTE, genRouteHandler({
|
|
4180
|
+
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4181
|
+
const { userId, isAdmin } = params;
|
|
4182
|
+
const canReview = yield canReviewLogs(userId, isAdmin);
|
|
4183
|
+
return canReview;
|
|
4184
|
+
}),
|
|
4185
|
+
}));
|
|
4186
|
+
/**
|
|
4187
|
+
* Get all logs for a certain month
|
|
4188
|
+
* @author Gabe Abrams
|
|
4189
|
+
* @param {number} year the year to query (e.g. 2022)
|
|
4190
|
+
* @param {number} month the month to query (e.g. 1 = January)
|
|
4191
|
+
* @returns {Log[]} list of logs from the given month
|
|
4192
|
+
*/
|
|
4193
|
+
opts.app.get(`${LOG_REVIEW_ROUTE_PATH_PREFIX}/years/:year/months/:month`, genRouteHandler({
|
|
4194
|
+
paramTypes: {
|
|
4195
|
+
year: ParamType$1.Int,
|
|
4196
|
+
month: ParamType$1.Int,
|
|
4197
|
+
},
|
|
4198
|
+
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4199
|
+
// Get user info
|
|
4200
|
+
const { year, month, userId, isAdmin, } = params;
|
|
4201
|
+
// Validate user
|
|
4202
|
+
const canReview = yield canReviewLogs(userId, isAdmin);
|
|
4203
|
+
if (!canReview) {
|
|
4204
|
+
throw new ErrorWithCode('You cannot access this resource because you do not have the appropriate permissions.', ReactKitErrorCode$1.NotAllowedToReviewLogs);
|
|
4035
4205
|
}
|
|
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
|
-
}
|
|
4206
|
+
// Query for logs
|
|
4207
|
+
const logs = yield _logCollection.find({
|
|
4208
|
+
year,
|
|
4209
|
+
month,
|
|
4210
|
+
});
|
|
4211
|
+
// Return logs
|
|
4212
|
+
return logs;
|
|
4213
|
+
}),
|
|
4214
|
+
}));
|
|
4077
4215
|
};
|
|
4078
4216
|
|
|
4079
4217
|
// Import shared types
|
|
@@ -4373,18 +4511,6 @@ const parseUserAgent = (userAgent) => {
|
|
|
4373
4511
|
};
|
|
4374
4512
|
};
|
|
4375
4513
|
|
|
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
4514
|
/**
|
|
4389
4515
|
* Generate an express API route handler
|
|
4390
4516
|
* @author Gabe Abrams
|
|
@@ -4757,7 +4883,7 @@ const genRouteHandler = (opts) => {
|
|
|
4757
4883
|
}
|
|
4758
4884
|
: {
|
|
4759
4885
|
type: LogType$1.Action,
|
|
4760
|
-
target: ((_m = opts.target) !== null && _m !== void 0 ? _m : LogBuiltInMetadata.Target.
|
|
4886
|
+
target: ((_m = opts.target) !== null && _m !== void 0 ? _m : LogBuiltInMetadata.Target.NoTarget),
|
|
4761
4887
|
action: ((_o = opts.action) !== null && _o !== void 0 ? _o : LogAction$1.Unknown),
|
|
4762
4888
|
});
|
|
4763
4889
|
// Source-specific info
|
|
@@ -5124,6 +5250,31 @@ const initLogCollection = (Collection) => {
|
|
|
5124
5250
|
});
|
|
5125
5251
|
};
|
|
5126
5252
|
|
|
5253
|
+
// Cache user's ability
|
|
5254
|
+
let canReview = undefined;
|
|
5255
|
+
/**
|
|
5256
|
+
* Check if the current user can review logs
|
|
5257
|
+
* @author Gabe Abrams
|
|
5258
|
+
* @returns true if current user can review logs
|
|
5259
|
+
*/
|
|
5260
|
+
const canReviewLogs = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
5261
|
+
// If cached, use that value
|
|
5262
|
+
if (canReview !== undefined) {
|
|
5263
|
+
return canReview;
|
|
5264
|
+
}
|
|
5265
|
+
// Ask on server
|
|
5266
|
+
try {
|
|
5267
|
+
canReview = !!(yield visitServerEndpoint({
|
|
5268
|
+
path: LOG_REVIEW_STATUS_ROUTE,
|
|
5269
|
+
method: 'GET',
|
|
5270
|
+
}));
|
|
5271
|
+
}
|
|
5272
|
+
catch (err) {
|
|
5273
|
+
canReview = false;
|
|
5274
|
+
}
|
|
5275
|
+
return canReview;
|
|
5276
|
+
});
|
|
5277
|
+
|
|
5127
5278
|
/**
|
|
5128
5279
|
* Days of the week
|
|
5129
5280
|
* @author Gabe Abrams
|
|
@@ -5140,5 +5291,5 @@ var DayOfWeek;
|
|
|
5140
5291
|
})(DayOfWeek || (DayOfWeek = {}));
|
|
5141
5292
|
var DayOfWeek$1 = DayOfWeek;
|
|
5142
5293
|
|
|
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 };
|
|
5294
|
+
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
5295
|
//# sourceMappingURL=index.js.map
|