dce-reactkit 4.0.0-beta-date-and-time.1 → 4.0.0-beta-logreviewer.1
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 +712 -943
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Pagination.d.ts +9 -0
- package/dist/cjs/types/components/SimpleDateChooser.d.ts +1 -3
- package/dist/cjs/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- package/dist/cjs/types/helpers/cloneDeep.d.ts +8 -0
- package/dist/cjs/types/index.d.ts +4 -2
- package/dist/cjs/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +13 -0
- package/dist/cjs/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +17 -0
- package/dist/cjs/types/types/LogReviewerFilterState/ContextFilterState.d.ts +6 -0
- package/dist/cjs/types/types/LogReviewerFilterState/DateFilterState.d.ts +13 -0
- package/dist/cjs/types/types/LogReviewerFilterState/TagFilterState.d.ts +4 -0
- package/dist/cjs/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +1 -3
- package/dist/esm/index.js +711 -944
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Pagination.d.ts +9 -0
- package/dist/esm/types/components/SimpleDateChooser.d.ts +1 -3
- package/dist/esm/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- package/dist/esm/types/helpers/cloneDeep.d.ts +8 -0
- package/dist/esm/types/index.d.ts +4 -2
- package/dist/esm/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +13 -0
- package/dist/esm/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +17 -0
- package/dist/esm/types/types/LogReviewerFilterState/ContextFilterState.d.ts +6 -0
- package/dist/esm/types/types/LogReviewerFilterState/DateFilterState.d.ts +13 -0
- package/dist/esm/types/types/LogReviewerFilterState/TagFilterState.d.ts +4 -0
- package/dist/esm/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +1 -3
- package/dist/index.d.ts +94 -41
- package/package.json +3 -3
- package/rollup.config.js +0 -2
- package/src/components/LogReviewer.tsx +1133 -1307
- package/src/components/Pagination.tsx +162 -0
- package/src/components/SimpleDateChooser.tsx +26 -62
- package/src/constants/LOG_REVIEW_GET_LOGS_ROUTE.ts +9 -0
- package/src/helpers/cloneDeep.ts +11 -0
- package/src/index.ts +6 -2
- package/src/types/LogReviewerFilterState/ActionErrorFilterState.ts +21 -0
- package/src/types/LogReviewerFilterState/AdvancedFilterState.ts +33 -0
- package/src/types/LogReviewerFilterState/ContextFilterState.ts +13 -0
- package/src/types/LogReviewerFilterState/DateFilterState.ts +23 -0
- package/src/types/LogReviewerFilterState/TagFilterState.ts +6 -0
- package/src/types/LogReviewerFilterState/index.ts +24 -0
- package/src/types/ReactKitErrorCode.tsx +1 -3
- package/dist/cjs/types/components/SimpleTimeChooser.d.ts +0 -20
- package/dist/esm/types/components/SimpleTimeChooser.d.ts +0 -20
- package/genEncodedSecret.ts +0 -84
- package/src/components/SimpleTimeChooser.tsx +0 -195
package/dist/cjs/index.js
CHANGED
|
@@ -6,6 +6,7 @@ var React = require('react');
|
|
|
6
6
|
var freeSolidSvgIcons = require('@fortawesome/free-solid-svg-icons');
|
|
7
7
|
var reactFontawesome = require('@fortawesome/react-fontawesome');
|
|
8
8
|
var freeRegularSvgIcons = require('@fortawesome/free-regular-svg-icons');
|
|
9
|
+
var clone = require('nanoclone');
|
|
9
10
|
|
|
10
11
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
12
|
|
|
@@ -29,6 +30,7 @@ function _interopNamespace(e) {
|
|
|
29
30
|
|
|
30
31
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
31
32
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
33
|
+
var clone__default = /*#__PURE__*/_interopDefaultLegacy(clone);
|
|
32
34
|
|
|
33
35
|
/*! *****************************************************************************
|
|
34
36
|
Copyright (c) Microsoft Corporation.
|
|
@@ -55,7 +57,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
55
57
|
});
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
// Highest error code =
|
|
60
|
+
// Highest error code = DRK34
|
|
59
61
|
/**
|
|
60
62
|
* List of error codes built into the react kit
|
|
61
63
|
* @author Gabe Abrams
|
|
@@ -66,8 +68,6 @@ var ReactKitErrorCode;
|
|
|
66
68
|
ReactKitErrorCode["NoCode"] = "DRK2";
|
|
67
69
|
ReactKitErrorCode["SessionExpired"] = "DRK3";
|
|
68
70
|
ReactKitErrorCode["NoCACCLSendRequestFunction"] = "DRK7";
|
|
69
|
-
ReactKitErrorCode["SimpleDateChooserInvalidDateRange"] = "DRK35";
|
|
70
|
-
ReactKitErrorCode["SimpleDateChooserInvalidNumMonths"] = "DRK36";
|
|
71
71
|
})(ReactKitErrorCode || (ReactKitErrorCode = {}));
|
|
72
72
|
var ReactKitErrorCode$1 = ReactKitErrorCode;
|
|
73
73
|
|
|
@@ -2549,19 +2549,6 @@ const ButtonInputGroup = (props) => {
|
|
|
2549
2549
|
: children))));
|
|
2550
2550
|
};
|
|
2551
2551
|
|
|
2552
|
-
// Constants
|
|
2553
|
-
const ORDINALS = ['th', 'st', 'nd', 'rd'];
|
|
2554
|
-
/**
|
|
2555
|
-
* Get a number's ordinal
|
|
2556
|
-
* @author Gabe Abrams
|
|
2557
|
-
* @param num the number being analyzed
|
|
2558
|
-
* @returns ordinal
|
|
2559
|
-
*/
|
|
2560
|
-
const getOrdinal = (num) => {
|
|
2561
|
-
var _a, _b;
|
|
2562
|
-
return ((_b = (_a = ORDINALS[(num - 20) % 10]) !== null && _a !== void 0 ? _a : ORDINALS[num]) !== null && _b !== void 0 ? _b : ORDINALS[0]);
|
|
2563
|
-
};
|
|
2564
|
-
|
|
2565
2552
|
const monthNames = [
|
|
2566
2553
|
{ short: 'Jan', full: 'January' },
|
|
2567
2554
|
{ short: 'Feb', full: 'February' },
|
|
@@ -2590,6 +2577,19 @@ const getMonthName = (month) => {
|
|
|
2590
2577
|
return ((_a = monthNames[month - 1]) !== null && _a !== void 0 ? _a : monthNames[0]);
|
|
2591
2578
|
};
|
|
2592
2579
|
|
|
2580
|
+
// Constants
|
|
2581
|
+
const ORDINALS = ['th', 'st', 'nd', 'rd'];
|
|
2582
|
+
/**
|
|
2583
|
+
* Get a number's ordinal
|
|
2584
|
+
* @author Gabe Abrams
|
|
2585
|
+
* @param num the number being analyzed
|
|
2586
|
+
* @returns ordinal
|
|
2587
|
+
*/
|
|
2588
|
+
const getOrdinal = (num) => {
|
|
2589
|
+
var _a, _b;
|
|
2590
|
+
return ((_b = (_a = ORDINALS[(num - 20) % 10]) !== null && _a !== void 0 ? _a : ORDINALS[num]) !== null && _b !== void 0 ? _b : ORDINALS[0]);
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2593
2593
|
/**
|
|
2594
2594
|
* Get current time info in US Boston Eastern Time, independent of machine
|
|
2595
2595
|
* timezone
|
|
@@ -2653,7 +2653,6 @@ const getTimeInfoInET = (dateOrTimestamp) => {
|
|
|
2653
2653
|
/**
|
|
2654
2654
|
* A very simple, lightweight date chooser
|
|
2655
2655
|
* @author Gabe Abrams
|
|
2656
|
-
* @author Gardeniu Liu
|
|
2657
2656
|
*/
|
|
2658
2657
|
/*------------------------------------------------------------------------*/
|
|
2659
2658
|
/* ------------------------------ Component ----------------------------- */
|
|
@@ -2663,7 +2662,7 @@ const SimpleDateChooser = (props) => {
|
|
|
2663
2662
|
/* -------------------------------- Setup ------------------------------- */
|
|
2664
2663
|
/*------------------------------------------------------------------------*/
|
|
2665
2664
|
/* -------------- Props ------------- */
|
|
2666
|
-
const { ariaLabel, name, onChange, numMonthsToShow = 6,
|
|
2665
|
+
const { ariaLabel, name, onChange, chooseFromPast, numMonthsToShow = 6, } = props;
|
|
2667
2666
|
/*------------------------------------------------------------------------*/
|
|
2668
2667
|
/* ------------------------------- Render ------------------------------- */
|
|
2669
2668
|
/*------------------------------------------------------------------------*/
|
|
@@ -2675,28 +2674,14 @@ const SimpleDateChooser = (props) => {
|
|
|
2675
2674
|
const choices = [];
|
|
2676
2675
|
let startYear = today.year;
|
|
2677
2676
|
let startMonth = today.month;
|
|
2678
|
-
|
|
2679
|
-
if (dontAllowPast && dontAllowFuture) {
|
|
2680
|
-
throw new ErrorWithCode('No past or future dates allowed', ReactKitErrorCode$1.SimpleDateChooserInvalidDateRange);
|
|
2681
|
-
}
|
|
2682
|
-
// Require numMonthsToShow to be positive
|
|
2683
|
-
if (numMonthsToShow <= 0) {
|
|
2684
|
-
throw new ErrorWithCode('numMonthsToShow must be positive', ReactKitErrorCode$1.SimpleDateChooserInvalidNumMonths);
|
|
2685
|
-
}
|
|
2686
|
-
// Recalculate startMonth and startYear when allowing past dates
|
|
2687
|
-
if (!dontAllowPast) {
|
|
2677
|
+
if (chooseFromPast) {
|
|
2688
2678
|
startMonth -= Math.max(0, numMonthsToShow - 1);
|
|
2689
2679
|
while (startMonth <= 0) {
|
|
2690
2680
|
startMonth += 12;
|
|
2691
2681
|
startYear -= 1;
|
|
2692
2682
|
}
|
|
2693
2683
|
}
|
|
2694
|
-
|
|
2695
|
-
let totalMonthsToShow = numMonthsToShow;
|
|
2696
|
-
if (!dontAllowPast && !dontAllowFuture) {
|
|
2697
|
-
totalMonthsToShow = totalMonthsToShow * 2 - 1;
|
|
2698
|
-
}
|
|
2699
|
-
for (let i = 0; i < totalMonthsToShow; i++) {
|
|
2684
|
+
for (let i = 0; i < numMonthsToShow; i++) {
|
|
2700
2685
|
// Get month and year info
|
|
2701
2686
|
const unmoddedMonth = (startMonth + i);
|
|
2702
2687
|
let month = unmoddedMonth;
|
|
@@ -2715,25 +2700,23 @@ const SimpleDateChooser = (props) => {
|
|
|
2715
2700
|
// Figure out which days are allowed
|
|
2716
2701
|
const days = [];
|
|
2717
2702
|
const numDaysInMonth = (new Date(year, month, 0)).getDate();
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
days.push(today.day); // Add current day
|
|
2727
|
-
// Future selection: add all remaining days of the month
|
|
2728
|
-
if (!dontAllowFuture) {
|
|
2729
|
-
for (let day = today.day + 1; day <= numDaysInMonth; day++) {
|
|
2730
|
-
days.push(day);
|
|
2731
|
-
}
|
|
2703
|
+
if (chooseFromPast) {
|
|
2704
|
+
// Past selection
|
|
2705
|
+
const numDaysToAdd = ((month === today.month)
|
|
2706
|
+
? today.day // Current month, only add up to today
|
|
2707
|
+
: numDaysInMonth // Past month, add all days
|
|
2708
|
+
);
|
|
2709
|
+
for (let day = 1; day <= numDaysToAdd; day++) {
|
|
2710
|
+
days.push(day);
|
|
2732
2711
|
}
|
|
2733
2712
|
}
|
|
2734
|
-
else {
|
|
2735
|
-
//
|
|
2736
|
-
|
|
2713
|
+
else {
|
|
2714
|
+
// Future selection: add all remaining days of the month
|
|
2715
|
+
const firstDay = (month === today.month
|
|
2716
|
+
? today.day // Current month: start at current date
|
|
2717
|
+
: 1 // Future month: start at beginning of month
|
|
2718
|
+
);
|
|
2719
|
+
for (let day = firstDay; day <= numDaysInMonth; day++) {
|
|
2737
2720
|
days.push(day);
|
|
2738
2721
|
}
|
|
2739
2722
|
}
|
|
@@ -2753,8 +2736,8 @@ const SimpleDateChooser = (props) => {
|
|
|
2753
2736
|
monthOptions.push(React__default["default"].createElement("option", { key: `${choice.year}-${choice.month}`, value: `${choice.month}-${choice.year}`, "aria-label": `choose ${choice.choiceName}`, onSelect: () => {
|
|
2754
2737
|
onChange(choice.month, choice.days[0], choice.year);
|
|
2755
2738
|
} }, choice.choiceName));
|
|
2756
|
-
// This is the currently selected month
|
|
2757
2739
|
if (month === choice.month) {
|
|
2740
|
+
// This is the currently selected month
|
|
2758
2741
|
// Create day options
|
|
2759
2742
|
choice.days.forEach((dayChoice) => {
|
|
2760
2743
|
const ordinal = getOrdinal(dayChoice);
|
|
@@ -2776,125 +2759,6 @@ const SimpleDateChooser = (props) => {
|
|
|
2776
2759
|
} }, dayOptions)));
|
|
2777
2760
|
};
|
|
2778
2761
|
|
|
2779
|
-
/**
|
|
2780
|
-
* Pad a number with zeros on the left (e.g. 5 becomes 05 with 2 digit padding)
|
|
2781
|
-
* @author Gabe Abrams
|
|
2782
|
-
* @param num the number to pad
|
|
2783
|
-
* @param numDigits the minimum number of digits before the decimal
|
|
2784
|
-
* @returns padded number
|
|
2785
|
-
*/
|
|
2786
|
-
const padZerosLeft = (num, numDigits) => {
|
|
2787
|
-
// Convert to string
|
|
2788
|
-
let out = String(num);
|
|
2789
|
-
// Add zeros
|
|
2790
|
-
while (out.split('.')[0].length < numDigits) {
|
|
2791
|
-
out = `0${out}`;
|
|
2792
|
-
}
|
|
2793
|
-
// Return
|
|
2794
|
-
return out;
|
|
2795
|
-
};
|
|
2796
|
-
|
|
2797
|
-
/**
|
|
2798
|
-
* A very simple, lightweight time chooser
|
|
2799
|
-
* @author Gardenia Liu
|
|
2800
|
-
*/
|
|
2801
|
-
/*------------------------------------------------------------------------*/
|
|
2802
|
-
/* ------------------------------ Constants ----------------------------- */
|
|
2803
|
-
/*------------------------------------------------------------------------*/
|
|
2804
|
-
// Allowed intervals between options
|
|
2805
|
-
const ALLOWED_INTERVALS = [15, 30, 60]; // min
|
|
2806
|
-
// Default interval to use if an unsupported interval is passed in
|
|
2807
|
-
const DEFAULT_INTERVAL = ALLOWED_INTERVALS[0]; // min
|
|
2808
|
-
/*------------------------------------------------------------------------*/
|
|
2809
|
-
/* ------------------------------ Component ----------------------------- */
|
|
2810
|
-
/*------------------------------------------------------------------------*/
|
|
2811
|
-
const SimpleTimeChooser = (props) => {
|
|
2812
|
-
/*------------------------------------------------------------------------*/
|
|
2813
|
-
/* -------------------------------- Setup ------------------------------- */
|
|
2814
|
-
/*------------------------------------------------------------------------*/
|
|
2815
|
-
/* -------------- Props ------------- */
|
|
2816
|
-
const { ariaLabel, name, hour, minute, onChange, } = props;
|
|
2817
|
-
let { intervalMin = DEFAULT_INTERVAL, } = props;
|
|
2818
|
-
// Use default interval if not supported
|
|
2819
|
-
if (ALLOWED_INTERVALS.includes(intervalMin)) {
|
|
2820
|
-
intervalMin = DEFAULT_INTERVAL;
|
|
2821
|
-
}
|
|
2822
|
-
/*------------------------------------------------------------------------*/
|
|
2823
|
-
/* ------------------------- Component Functions ------------------------ */
|
|
2824
|
-
/*------------------------------------------------------------------------*/
|
|
2825
|
-
/**
|
|
2826
|
-
* Convert number of minutes since midnight into 24hour and minute format
|
|
2827
|
-
* @author Gabe Abrams
|
|
2828
|
-
* @param minSinceMidnight total minutes since midnight
|
|
2829
|
-
* @returns hours (24) and minutes
|
|
2830
|
-
*/
|
|
2831
|
-
const convertMinSinceMidnightToHoursAndMin = (minSinceMidnight) => {
|
|
2832
|
-
return {
|
|
2833
|
-
hours: Math.floor(minSinceMidnight / 60),
|
|
2834
|
-
minutes: minSinceMidnight % 60,
|
|
2835
|
-
};
|
|
2836
|
-
};
|
|
2837
|
-
/**
|
|
2838
|
-
* Convert time in minutes into HH:MM format
|
|
2839
|
-
* @author Gardenia Liu
|
|
2840
|
-
* @param totalMinutes total minutes since midnight
|
|
2841
|
-
* @returns formatted time string
|
|
2842
|
-
*/
|
|
2843
|
-
const formatTime = (totalMinutes) => {
|
|
2844
|
-
// Handle special cases
|
|
2845
|
-
if (totalMinutes === 0) {
|
|
2846
|
-
return '12:00 Midnight';
|
|
2847
|
-
}
|
|
2848
|
-
if (totalMinutes === 12 * 60) {
|
|
2849
|
-
return '12:00 Noon';
|
|
2850
|
-
}
|
|
2851
|
-
// All normal cases:
|
|
2852
|
-
const timeInfo = convertMinSinceMidnightToHoursAndMin(totalMinutes);
|
|
2853
|
-
let { hours } = timeInfo;
|
|
2854
|
-
const { minutes } = timeInfo;
|
|
2855
|
-
// Process 24hr -> 12hr
|
|
2856
|
-
const isAM = (hours < 12);
|
|
2857
|
-
if (hours === 0) {
|
|
2858
|
-
hours = 12;
|
|
2859
|
-
}
|
|
2860
|
-
else if (hours > 12) {
|
|
2861
|
-
hours %= 12;
|
|
2862
|
-
}
|
|
2863
|
-
// Pad with zeros
|
|
2864
|
-
const paddedMinutes = padZerosLeft(minutes, 2);
|
|
2865
|
-
// Assemble time string
|
|
2866
|
-
return `${hours}:${paddedMinutes} ${isAM ? 'AM' : 'PM'}`;
|
|
2867
|
-
};
|
|
2868
|
-
/*------------------------------------------------------------------------*/
|
|
2869
|
-
/* ------------------------------- Render ------------------------------- */
|
|
2870
|
-
/*------------------------------------------------------------------------*/
|
|
2871
|
-
/*----------------------------------------*/
|
|
2872
|
-
/* --------------- Main UI -------------- */
|
|
2873
|
-
/*----------------------------------------*/
|
|
2874
|
-
// Generate list of time options
|
|
2875
|
-
const times = [];
|
|
2876
|
-
for (let time = 0; time < 24 * 60; time += intervalMin) {
|
|
2877
|
-
times.push(formatTime(time));
|
|
2878
|
-
}
|
|
2879
|
-
// Create choice options
|
|
2880
|
-
const selectedTimeMin = hour * 60 + minute; // minutes since midnight
|
|
2881
|
-
const timeOptions = times.map((timeString, timeIndex) => {
|
|
2882
|
-
// Create time option
|
|
2883
|
-
const numMinutesForChoice = timeIndex * intervalMin;
|
|
2884
|
-
// Render the option
|
|
2885
|
-
return (React__default["default"].createElement("option", { key: numMinutesForChoice, value: numMinutesForChoice, "aria-label": `choose ${timeString}` }, timeString));
|
|
2886
|
-
});
|
|
2887
|
-
return (React__default["default"].createElement("div", { className: "SimpleTimeChooser-container", "aria-label": `time chooser with selected time: ${formatTime(selectedTimeMin)}` },
|
|
2888
|
-
React__default["default"].createElement("select", { "aria-label": `time for ${ariaLabel}`, className: "custom-select d-inline-block", style: { width: 'auto' }, id: `SimpleTimeChooser-${name}-time`, value: selectedTimeMin, onChange: (e) => {
|
|
2889
|
-
// Parse selector value (string)
|
|
2890
|
-
const newTime = Number.parseInt(e.target.value, 10);
|
|
2891
|
-
// Convert minutes since midnight to hour and minute
|
|
2892
|
-
const timeInfo = convertMinSinceMidnightToHoursAndMin(newTime);
|
|
2893
|
-
// Notify parent of change
|
|
2894
|
-
onChange(timeInfo.hours, timeInfo.minutes);
|
|
2895
|
-
} }, timeOptions)));
|
|
2896
|
-
};
|
|
2897
|
-
|
|
2898
2762
|
/**
|
|
2899
2763
|
* Drawer container
|
|
2900
2764
|
* @author Gabe Abrams
|
|
@@ -3650,10 +3514,10 @@ const getHumanReadableDate = (dateOrTimestamp) => {
|
|
|
3650
3514
|
};
|
|
3651
3515
|
|
|
3652
3516
|
/**
|
|
3653
|
-
* Path of the route for
|
|
3517
|
+
* Path of the route for getting logs for log review
|
|
3654
3518
|
* @author Gabe Abrams
|
|
3655
3519
|
*/
|
|
3656
|
-
const
|
|
3520
|
+
const LOG_REVIEW_GET_LOGS_ROUTE = `/admin${ROUTE_PATH_PREFIX}/logs`;
|
|
3657
3521
|
|
|
3658
3522
|
/**
|
|
3659
3523
|
* Source of a log event
|
|
@@ -4258,6 +4122,70 @@ const IntelliTable = (props) => {
|
|
|
4258
4122
|
} }, table)));
|
|
4259
4123
|
};
|
|
4260
4124
|
|
|
4125
|
+
// Import React
|
|
4126
|
+
/*------------------------------------------------------------------------*/
|
|
4127
|
+
/* ------------------------------ Component ----------------------------- */
|
|
4128
|
+
/*------------------------------------------------------------------------*/
|
|
4129
|
+
const Pagination = ({ currentPage, numPages, loading = false, onPageChanged, }) => {
|
|
4130
|
+
/*------------------------------------------------------------------------*/
|
|
4131
|
+
/* -------------------------------- Setup ------------------------------- */
|
|
4132
|
+
/*------------------------------------------------------------------------*/
|
|
4133
|
+
// Compute pages to display
|
|
4134
|
+
const pages = [];
|
|
4135
|
+
const delta = 2; // how many pages to show on either side of current
|
|
4136
|
+
let start = Math.max(1, currentPage - delta);
|
|
4137
|
+
let end = Math.min(numPages, currentPage + delta);
|
|
4138
|
+
// If we are too close to the beginning or end, shift the window.
|
|
4139
|
+
if (currentPage - delta < 1) {
|
|
4140
|
+
end = Math.min(numPages, end + (1 - (currentPage - delta)));
|
|
4141
|
+
}
|
|
4142
|
+
if (currentPage + delta > numPages) {
|
|
4143
|
+
start = Math.max(1, start - ((currentPage + delta) - numPages));
|
|
4144
|
+
}
|
|
4145
|
+
for (let i = start; i <= end; i++) {
|
|
4146
|
+
pages.push(i);
|
|
4147
|
+
}
|
|
4148
|
+
/*------------------------------------------------------------------------*/
|
|
4149
|
+
/* ------------------------------- Render ------------------------------- */
|
|
4150
|
+
/*------------------------------------------------------------------------*/
|
|
4151
|
+
return (React__default["default"].createElement("nav", { "aria-label": "Page navigation for logs", className: "mt-3" },
|
|
4152
|
+
React__default["default"].createElement("ul", { className: "pagination justify-content-center" },
|
|
4153
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage <= 1 || loading) ? 'disabled' : ''}` },
|
|
4154
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(currentPage - 1); }, disabled: currentPage <= 1 || loading, "aria-label": "Go to previous page" },
|
|
4155
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowLeft }),
|
|
4156
|
+
' ',
|
|
4157
|
+
"Prev")),
|
|
4158
|
+
currentPage > 3
|
|
4159
|
+
&& pages[0] !== 1
|
|
4160
|
+
&& (React__default["default"].createElement("li", { className: "page-item" },
|
|
4161
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(1); }, disabled: loading, "aria-label": "Go to page 1" }, "1"))),
|
|
4162
|
+
currentPage > 4 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
4163
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
4164
|
+
pages.map((pageNum) => {
|
|
4165
|
+
return (React__default["default"].createElement("li", { key: pageNum, className: `page-item ${pageNum === currentPage ? 'active' : ''}` },
|
|
4166
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(pageNum); }, disabled: loading, "aria-label": `Go to page ${pageNum}` }, pageNum)));
|
|
4167
|
+
}),
|
|
4168
|
+
currentPage < numPages - 3 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
4169
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
4170
|
+
currentPage < numPages - 2
|
|
4171
|
+
&& pages[pages.length - 1] !== numPages
|
|
4172
|
+
&& (React__default["default"].createElement("li", { className: "page-item" },
|
|
4173
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(numPages); }, disabled: loading, "aria-label": "Go to last page" }, numPages))),
|
|
4174
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage >= numPages || loading) ? 'disabled' : ''}` },
|
|
4175
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(currentPage + 1); }, disabled: currentPage >= numPages || loading, "aria-label": "Go to next page" },
|
|
4176
|
+
"Next",
|
|
4177
|
+
' ',
|
|
4178
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowRight }))))));
|
|
4179
|
+
};
|
|
4180
|
+
|
|
4181
|
+
/**
|
|
4182
|
+
* Deeply clones an object
|
|
4183
|
+
* @author Yuen Ler Chow
|
|
4184
|
+
* @param obj the object to clone
|
|
4185
|
+
* @returns a deep clone of the object
|
|
4186
|
+
*/
|
|
4187
|
+
const cloneDeep = clone__default["default"];
|
|
4188
|
+
|
|
4261
4189
|
/**
|
|
4262
4190
|
* Log reviewer panel that allows users (must be approved admins) to
|
|
4263
4191
|
* review logs written by dce-reactkit
|
|
@@ -4613,7 +4541,7 @@ var ActionType$6;
|
|
|
4613
4541
|
(function (ActionType) {
|
|
4614
4542
|
// Show the loading bar
|
|
4615
4543
|
ActionType["StartLoading"] = "start-loading";
|
|
4616
|
-
// Finish loading
|
|
4544
|
+
// Finish loading logs
|
|
4617
4545
|
ActionType["FinishLoading"] = "finish-loading";
|
|
4618
4546
|
// Reset filters to initial values
|
|
4619
4547
|
ActionType["ResetFilters"] = "reset-filters";
|
|
@@ -4631,6 +4559,14 @@ var ActionType$6;
|
|
|
4631
4559
|
ActionType["UpdateActionErrorFilterState"] = "update-action-error-filter-state";
|
|
4632
4560
|
// Update the advanced filter state
|
|
4633
4561
|
ActionType["UpdateAdvancedFilterState"] = "update-advanced-filter-state";
|
|
4562
|
+
// Set has another page
|
|
4563
|
+
ActionType["SetHasAnotherPage"] = "set-has-another-page";
|
|
4564
|
+
// Set the number of pages
|
|
4565
|
+
ActionType["SetNumPages"] = "set-num-pages";
|
|
4566
|
+
// Set page number
|
|
4567
|
+
ActionType["SetPageNumber"] = "set-page-number";
|
|
4568
|
+
// Reset user made filter change indicator
|
|
4569
|
+
ActionType["ResetUserMadeFilterChange"] = "reset-user-made-filter-change";
|
|
4634
4570
|
})(ActionType$6 || (ActionType$6 = {}));
|
|
4635
4571
|
/**
|
|
4636
4572
|
* Reducer that executes actions
|
|
@@ -4644,7 +4580,7 @@ const reducer$7 = (state, action) => {
|
|
|
4644
4580
|
return Object.assign(Object.assign({}, state), { loading: true });
|
|
4645
4581
|
}
|
|
4646
4582
|
case ActionType$6.FinishLoading: {
|
|
4647
|
-
return Object.assign(Object.assign({}, state), { loading: false,
|
|
4583
|
+
return Object.assign(Object.assign({}, state), { loading: false, logs: action.logs });
|
|
4648
4584
|
}
|
|
4649
4585
|
case ActionType$6.ToggleFilterDrawer: {
|
|
4650
4586
|
return Object.assign(Object.assign({}, state), { expandedFilterDrawer: (state.expandedFilterDrawer === action.filterDrawer
|
|
@@ -4655,22 +4591,34 @@ const reducer$7 = (state, action) => {
|
|
|
4655
4591
|
return Object.assign(Object.assign({}, state), { expandedFilterDrawer: undefined });
|
|
4656
4592
|
}
|
|
4657
4593
|
case ActionType$6.ResetFilters: {
|
|
4658
|
-
return Object.assign(Object.assign({}, state), {
|
|
4594
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.initDateFilterState, pendingContextFilterState: action.initContextFilterState, pendingTagFilterState: action.initTagFilterState, pendingActionErrorFilterState: action.initActionErrorFilterState, pendingAdvancedFilterState: action.initAdvancedFilterState, pageNumber: 1 });
|
|
4659
4595
|
}
|
|
4660
4596
|
case ActionType$6.UpdateDateFilterState: {
|
|
4661
|
-
return Object.assign(Object.assign({}, state), {
|
|
4597
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.dateFilterState, userMadeFilterChange: true });
|
|
4662
4598
|
}
|
|
4663
4599
|
case ActionType$6.UpdateContextFilterState: {
|
|
4664
|
-
return Object.assign(Object.assign({}, state), {
|
|
4600
|
+
return Object.assign(Object.assign({}, state), { pendingContextFilterState: action.contextFilterState, userMadeFilterChange: true });
|
|
4665
4601
|
}
|
|
4666
4602
|
case ActionType$6.UpdateTagFilterState: {
|
|
4667
|
-
return Object.assign(Object.assign({}, state), {
|
|
4603
|
+
return Object.assign(Object.assign({}, state), { pendingTagFilterState: action.tagFilterState, userMadeFilterChange: true });
|
|
4668
4604
|
}
|
|
4669
4605
|
case ActionType$6.UpdateActionErrorFilterState: {
|
|
4670
|
-
return Object.assign(Object.assign({}, state), {
|
|
4606
|
+
return Object.assign(Object.assign({}, state), { pendingActionErrorFilterState: action.actionErrorFilterState, userMadeFilterChange: true });
|
|
4671
4607
|
}
|
|
4672
4608
|
case ActionType$6.UpdateAdvancedFilterState: {
|
|
4673
|
-
return Object.assign(Object.assign({}, state), {
|
|
4609
|
+
return Object.assign(Object.assign({}, state), { pendingAdvancedFilterState: action.advancedFilterState, userMadeFilterChange: true });
|
|
4610
|
+
}
|
|
4611
|
+
case ActionType$6.SetHasAnotherPage: {
|
|
4612
|
+
return Object.assign(Object.assign({}, state), { hasAnotherPage: action.hasAnotherPage });
|
|
4613
|
+
}
|
|
4614
|
+
case ActionType$6.SetNumPages: {
|
|
4615
|
+
return Object.assign(Object.assign({}, state), { numPages: action.numPages });
|
|
4616
|
+
}
|
|
4617
|
+
case ActionType$6.SetPageNumber: {
|
|
4618
|
+
return Object.assign(Object.assign({}, state), { pageNumber: action.pageNumber });
|
|
4619
|
+
}
|
|
4620
|
+
case ActionType$6.ResetUserMadeFilterChange: {
|
|
4621
|
+
return Object.assign(Object.assign({}, state), { userMadeFilterChange: false });
|
|
4674
4622
|
}
|
|
4675
4623
|
default: {
|
|
4676
4624
|
return state;
|
|
@@ -4741,7 +4689,7 @@ const LogReviewer = (props) => {
|
|
|
4741
4689
|
else {
|
|
4742
4690
|
// Case: subcontexts exist
|
|
4743
4691
|
initContextFilterState[context] = {};
|
|
4744
|
-
Object.
|
|
4692
|
+
Object.keys(contextMap[context]).forEach((subcontext) => {
|
|
4745
4693
|
// Skip self ("_")
|
|
4746
4694
|
if (subcontext === '_') {
|
|
4747
4695
|
return;
|
|
@@ -4789,125 +4737,105 @@ const LogReviewer = (props) => {
|
|
|
4789
4737
|
// Initial state
|
|
4790
4738
|
const initialState = {
|
|
4791
4739
|
loading: true,
|
|
4792
|
-
|
|
4740
|
+
logs: [],
|
|
4793
4741
|
expandedFilterDrawer: undefined,
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4742
|
+
pendingDateFilterState: initDateFilterState,
|
|
4743
|
+
pendingContextFilterState: initContextFilterState,
|
|
4744
|
+
pendingTagFilterState: initTagFilterState,
|
|
4745
|
+
pendingActionErrorFilterState: initActionErrorFilterState,
|
|
4746
|
+
pendingAdvancedFilterState: initAdvancedFilterState,
|
|
4747
|
+
pageNumber: 1,
|
|
4748
|
+
hasAnotherPage: false,
|
|
4749
|
+
numPages: 1,
|
|
4750
|
+
userMadeFilterChange: false,
|
|
4799
4751
|
};
|
|
4800
4752
|
// Initialize state
|
|
4801
4753
|
const [state, dispatch] = React.useReducer(reducer$7, initialState);
|
|
4802
4754
|
// Destructure common state
|
|
4803
|
-
const { loading,
|
|
4755
|
+
const { loading, logs, expandedFilterDrawer, pendingDateFilterState, pendingContextFilterState, pendingTagFilterState, pendingActionErrorFilterState, pendingAdvancedFilterState, pageNumber, numPages, userMadeFilterChange, } = state;
|
|
4756
|
+
/* -------------- Refs -------------- */
|
|
4757
|
+
// Initialize refs
|
|
4758
|
+
const activeFiltersRef = React.useRef({
|
|
4759
|
+
dateFilterState: JSON.parse(JSON.stringify(pendingDateFilterState)),
|
|
4760
|
+
contextFilterState: JSON.parse(JSON.stringify(pendingContextFilterState)),
|
|
4761
|
+
tagFilterState: JSON.parse(JSON.stringify(pendingTagFilterState)),
|
|
4762
|
+
actionErrorFilterState: JSON.parse(JSON.stringify(pendingActionErrorFilterState)),
|
|
4763
|
+
advancedFilterState: JSON.parse(JSON.stringify(pendingAdvancedFilterState)),
|
|
4764
|
+
});
|
|
4804
4765
|
/*------------------------------------------------------------------------*/
|
|
4805
4766
|
/* ------------------------- Component Functions ------------------------ */
|
|
4806
4767
|
/*------------------------------------------------------------------------*/
|
|
4807
4768
|
/**
|
|
4808
|
-
*
|
|
4809
|
-
*
|
|
4810
|
-
* @
|
|
4811
|
-
* @param
|
|
4812
|
-
* @
|
|
4813
|
-
|
|
4814
|
-
const listMonthsToLoad = (newDateFilterState) => {
|
|
4815
|
-
// List of year/month combos that need to be loaded
|
|
4816
|
-
const toLoad = [];
|
|
4817
|
-
// Loop through dates
|
|
4818
|
-
let { year, month } = newDateFilterState.startDate;
|
|
4819
|
-
while (
|
|
4820
|
-
// Earlier year
|
|
4821
|
-
(year < newDateFilterState.endDate.year)
|
|
4822
|
-
// Current year but included month
|
|
4823
|
-
|| (year === newDateFilterState.endDate.year
|
|
4824
|
-
&& month <= newDateFilterState.endDate.month)) {
|
|
4825
|
-
// Add to list if not already loaded
|
|
4826
|
-
if (!logMap[year]
|
|
4827
|
-
|| !logMap[year][month]) {
|
|
4828
|
-
toLoad.push({
|
|
4829
|
-
year,
|
|
4830
|
-
month,
|
|
4831
|
-
});
|
|
4832
|
-
}
|
|
4833
|
-
// Increment
|
|
4834
|
-
month += 1;
|
|
4835
|
-
if (month > 12) {
|
|
4836
|
-
month -= 12;
|
|
4837
|
-
year += 1;
|
|
4838
|
-
}
|
|
4839
|
-
}
|
|
4840
|
-
// Return
|
|
4841
|
-
return toLoad;
|
|
4842
|
-
};
|
|
4843
|
-
/**
|
|
4844
|
-
* Handle updated start/end dates (updates state, loads if necessary)
|
|
4845
|
-
* @author Gabe Abrams
|
|
4846
|
-
* @param newDateFilterState the new date filter state
|
|
4769
|
+
* Fetch logs from the server based on current filters
|
|
4770
|
+
* @author Yuen Ler Chow
|
|
4771
|
+
* @param opts object containing all arguments
|
|
4772
|
+
* @param opts.filters the filters to apply
|
|
4773
|
+
* @param opts.pageNum the page number to fetch
|
|
4774
|
+
* @param opts.filtersChanged if true, the filters have changed
|
|
4847
4775
|
*/
|
|
4848
|
-
const
|
|
4849
|
-
|
|
4850
|
-
dispatch({
|
|
4851
|
-
type: ActionType$6.UpdateDateFilterState,
|
|
4852
|
-
dateFilterState: newDateFilterState,
|
|
4853
|
-
});
|
|
4854
|
-
// Check which year/month combos we need to load
|
|
4855
|
-
const toLoad = listMonthsToLoad(newDateFilterState);
|
|
4856
|
-
// If nothing to load, finished
|
|
4857
|
-
if (toLoad.length === 0) {
|
|
4858
|
-
return;
|
|
4859
|
-
}
|
|
4860
|
-
// Start loading
|
|
4776
|
+
const fetchLogs = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4777
|
+
const { filters, pageNum, filtersChanged, } = opts;
|
|
4861
4778
|
dispatch({
|
|
4862
4779
|
type: ActionType$6.StartLoading,
|
|
4863
4780
|
});
|
|
4864
|
-
// Load required months
|
|
4865
4781
|
try {
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
}
|
|
4889
|
-
logMap[year][month] = logs;
|
|
4782
|
+
// Send filters to the server
|
|
4783
|
+
let fetchedLogs = [];
|
|
4784
|
+
// Get logs from server
|
|
4785
|
+
const response = yield visitServerEndpoint({
|
|
4786
|
+
path: LOG_REVIEW_GET_LOGS_ROUTE,
|
|
4787
|
+
method: 'GET',
|
|
4788
|
+
params: {
|
|
4789
|
+
pageNumber: pageNum,
|
|
4790
|
+
filters,
|
|
4791
|
+
countDocuments: filtersChanged,
|
|
4792
|
+
},
|
|
4793
|
+
});
|
|
4794
|
+
fetchedLogs = fetchedLogs.concat(response.items);
|
|
4795
|
+
dispatch({
|
|
4796
|
+
type: ActionType$6.SetHasAnotherPage,
|
|
4797
|
+
hasAnotherPage: response.hasAnotherPage,
|
|
4798
|
+
});
|
|
4799
|
+
if (filtersChanged && response.numPages !== undefined) {
|
|
4800
|
+
dispatch({
|
|
4801
|
+
type: ActionType$6.SetNumPages,
|
|
4802
|
+
numPages: response.numPages,
|
|
4803
|
+
});
|
|
4890
4804
|
}
|
|
4805
|
+
// Update logs in state
|
|
4806
|
+
dispatch({
|
|
4807
|
+
type: ActionType$6.FinishLoading,
|
|
4808
|
+
logs: fetchedLogs,
|
|
4809
|
+
});
|
|
4810
|
+
// Update page number
|
|
4811
|
+
dispatch({
|
|
4812
|
+
type: ActionType$6.SetPageNumber,
|
|
4813
|
+
pageNumber: pageNum,
|
|
4814
|
+
});
|
|
4891
4815
|
}
|
|
4892
4816
|
catch (err) {
|
|
4893
4817
|
return showFatalError(err);
|
|
4894
4818
|
}
|
|
4895
|
-
// Finish loading
|
|
4896
|
-
dispatch({
|
|
4897
|
-
type: ActionType$6.FinishLoading,
|
|
4898
|
-
logMap,
|
|
4899
|
-
});
|
|
4900
4819
|
});
|
|
4901
4820
|
/*------------------------------------------------------------------------*/
|
|
4902
4821
|
/* ------------------------- Lifecycle Functions ------------------------ */
|
|
4903
4822
|
/*------------------------------------------------------------------------*/
|
|
4904
4823
|
/**
|
|
4905
|
-
*
|
|
4906
|
-
* @author
|
|
4824
|
+
* Fetch logs on mount
|
|
4825
|
+
* @author Yuen Ler Chow
|
|
4907
4826
|
*/
|
|
4908
4827
|
React.useEffect(() => {
|
|
4909
|
-
|
|
4910
|
-
|
|
4828
|
+
fetchLogs({
|
|
4829
|
+
filters: {
|
|
4830
|
+
dateFilterState: pendingDateFilterState,
|
|
4831
|
+
contextFilterState: pendingContextFilterState,
|
|
4832
|
+
tagFilterState: pendingTagFilterState,
|
|
4833
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4834
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4835
|
+
},
|
|
4836
|
+
pageNum: 1,
|
|
4837
|
+
filtersChanged: true,
|
|
4838
|
+
});
|
|
4911
4839
|
}, []);
|
|
4912
4840
|
/*------------------------------------------------------------------------*/
|
|
4913
4841
|
/* ------------------------------- Render ------------------------------- */
|
|
@@ -4915,718 +4843,534 @@ const LogReviewer = (props) => {
|
|
|
4915
4843
|
/*----------------------------------------*/
|
|
4916
4844
|
/* --------------- Main UI -------------- */
|
|
4917
4845
|
/*----------------------------------------*/
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4846
|
+
/*----------------------------------------*/
|
|
4847
|
+
/* ------------ Pagination -------------- */
|
|
4848
|
+
/*----------------------------------------*/
|
|
4849
|
+
const paginationControls = logs.length > 0 && (React__default["default"].createElement(Pagination, { currentPage: pageNumber, numPages: numPages, loading: loading, onPageChanged: (targetPage) => {
|
|
4850
|
+
const { current: activeFilters } = activeFiltersRef;
|
|
4851
|
+
fetchLogs({
|
|
4852
|
+
filters: {
|
|
4853
|
+
dateFilterState: activeFilters.dateFilterState,
|
|
4854
|
+
contextFilterState: activeFilters.contextFilterState,
|
|
4855
|
+
tagFilterState: activeFilters.tagFilterState,
|
|
4856
|
+
actionErrorFilterState: activeFilters.actionErrorFilterState,
|
|
4857
|
+
advancedFilterState: activeFilters.advancedFilterState,
|
|
4858
|
+
},
|
|
4859
|
+
pageNum: targetPage,
|
|
4860
|
+
filtersChanged: false,
|
|
4861
|
+
});
|
|
4862
|
+
} }));
|
|
4863
|
+
/*----------------------------------------*/
|
|
4864
|
+
/* --------------- Filters -------------- */
|
|
4865
|
+
/*----------------------------------------*/
|
|
4866
|
+
// Filter toggle
|
|
4867
|
+
const filterToggles = (React__default["default"].createElement("div", { className: "LogReviewer-filter-toggles" },
|
|
4868
|
+
React__default["default"].createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
|
|
4869
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-date-filter-drawer", className: `btn btn-${FilterDrawer.Date === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle date filter drawer", onClick: () => {
|
|
4870
|
+
dispatch({
|
|
4871
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
4872
|
+
filterDrawer: FilterDrawer.Date,
|
|
4873
|
+
});
|
|
4874
|
+
} },
|
|
4875
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCalendar, className: "me-2" }),
|
|
4876
|
+
"Date"),
|
|
4877
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-context-filter-drawer", className: `btn btn-${FilterDrawer.Context === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle context filter drawer", onClick: () => {
|
|
4878
|
+
dispatch({
|
|
4879
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
4880
|
+
filterDrawer: FilterDrawer.Context,
|
|
4881
|
+
});
|
|
4882
|
+
} },
|
|
4883
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "me-2" }),
|
|
4884
|
+
"Context"),
|
|
4885
|
+
(LogMetadata.Tag && Object.keys(LogMetadata.Tag).length > 0) && (React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-tag-filter-drawer", className: `btn btn-${FilterDrawer.Tag === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle tag filter drawer", onClick: () => {
|
|
4886
|
+
dispatch({
|
|
4887
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
4888
|
+
filterDrawer: FilterDrawer.Tag,
|
|
4889
|
+
});
|
|
4890
|
+
} },
|
|
4891
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTag, className: "me-2" }),
|
|
4892
|
+
"Tag")),
|
|
4893
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-action-filter-drawer", className: `btn btn-${FilterDrawer.Action === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle action and error filter drawer", onClick: () => {
|
|
4894
|
+
dispatch({
|
|
4895
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
4896
|
+
filterDrawer: FilterDrawer.Action,
|
|
4897
|
+
});
|
|
4898
|
+
} },
|
|
4899
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faHammer, className: "me-2" }),
|
|
4900
|
+
"Action"),
|
|
4901
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-toggle-advanced-filter-drawer", className: `btn btn-${FilterDrawer.Advanced === expandedFilterDrawer ? 'warning' : 'light'} me-2`, "aria-label": "toggle advanced filter drawer", onClick: () => {
|
|
4902
|
+
dispatch({
|
|
4903
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
4904
|
+
filterDrawer: FilterDrawer.Advanced,
|
|
4905
|
+
});
|
|
4906
|
+
} },
|
|
4907
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faList, className: "me-2" }),
|
|
4908
|
+
"Advanced"),
|
|
4909
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-reset-filters-button", className: "btn btn-light", "aria-label": "reset filters", onClick: () => {
|
|
4910
|
+
// Save active filters
|
|
4911
|
+
// Deep clone the initial filter states to avoid any reference issues
|
|
4912
|
+
// if the filter states are modified later
|
|
4913
|
+
activeFiltersRef.current = cloneDeep({
|
|
4914
|
+
dateFilterState: initDateFilterState,
|
|
4915
|
+
contextFilterState: initContextFilterState,
|
|
4916
|
+
tagFilterState: initTagFilterState,
|
|
4917
|
+
actionErrorFilterState: initActionErrorFilterState,
|
|
4918
|
+
advancedFilterState: initAdvancedFilterState,
|
|
4919
|
+
});
|
|
4920
|
+
fetchLogs({
|
|
4921
|
+
filters: {
|
|
4922
|
+
dateFilterState: initDateFilterState,
|
|
4923
|
+
contextFilterState: initContextFilterState,
|
|
4924
|
+
tagFilterState: initTagFilterState,
|
|
4925
|
+
actionErrorFilterState: initActionErrorFilterState,
|
|
4926
|
+
advancedFilterState: initAdvancedFilterState,
|
|
4927
|
+
},
|
|
4928
|
+
pageNum: 1,
|
|
4929
|
+
filtersChanged: true,
|
|
4930
|
+
});
|
|
4931
|
+
dispatch({
|
|
4932
|
+
type: ActionType$6.ResetFilters,
|
|
4933
|
+
initActionErrorFilterState,
|
|
4934
|
+
initAdvancedFilterState,
|
|
4935
|
+
initContextFilterState,
|
|
4936
|
+
initDateFilterState,
|
|
4937
|
+
initTagFilterState,
|
|
4938
|
+
});
|
|
4939
|
+
dispatch({
|
|
4940
|
+
type: ActionType$6.HideFilterDrawer,
|
|
4941
|
+
});
|
|
4942
|
+
} },
|
|
4943
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes }),
|
|
4944
|
+
' ',
|
|
4945
|
+
"Reset"),
|
|
4946
|
+
userMadeFilterChange && (React__default["default"].createElement("button", { type: "button", id: "LogReviewer-submit-filters-button", className: "btn btn-primary ms-2", "aria-label": "submit filters", onClick: () => {
|
|
4947
|
+
dispatch({
|
|
4948
|
+
type: ActionType$6.HideFilterDrawer,
|
|
4949
|
+
});
|
|
4950
|
+
// Reset user made filter change indicator
|
|
4951
|
+
dispatch({
|
|
4952
|
+
type: ActionType$6.ResetUserMadeFilterChange,
|
|
4953
|
+
});
|
|
4954
|
+
// Save active filters
|
|
4955
|
+
// Deep clone the pending filter states to avoid any reference issues
|
|
4956
|
+
// if the filter states are modified later
|
|
4957
|
+
activeFiltersRef.current = cloneDeep({
|
|
4958
|
+
dateFilterState: pendingDateFilterState,
|
|
4959
|
+
contextFilterState: pendingContextFilterState,
|
|
4960
|
+
tagFilterState: pendingTagFilterState,
|
|
4961
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4962
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4963
|
+
});
|
|
4964
|
+
fetchLogs({
|
|
4965
|
+
filters: {
|
|
4966
|
+
dateFilterState: pendingDateFilterState,
|
|
4967
|
+
contextFilterState: pendingContextFilterState,
|
|
4968
|
+
tagFilterState: pendingTagFilterState,
|
|
4969
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4970
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4971
|
+
},
|
|
4972
|
+
pageNum: 1,
|
|
4973
|
+
filtersChanged: true,
|
|
4974
|
+
});
|
|
4975
|
+
} },
|
|
4976
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faSearch }),
|
|
4977
|
+
' ',
|
|
4978
|
+
"Apply Filters")))));
|
|
4979
|
+
// Filter drawer
|
|
4980
|
+
let filterDrawer;
|
|
4981
|
+
if (expandedFilterDrawer) {
|
|
4982
|
+
if (expandedFilterDrawer === FilterDrawer.Date) {
|
|
4983
|
+
filterDrawer = (React__default["default"].createElement(TabBox, { title: "Date" },
|
|
4984
|
+
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter start date", name: "filter-start-date", year: pendingDateFilterState.startDate.year, month: pendingDateFilterState.startDate.month, day: pendingDateFilterState.startDate.day, chooseFromPast: true, numMonthsToShow: 36, onChange: (month, day, year) => {
|
|
4985
|
+
const newDateFilterState = Object.assign(Object.assign({}, pendingDateFilterState), { startDate: { month, day, year } });
|
|
4967
4986
|
dispatch({
|
|
4968
|
-
type: ActionType$6.
|
|
4969
|
-
|
|
4987
|
+
type: ActionType$6.UpdateDateFilterState,
|
|
4988
|
+
dateFilterState: newDateFilterState,
|
|
4970
4989
|
});
|
|
4971
|
-
} },
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4990
|
+
} }),
|
|
4991
|
+
' ',
|
|
4992
|
+
"to",
|
|
4993
|
+
' ',
|
|
4994
|
+
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: pendingDateFilterState.endDate.year, month: pendingDateFilterState.endDate.month, day: pendingDateFilterState.endDate.day, chooseFromPast: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
4995
|
+
if (year < pendingDateFilterState.startDate.year
|
|
4996
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
4997
|
+
&& month < pendingDateFilterState.startDate.month)
|
|
4998
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
4999
|
+
&& month === pendingDateFilterState.startDate.month
|
|
5000
|
+
&& day < pendingDateFilterState.startDate.day)) {
|
|
5001
|
+
return alert('Invalid End Date', 'The end date cannot be before the start date.');
|
|
5002
|
+
}
|
|
5003
|
+
const newDateFilterState = Object.assign(Object.assign({}, pendingDateFilterState), { endDate: { month, day, year } });
|
|
4975
5004
|
dispatch({
|
|
4976
|
-
type: ActionType$6.
|
|
4977
|
-
|
|
4978
|
-
initAdvancedFilterState,
|
|
4979
|
-
initContextFilterState,
|
|
4980
|
-
initDateFilterState,
|
|
4981
|
-
initTagFilterState,
|
|
5005
|
+
type: ActionType$6.UpdateDateFilterState,
|
|
5006
|
+
dateFilterState: newDateFilterState,
|
|
4982
5007
|
});
|
|
4983
|
-
} }
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
React__default["default"].createElement(SimpleDateChooser, { ariaLabel: "filter end date", name: "filter-end-date", year: dateFilterState.endDate.year, month: dateFilterState.endDate.month, day: dateFilterState.endDate.day, dontAllowFuture: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
5000
|
-
if (year < dateFilterState.startDate.year
|
|
5001
|
-
|| (year === dateFilterState.startDate.year
|
|
5002
|
-
&& month < dateFilterState.startDate.month)
|
|
5003
|
-
|| (year === dateFilterState.startDate.year
|
|
5004
|
-
&& month === dateFilterState.startDate.month
|
|
5005
|
-
&& day < dateFilterState.startDate.day)) {
|
|
5006
|
-
return alert('Invalid Start Date', 'The start date cannot be before the end date.');
|
|
5007
|
-
}
|
|
5008
|
-
dateFilterState.endDate = { month, day, year };
|
|
5009
|
-
handleDateRangeUpdated(dateFilterState);
|
|
5010
|
-
} })));
|
|
5011
|
-
}
|
|
5012
|
-
else if (expandedFilterDrawer === FilterDrawer.Context) {
|
|
5013
|
-
// Create item picker items
|
|
5014
|
-
const builtInPickableItem = {
|
|
5015
|
-
id: 'built-in-contexts',
|
|
5016
|
-
name: 'Auto-logged',
|
|
5017
|
-
isGroup: true,
|
|
5018
|
-
children: [],
|
|
5019
|
-
};
|
|
5020
|
-
const pickableItems = [];
|
|
5021
|
-
Object.keys(contextMap)
|
|
5022
|
-
.forEach((context) => {
|
|
5023
|
-
const value = contextMap[context];
|
|
5024
|
-
if (typeof value === 'string') {
|
|
5025
|
-
// No subcategories
|
|
5026
|
-
const item = {
|
|
5027
|
-
id: context,
|
|
5028
|
-
name: genHumanReadableName(context),
|
|
5029
|
-
isGroup: false,
|
|
5030
|
-
checked: !!contextFilterState[context],
|
|
5031
|
-
};
|
|
5032
|
-
// Add built-in items to its own folder
|
|
5033
|
-
const isBuiltIn = context in LogBuiltInMetadata.Context;
|
|
5034
|
-
if (isBuiltIn) {
|
|
5035
|
-
// Add to built-in pickable item
|
|
5036
|
-
builtInPickableItem.children.push(item);
|
|
5037
|
-
}
|
|
5038
|
-
else {
|
|
5039
|
-
// Add to pickable items list
|
|
5040
|
-
pickableItems.push(item);
|
|
5041
|
-
}
|
|
5042
|
-
return;
|
|
5043
|
-
}
|
|
5044
|
-
// Has subcategories
|
|
5045
|
-
const children = (Object.keys(value)
|
|
5046
|
-
// Remove parent name
|
|
5047
|
-
.filter((subcontext) => {
|
|
5048
|
-
return subcontext !== '_';
|
|
5049
|
-
})
|
|
5050
|
-
// Create child pickable items
|
|
5051
|
-
.map((subcontext) => {
|
|
5052
|
-
return {
|
|
5053
|
-
id: subcontext,
|
|
5054
|
-
name: genHumanReadableName(subcontext),
|
|
5055
|
-
isGroup: false,
|
|
5056
|
-
checked: contextFilterState[context][subcontext],
|
|
5057
|
-
};
|
|
5058
|
-
}));
|
|
5008
|
+
} })));
|
|
5009
|
+
}
|
|
5010
|
+
else if (expandedFilterDrawer === FilterDrawer.Context) {
|
|
5011
|
+
// Create item picker items
|
|
5012
|
+
const builtInPickableItem = {
|
|
5013
|
+
id: 'built-in-contexts',
|
|
5014
|
+
name: 'Auto-logged',
|
|
5015
|
+
isGroup: true,
|
|
5016
|
+
children: [],
|
|
5017
|
+
};
|
|
5018
|
+
const pickableItems = [];
|
|
5019
|
+
Object.keys(contextMap)
|
|
5020
|
+
.forEach((context) => {
|
|
5021
|
+
const value = contextMap[context];
|
|
5022
|
+
if (typeof value === 'string') {
|
|
5023
|
+
// No subcategories
|
|
5059
5024
|
const item = {
|
|
5060
5025
|
id: context,
|
|
5061
5026
|
name: genHumanReadableName(context),
|
|
5062
|
-
isGroup:
|
|
5063
|
-
|
|
5027
|
+
isGroup: false,
|
|
5028
|
+
checked: !!pendingContextFilterState[context],
|
|
5064
5029
|
};
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5030
|
+
// Add built-in items to its own folder
|
|
5031
|
+
const isBuiltIn = context in LogBuiltInMetadata.Context;
|
|
5032
|
+
if (isBuiltIn) {
|
|
5033
|
+
// Add to built-in pickable item
|
|
5034
|
+
builtInPickableItem.children.push(item);
|
|
5035
|
+
}
|
|
5036
|
+
else {
|
|
5037
|
+
// Add to pickable items list
|
|
5038
|
+
pickableItems.push(item);
|
|
5039
|
+
}
|
|
5040
|
+
return;
|
|
5041
|
+
}
|
|
5042
|
+
// Has subcategories
|
|
5043
|
+
const children = (Object.keys(value)
|
|
5044
|
+
// Remove parent name
|
|
5045
|
+
.filter((subcontext) => {
|
|
5046
|
+
return (subcontext !== '_');
|
|
5047
|
+
})
|
|
5048
|
+
// Create child pickable items
|
|
5049
|
+
.map((subcontext) => {
|
|
5050
|
+
return {
|
|
5051
|
+
id: subcontext,
|
|
5052
|
+
name: genHumanReadableName(subcontext),
|
|
5053
|
+
isGroup: false,
|
|
5054
|
+
checked: pendingContextFilterState[context][subcontext],
|
|
5055
|
+
};
|
|
5056
|
+
}));
|
|
5057
|
+
const item = {
|
|
5058
|
+
id: context,
|
|
5059
|
+
name: genHumanReadableName(context),
|
|
5060
|
+
isGroup: true,
|
|
5061
|
+
children,
|
|
5062
|
+
};
|
|
5063
|
+
pickableItems.push(item);
|
|
5064
|
+
});
|
|
5065
|
+
// Add built-in contexts to end of list
|
|
5066
|
+
pickableItems.push(builtInPickableItem);
|
|
5067
|
+
// Create filter UI
|
|
5068
|
+
filterDrawer = (React__default["default"].createElement(ItemPicker, { title: "Context", items: pickableItems, onChanged: (updatedItems) => {
|
|
5069
|
+
// Update our state
|
|
5070
|
+
const newContextFilterState = Object.assign({}, pendingContextFilterState);
|
|
5071
|
+
updatedItems.forEach((pickableItem) => {
|
|
5072
|
+
if (pickableItem.isGroup) {
|
|
5073
|
+
// Has subcontexts
|
|
5074
|
+
if (pickableItem.id === 'built-in-contexts') {
|
|
5075
|
+
// Built-in
|
|
5076
|
+
// Treat as if these were top-level contexts
|
|
5077
|
+
pickableItem.children.forEach((subcontextItem) => {
|
|
5078
|
+
newContextFilterState[subcontextItem.id] = ('checked' in subcontextItem
|
|
5079
|
+
&& subcontextItem.checked);
|
|
5080
|
+
});
|
|
5091
5081
|
}
|
|
5092
5082
|
else {
|
|
5093
|
-
//
|
|
5094
|
-
|
|
5083
|
+
// Not built-in
|
|
5084
|
+
pickableItem.children.forEach((subcontextItem) => {
|
|
5085
|
+
if (!subcontextItem.isGroup) {
|
|
5086
|
+
newContextFilterState[pickableItem.id][subcontextItem.id] = (subcontextItem.checked);
|
|
5087
|
+
}
|
|
5088
|
+
});
|
|
5095
5089
|
}
|
|
5096
|
-
}
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
}
|
|
5101
|
-
}
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5090
|
+
}
|
|
5091
|
+
else {
|
|
5092
|
+
// No subcontexts
|
|
5093
|
+
newContextFilterState[pickableItem.id] = (pickableItem.checked);
|
|
5094
|
+
}
|
|
5095
|
+
});
|
|
5096
|
+
// Update state
|
|
5097
|
+
dispatch({
|
|
5098
|
+
type: ActionType$6.UpdateContextFilterState,
|
|
5099
|
+
contextFilterState: newContextFilterState,
|
|
5100
|
+
});
|
|
5101
|
+
} }));
|
|
5102
|
+
}
|
|
5103
|
+
else if (expandedFilterDrawer === FilterDrawer.Tag) {
|
|
5104
|
+
// Create filter UI
|
|
5105
|
+
filterDrawer = (React__default["default"].createElement(TabBox, { title: "Tags" },
|
|
5106
|
+
React__default["default"].createElement("div", null, "If any tags are selected, logs must contain at least one (but not necessarily all) of the selected tags."),
|
|
5107
|
+
React__default["default"].createElement("div", { className: "d-flex gap-1 flex-wrap" }, Object.keys((_d = LogMetadata.Tag) !== null && _d !== void 0 ? _d : {})
|
|
5108
|
+
.map((tag) => {
|
|
5109
|
+
const description = genHumanReadableName(tag);
|
|
5110
|
+
return (React__default["default"].createElement(CheckboxButton, { key: tag, id: `LogReviewer-tag-${tag}-checkbox`, text: description, ariaLabel: `require that logs be tagged with "${description}" or any other selected tag`, checked: pendingTagFilterState[tag], onChanged: (checked) => {
|
|
5111
|
+
const newTagFilterState = Object.assign(Object.assign({}, pendingTagFilterState), { [tag]: checked });
|
|
5112
|
+
dispatch({
|
|
5113
|
+
type: ActionType$6.UpdateTagFilterState,
|
|
5114
|
+
tagFilterState: newTagFilterState,
|
|
5115
|
+
});
|
|
5116
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5117
|
+
}))));
|
|
5118
|
+
}
|
|
5119
|
+
else if (expandedFilterDrawer === FilterDrawer.Action) {
|
|
5120
|
+
// Create filter UI
|
|
5121
|
+
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5122
|
+
React__default["default"].createElement(TabBox, { title: "Log Type" },
|
|
5123
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
|
|
5124
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: undefined });
|
|
5125
|
+
dispatch({
|
|
5126
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5127
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5128
|
+
});
|
|
5129
|
+
}, ariaLabel: "show logs of all types", selected: pendingActionErrorFilterState.type === undefined, unselectedVariant: Variant$1.Light }),
|
|
5130
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-action-only", text: "Action Logs Only", onSelected: () => {
|
|
5131
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: LogType$1.Action });
|
|
5132
|
+
dispatch({
|
|
5133
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5134
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5135
|
+
});
|
|
5136
|
+
}, ariaLabel: "only show action logs", selected: pendingActionErrorFilterState.type === LogType$1.Action, unselectedVariant: Variant$1.Light }),
|
|
5137
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-error-only", text: "Action Error Only", onSelected: () => {
|
|
5138
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: LogType$1.Error });
|
|
5139
|
+
dispatch({
|
|
5140
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5141
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5142
|
+
});
|
|
5143
|
+
}, ariaLabel: "only show error logs", selected: pendingActionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
5144
|
+
(pendingActionErrorFilterState.type === undefined
|
|
5145
|
+
|| pendingActionErrorFilterState.type === LogType$1.Action) && (React__default["default"].createElement(TabBox, { title: "Action Log Details" },
|
|
5146
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Action", className: "mb-2", wrapButtonsAndAddGaps: true }, Object.keys(LogAction$1)
|
|
5147
|
+
.map((action) => {
|
|
5148
|
+
const description = genHumanReadableName(action);
|
|
5149
|
+
return (React__default["default"].createElement(CheckboxButton, { key: action, id: `LogReviewer-action-${action}-checkbox`, text: description, ariaLabel: `include logs with action type "${description}" in results`, noMarginOnRight: true, checked: pendingActionErrorFilterState.action[action], onChanged: (checked) => {
|
|
5150
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { action: Object.assign(Object.assign({}, pendingActionErrorFilterState.action), { [action]: checked }) });
|
|
5112
5151
|
dispatch({
|
|
5113
|
-
type: ActionType$6.
|
|
5114
|
-
|
|
5152
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5153
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5115
5154
|
});
|
|
5116
|
-
} }));
|
|
5117
|
-
}))
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
|
|
5124
|
-
actionErrorFilterState.type = undefined;
|
|
5155
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5156
|
+
})),
|
|
5157
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Target", wrapButtonsAndAddGaps: true }, Object.keys(targetMap)
|
|
5158
|
+
.map((target) => {
|
|
5159
|
+
const description = genHumanReadableName(target);
|
|
5160
|
+
return (React__default["default"].createElement(CheckboxButton, { key: target, id: `LogReviewer-target-${target}-checkbox`, text: description, ariaLabel: `include logs with target "${description}" in results`, checked: pendingActionErrorFilterState.target[target], noMarginOnRight: true, onChanged: (checked) => {
|
|
5161
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { target: Object.assign(Object.assign({}, pendingActionErrorFilterState.target), { [target]: checked }) });
|
|
5125
5162
|
dispatch({
|
|
5126
5163
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5127
|
-
actionErrorFilterState,
|
|
5164
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5128
5165
|
});
|
|
5129
|
-
},
|
|
5130
|
-
|
|
5131
|
-
|
|
5166
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5167
|
+
})))),
|
|
5168
|
+
(pendingActionErrorFilterState.type === undefined
|
|
5169
|
+
|| pendingActionErrorFilterState.type === LogType$1.Error) && (React__default["default"].createElement(TabBox, { title: "Error Log Details" },
|
|
5170
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5171
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Message"),
|
|
5172
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error message", value: pendingActionErrorFilterState.errorMessage, placeholder: "e.g. undefined is not a function", onChange: (e) => {
|
|
5173
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { errorMessage: e.target.value });
|
|
5132
5174
|
dispatch({
|
|
5133
5175
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5134
|
-
actionErrorFilterState,
|
|
5176
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5135
5177
|
});
|
|
5136
|
-
}
|
|
5137
|
-
|
|
5138
|
-
|
|
5178
|
+
} })),
|
|
5179
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5180
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Code"),
|
|
5181
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for error code", value: pendingActionErrorFilterState.errorCode, placeholder: "e.g. GC22", onChange: (e) => {
|
|
5182
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { errorCode: ((e.target.value)
|
|
5183
|
+
.trim()
|
|
5184
|
+
.toUpperCase()) });
|
|
5139
5185
|
dispatch({
|
|
5140
5186
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5141
|
-
actionErrorFilterState,
|
|
5187
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5142
5188
|
});
|
|
5143
|
-
}
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
React__default["default"].createElement("
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
dispatch({
|
|
5186
|
-
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5187
|
-
actionErrorFilterState,
|
|
5188
|
-
});
|
|
5189
|
-
} }))))));
|
|
5190
|
-
}
|
|
5191
|
-
else if (expandedFilterDrawer === FilterDrawer.Advanced) {
|
|
5192
|
-
// Create advanced filter ui
|
|
5193
|
-
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5194
|
-
React__default["default"].createElement(TabBox, { title: "User" },
|
|
5195
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5196
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "User First Name"),
|
|
5197
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user first name", value: advancedFilterState.userFirstName, placeholder: "e.g. Divardo", onChange: (e) => {
|
|
5198
|
-
advancedFilterState.userFirstName = e.target.value;
|
|
5199
|
-
dispatch({
|
|
5200
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5201
|
-
advancedFilterState,
|
|
5202
|
-
});
|
|
5203
|
-
} })),
|
|
5204
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5205
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "User Last Name"),
|
|
5206
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user last name", value: advancedFilterState.userLastName, placeholder: "e.g. Calicci", onChange: (e) => {
|
|
5207
|
-
advancedFilterState.userLastName = e.target.value;
|
|
5208
|
-
dispatch({
|
|
5209
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5210
|
-
advancedFilterState,
|
|
5211
|
-
});
|
|
5212
|
-
} })),
|
|
5213
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5214
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "User Email"),
|
|
5215
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user email", value: advancedFilterState.userEmail, placeholder: "e.g. calicci@fas.harvard.edu", onChange: (e) => {
|
|
5216
|
-
advancedFilterState.userEmail = ((e.target.value)
|
|
5217
|
-
.trim());
|
|
5218
|
-
dispatch({
|
|
5219
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5220
|
-
advancedFilterState,
|
|
5221
|
-
});
|
|
5222
|
-
} })),
|
|
5223
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5224
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "User Canvas Id"),
|
|
5225
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user canvas id", value: advancedFilterState.userId, placeholder: "e.g. 104985", onChange: (e) => {
|
|
5226
|
-
const { value } = e.target;
|
|
5227
|
-
// Only update if value contains only numbers
|
|
5228
|
-
if (/^\d+$/.test(value)) {
|
|
5229
|
-
advancedFilterState.userId = ((e.target.value)
|
|
5230
|
-
.trim());
|
|
5231
|
-
}
|
|
5232
|
-
dispatch({
|
|
5233
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5234
|
-
advancedFilterState,
|
|
5235
|
-
});
|
|
5236
|
-
} })),
|
|
5237
|
-
React__default["default"].createElement(ButtonInputGroup, { label: "Role" },
|
|
5238
|
-
React__default["default"].createElement(CheckboxButton, { text: "Students", onChanged: (checked) => {
|
|
5239
|
-
advancedFilterState.includeLearners = checked;
|
|
5240
|
-
dispatch({
|
|
5241
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5242
|
-
advancedFilterState,
|
|
5243
|
-
});
|
|
5244
|
-
}, checked: advancedFilterState.includeLearners, ariaLabel: "show logs from students" }),
|
|
5245
|
-
React__default["default"].createElement(CheckboxButton, { text: "Teaching Team Members", onChanged: (checked) => {
|
|
5246
|
-
advancedFilterState.includeTTMs = checked;
|
|
5189
|
+
} }))))));
|
|
5190
|
+
}
|
|
5191
|
+
else if (expandedFilterDrawer === FilterDrawer.Advanced) {
|
|
5192
|
+
// Create advanced filter ui
|
|
5193
|
+
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5194
|
+
React__default["default"].createElement(TabBox, { title: "User" },
|
|
5195
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5196
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User First Name"),
|
|
5197
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user first name", value: pendingAdvancedFilterState.userFirstName, placeholder: "e.g. Divardo", onChange: (e) => {
|
|
5198
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userFirstName: e.target.value });
|
|
5199
|
+
dispatch({
|
|
5200
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5201
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5202
|
+
});
|
|
5203
|
+
} })),
|
|
5204
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5205
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Last Name"),
|
|
5206
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user last name", value: pendingAdvancedFilterState.userLastName, placeholder: "e.g. Calicci", onChange: (e) => {
|
|
5207
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userLastName: e.target.value });
|
|
5208
|
+
dispatch({
|
|
5209
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5210
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5211
|
+
});
|
|
5212
|
+
} })),
|
|
5213
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5214
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Email"),
|
|
5215
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user email", value: pendingAdvancedFilterState.userEmail, placeholder: "e.g. calicci@fas.harvard.edu", onChange: (e) => {
|
|
5216
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userEmail: ((e.target.value)
|
|
5217
|
+
.trim()) });
|
|
5218
|
+
dispatch({
|
|
5219
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5220
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5221
|
+
});
|
|
5222
|
+
} })),
|
|
5223
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5224
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Canvas Id"),
|
|
5225
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for user canvas id", value: pendingAdvancedFilterState.userId, placeholder: "e.g. 104985", onChange: (e) => {
|
|
5226
|
+
const { value } = e.target;
|
|
5227
|
+
// Only update if value contains only numbers
|
|
5228
|
+
if (/^\d+$/.test(value) || value === '') {
|
|
5229
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userId: ((e.target.value)
|
|
5230
|
+
.trim()) });
|
|
5247
5231
|
dispatch({
|
|
5248
5232
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5249
|
-
advancedFilterState,
|
|
5233
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5250
5234
|
});
|
|
5251
|
-
}
|
|
5252
|
-
|
|
5253
|
-
|
|
5235
|
+
}
|
|
5236
|
+
} })),
|
|
5237
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Role" },
|
|
5238
|
+
React__default["default"].createElement(CheckboxButton, { text: "Students", onChanged: (checked) => {
|
|
5239
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeLearners: checked });
|
|
5240
|
+
dispatch({
|
|
5241
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5242
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5243
|
+
});
|
|
5244
|
+
}, checked: pendingAdvancedFilterState.includeLearners, ariaLabel: "show logs from students", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
5245
|
+
React__default["default"].createElement(CheckboxButton, { text: "Teaching Team Members", onChanged: (checked) => {
|
|
5246
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeTTMs: checked });
|
|
5247
|
+
dispatch({
|
|
5248
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5249
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5250
|
+
});
|
|
5251
|
+
}, checked: pendingAdvancedFilterState.includeTTMs, ariaLabel: "show logs from teaching team members", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
5252
|
+
React__default["default"].createElement(CheckboxButton, { text: "Admins", onChanged: (checked) => {
|
|
5253
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeAdmins: checked });
|
|
5254
|
+
dispatch({
|
|
5255
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5256
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5257
|
+
});
|
|
5258
|
+
}, checked: pendingAdvancedFilterState.includeAdmins, ariaLabel: "show logs from admins", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }))),
|
|
5259
|
+
React__default["default"].createElement(TabBox, { title: "Course" },
|
|
5260
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5261
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Name"),
|
|
5262
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course name", value: pendingAdvancedFilterState.courseName, placeholder: "e.g. GLC 200", onChange: (e) => {
|
|
5263
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { courseName: e.target.value });
|
|
5264
|
+
dispatch({
|
|
5265
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5266
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5267
|
+
});
|
|
5268
|
+
} })),
|
|
5269
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5270
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Canvas Id"),
|
|
5271
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for course canvas id", value: pendingAdvancedFilterState.courseId, placeholder: "e.g. 15948", onChange: (e) => {
|
|
5272
|
+
const { value } = e.target;
|
|
5273
|
+
// Only update if value contains only numbers
|
|
5274
|
+
if (/^\d+$/.test(value) || value === '') {
|
|
5275
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { courseId: ((e.target.value)
|
|
5276
|
+
.trim()) });
|
|
5254
5277
|
dispatch({
|
|
5255
5278
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5256
|
-
advancedFilterState,
|
|
5279
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5257
5280
|
});
|
|
5258
|
-
}
|
|
5259
|
-
|
|
5281
|
+
}
|
|
5282
|
+
} }))),
|
|
5283
|
+
React__default["default"].createElement(TabBox, { title: "Device" },
|
|
5284
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Device Type" },
|
|
5285
|
+
React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected: pendingAdvancedFilterState.isMobile === undefined, onSelected: () => {
|
|
5286
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: undefined });
|
|
5287
|
+
dispatch({
|
|
5288
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5289
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5290
|
+
});
|
|
5291
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5292
|
+
React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: pendingAdvancedFilterState.isMobile === true, onSelected: () => {
|
|
5293
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: true });
|
|
5294
|
+
dispatch({
|
|
5295
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5296
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5297
|
+
});
|
|
5298
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5299
|
+
React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: pendingAdvancedFilterState.isMobile === false, onSelected: () => {
|
|
5300
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: false });
|
|
5301
|
+
dispatch({
|
|
5302
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5303
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5304
|
+
});
|
|
5305
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }))),
|
|
5306
|
+
React__default["default"].createElement(TabBox, { title: "Source" },
|
|
5307
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Source Type" },
|
|
5308
|
+
React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected: pendingAdvancedFilterState.source === undefined, onSelected: () => {
|
|
5309
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: undefined });
|
|
5310
|
+
dispatch({
|
|
5311
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5312
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5313
|
+
});
|
|
5314
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5315
|
+
React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected: pendingAdvancedFilterState.source === LogSource$1.Client, onSelected: () => {
|
|
5316
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: LogSource$1.Client });
|
|
5317
|
+
dispatch({
|
|
5318
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5319
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5320
|
+
});
|
|
5321
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5322
|
+
React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected: pendingAdvancedFilterState.source === LogSource$1.Server, onSelected: () => {
|
|
5323
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: LogSource$1.Server });
|
|
5324
|
+
dispatch({
|
|
5325
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5326
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5327
|
+
});
|
|
5328
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
5329
|
+
pendingAdvancedFilterState.source !== LogSource$1.Client && (React__default["default"].createElement("div", { className: "mt-2" },
|
|
5260
5330
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5261
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "
|
|
5262
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for
|
|
5263
|
-
|
|
5331
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
5332
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route path", value: pendingAdvancedFilterState.routePath, placeholder: "e.g. /api/ttm/courses/12345", onChange: (e) => {
|
|
5333
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { routePath: ((e.target.value)
|
|
5334
|
+
.trim()) });
|
|
5264
5335
|
dispatch({
|
|
5265
5336
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5266
|
-
advancedFilterState,
|
|
5337
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5267
5338
|
});
|
|
5268
5339
|
} })),
|
|
5269
5340
|
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5270
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "
|
|
5271
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for
|
|
5272
|
-
const
|
|
5273
|
-
|
|
5274
|
-
if (/^\d+$/.test(value)) {
|
|
5275
|
-
advancedFilterState.courseId = ((e.target.value)
|
|
5276
|
-
.trim());
|
|
5277
|
-
}
|
|
5278
|
-
dispatch({
|
|
5279
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5280
|
-
advancedFilterState,
|
|
5281
|
-
});
|
|
5282
|
-
} }))),
|
|
5283
|
-
React__default["default"].createElement(TabBox, { title: "Device" },
|
|
5284
|
-
React__default["default"].createElement(ButtonInputGroup, { label: "Device Type" },
|
|
5285
|
-
React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected: advancedFilterState.isMobile === undefined, onSelected: () => {
|
|
5286
|
-
advancedFilterState.isMobile = undefined;
|
|
5287
|
-
dispatch({
|
|
5288
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5289
|
-
advancedFilterState,
|
|
5290
|
-
});
|
|
5291
|
-
} }),
|
|
5292
|
-
React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: advancedFilterState.isMobile === true, onSelected: () => {
|
|
5293
|
-
advancedFilterState.isMobile = true;
|
|
5294
|
-
dispatch({
|
|
5295
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5296
|
-
advancedFilterState,
|
|
5297
|
-
});
|
|
5298
|
-
} }),
|
|
5299
|
-
React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: advancedFilterState.isMobile === false, onSelected: () => {
|
|
5300
|
-
advancedFilterState.isMobile = false;
|
|
5301
|
-
dispatch({
|
|
5302
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5303
|
-
advancedFilterState,
|
|
5304
|
-
});
|
|
5305
|
-
}, noMarginOnRight: true }))),
|
|
5306
|
-
React__default["default"].createElement(TabBox, { title: "Source" },
|
|
5307
|
-
React__default["default"].createElement(ButtonInputGroup, { label: "Source Type" },
|
|
5308
|
-
React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected: advancedFilterState.source === undefined, onSelected: () => {
|
|
5309
|
-
advancedFilterState.source = undefined;
|
|
5310
|
-
dispatch({
|
|
5311
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5312
|
-
advancedFilterState,
|
|
5313
|
-
});
|
|
5314
|
-
} }),
|
|
5315
|
-
React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected: advancedFilterState.source === LogSource$1.Client, onSelected: () => {
|
|
5316
|
-
advancedFilterState.source = LogSource$1.Client;
|
|
5341
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
5342
|
+
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route template", value: pendingAdvancedFilterState.routeTemplate, placeholder: "e.g. /api/ttm/courses/:courseId", onChange: (e) => {
|
|
5343
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { routeTemplate: ((e.target.value)
|
|
5344
|
+
.trim()) });
|
|
5317
5345
|
dispatch({
|
|
5318
5346
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5319
|
-
advancedFilterState,
|
|
5347
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5320
5348
|
});
|
|
5321
|
-
} })
|
|
5322
|
-
React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected: advancedFilterState.source === LogSource$1.Server, onSelected: () => {
|
|
5323
|
-
advancedFilterState.source = LogSource$1.Server;
|
|
5324
|
-
dispatch({
|
|
5325
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5326
|
-
advancedFilterState,
|
|
5327
|
-
});
|
|
5328
|
-
}, noMarginOnRight: true })),
|
|
5329
|
-
advancedFilterState.source !== LogSource$1.Client && (React__default["default"].createElement("div", { className: "mt-2" },
|
|
5330
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5331
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
5332
|
-
React__default["default"].createElement("input", { type: "text", className: "form-control", "aria-label": "query for server route path", value: advancedFilterState.routePath, placeholder: "e.g. /api/ttm/courses/12345", onChange: (e) => {
|
|
5333
|
-
advancedFilterState.courseName = ((e.target.value)
|
|
5334
|
-
.trim());
|
|
5335
|
-
dispatch({
|
|
5336
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5337
|
-
advancedFilterState,
|
|
5338
|
-
});
|
|
5339
|
-
} })),
|
|
5340
|
-
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5341
|
-
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
5342
|
-
React__default["default"].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) => {
|
|
5343
|
-
advancedFilterState.courseName = ((e.target.value)
|
|
5344
|
-
.trim());
|
|
5345
|
-
dispatch({
|
|
5346
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5347
|
-
advancedFilterState,
|
|
5348
|
-
});
|
|
5349
|
-
} })))))));
|
|
5350
|
-
}
|
|
5349
|
+
} })))))));
|
|
5351
5350
|
}
|
|
5352
|
-
// Filters UI
|
|
5353
|
-
const filters = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5354
|
-
filterToggles,
|
|
5355
|
-
filterDrawer && (React__default["default"].createElement(Drawer, { customBackgroundColor: "#eee" }, filterDrawer))));
|
|
5356
|
-
// Actually filter the logs
|
|
5357
|
-
// > Perform filters
|
|
5358
|
-
const logs = [];
|
|
5359
|
-
Object.keys(logMap).forEach((year) => {
|
|
5360
|
-
Object.keys(logMap[year]).forEach((month) => {
|
|
5361
|
-
logMap[year][month].forEach((log) => {
|
|
5362
|
-
/* ----------- Date Filter ---------- */
|
|
5363
|
-
var _a;
|
|
5364
|
-
// Before start date
|
|
5365
|
-
if (
|
|
5366
|
-
// Previous year
|
|
5367
|
-
log.year < dateFilterState.startDate.year
|
|
5368
|
-
// Same year, earlier month
|
|
5369
|
-
|| ((log.year === dateFilterState.startDate.year)
|
|
5370
|
-
&& (log.month < dateFilterState.startDate.month))
|
|
5371
|
-
// Same year, same month, earlier day
|
|
5372
|
-
|| ((log.year === dateFilterState.startDate.year)
|
|
5373
|
-
&& (log.month === dateFilterState.startDate.month)
|
|
5374
|
-
&& (log.day < dateFilterState.startDate.day))) {
|
|
5375
|
-
return;
|
|
5376
|
-
}
|
|
5377
|
-
// After end date
|
|
5378
|
-
if (
|
|
5379
|
-
// Later year
|
|
5380
|
-
log.year > dateFilterState.endDate.year
|
|
5381
|
-
// Same year, later month
|
|
5382
|
-
|| ((log.year === dateFilterState.endDate.year)
|
|
5383
|
-
&& (log.month > dateFilterState.endDate.month))
|
|
5384
|
-
// Same year, same month, later day
|
|
5385
|
-
|| ((log.year === dateFilterState.endDate.year)
|
|
5386
|
-
&& (log.month === dateFilterState.endDate.month)
|
|
5387
|
-
&& (log.day > dateFilterState.endDate.day))) {
|
|
5388
|
-
return;
|
|
5389
|
-
}
|
|
5390
|
-
/* --------- Context Filter --------- */
|
|
5391
|
-
// Context doesn't match
|
|
5392
|
-
if (
|
|
5393
|
-
// Whole context is deselected
|
|
5394
|
-
contextFilterState[log.context] === false
|
|
5395
|
-
// None of the subcontexts are selected
|
|
5396
|
-
|| (
|
|
5397
|
-
// Has subcontexts
|
|
5398
|
-
typeof contextFilterState[log.context] !== 'boolean'
|
|
5399
|
-
// None of the subcontexts are selected
|
|
5400
|
-
&& Object.values((_a = contextFilterState[log.context]) !== null && _a !== void 0 ? _a : {})
|
|
5401
|
-
.every((isSelected) => {
|
|
5402
|
-
return !isSelected;
|
|
5403
|
-
}))) {
|
|
5404
|
-
return;
|
|
5405
|
-
}
|
|
5406
|
-
// Subcontext doesn't match
|
|
5407
|
-
if (
|
|
5408
|
-
// Log context is not "uncategorized" (no point in further filters)
|
|
5409
|
-
log.context !== LogBuiltInMetadata.Context.Uncategorized
|
|
5410
|
-
// Log has a subcontext
|
|
5411
|
-
&& log.subcontext
|
|
5412
|
-
// Context has subcontexts
|
|
5413
|
-
&& (contextFilterState[log.context]
|
|
5414
|
-
&& contextFilterState[log.context] !== false
|
|
5415
|
-
&& contextFilterState[log.context] !== true)
|
|
5416
|
-
// Subcontext is not selected
|
|
5417
|
-
&& !contextFilterState[log.context][log.subcontext]) {
|
|
5418
|
-
return;
|
|
5419
|
-
}
|
|
5420
|
-
/* -------------- Tags -------------- */
|
|
5421
|
-
// No tags match
|
|
5422
|
-
if (
|
|
5423
|
-
// At least one tag is required
|
|
5424
|
-
Object.values(tagFilterState)
|
|
5425
|
-
.filter((isSelected) => {
|
|
5426
|
-
return isSelected;
|
|
5427
|
-
})
|
|
5428
|
-
.length > 0
|
|
5429
|
-
// No tags match
|
|
5430
|
-
&& log.tags.every((tag) => {
|
|
5431
|
-
return !tagFilterState[tag];
|
|
5432
|
-
})) {
|
|
5433
|
-
return;
|
|
5434
|
-
}
|
|
5435
|
-
/* ------- Actions and Errors ------- */
|
|
5436
|
-
// Log type doesn't match
|
|
5437
|
-
if (
|
|
5438
|
-
// Filter won't allow all types
|
|
5439
|
-
actionErrorFilterState.type !== undefined
|
|
5440
|
-
// Log type doesn't match
|
|
5441
|
-
&& actionErrorFilterState.type !== log.type) {
|
|
5442
|
-
return;
|
|
5443
|
-
}
|
|
5444
|
-
// Filter errors
|
|
5445
|
-
if (log.type === LogType$1.Error) {
|
|
5446
|
-
// Message doesn't match
|
|
5447
|
-
if (
|
|
5448
|
-
// Message exists
|
|
5449
|
-
log.errorMessage
|
|
5450
|
-
// Message filter exists
|
|
5451
|
-
&& actionErrorFilterState.errorMessage.trim().length > 0
|
|
5452
|
-
// Message doesn't match
|
|
5453
|
-
&& log.errorMessage.toLowerCase().includes(actionErrorFilterState.errorMessage.trim().toLowerCase())) {
|
|
5454
|
-
return;
|
|
5455
|
-
}
|
|
5456
|
-
// Code doesn't match
|
|
5457
|
-
if (
|
|
5458
|
-
// Code exists
|
|
5459
|
-
log.errorCode
|
|
5460
|
-
// Code filter exists
|
|
5461
|
-
&& actionErrorFilterState.errorCode.trim().length > 0
|
|
5462
|
-
// Code doesn't match
|
|
5463
|
-
&& log.errorCode.toUpperCase().includes(actionErrorFilterState.errorCode.trim().toUpperCase())) {
|
|
5464
|
-
return;
|
|
5465
|
-
}
|
|
5466
|
-
}
|
|
5467
|
-
// Filter actions
|
|
5468
|
-
if (log.type === LogType$1.Action) {
|
|
5469
|
-
// Target isn't selected
|
|
5470
|
-
if (
|
|
5471
|
-
// Target exists
|
|
5472
|
-
log.target
|
|
5473
|
-
// Target isn't selected
|
|
5474
|
-
&& !actionErrorFilterState.target[log.target]) {
|
|
5475
|
-
return;
|
|
5476
|
-
}
|
|
5477
|
-
// Action
|
|
5478
|
-
if (
|
|
5479
|
-
// Action exists
|
|
5480
|
-
log.action
|
|
5481
|
-
// Action isn't selected
|
|
5482
|
-
&& !actionErrorFilterState.action[log.action]) {
|
|
5483
|
-
return;
|
|
5484
|
-
}
|
|
5485
|
-
}
|
|
5486
|
-
/* --------- Advanced Filter -------- */
|
|
5487
|
-
// First name doesn't match
|
|
5488
|
-
if (
|
|
5489
|
-
// First name exists
|
|
5490
|
-
log.userFirstName
|
|
5491
|
-
// First name query doesn't match
|
|
5492
|
-
&& !log.userFirstName.toLowerCase().includes(advancedFilterState.userFirstName.toLowerCase().trim())) {
|
|
5493
|
-
return;
|
|
5494
|
-
}
|
|
5495
|
-
// Last name doesn't match
|
|
5496
|
-
if (
|
|
5497
|
-
// Last name exists
|
|
5498
|
-
log.userLastName
|
|
5499
|
-
// Last name query doesn't match
|
|
5500
|
-
&& !log.userLastName.toLowerCase().includes(advancedFilterState.userLastName.toLowerCase().trim())) {
|
|
5501
|
-
return;
|
|
5502
|
-
}
|
|
5503
|
-
// Email doesn't match
|
|
5504
|
-
if (
|
|
5505
|
-
// Email exists
|
|
5506
|
-
log.userEmail
|
|
5507
|
-
// Email query doesn't match
|
|
5508
|
-
&& !log.userEmail.toLowerCase().includes(advancedFilterState.userEmail.toLowerCase().trim())) {
|
|
5509
|
-
return;
|
|
5510
|
-
}
|
|
5511
|
-
// User id doesn't match
|
|
5512
|
-
if (
|
|
5513
|
-
// User id exists
|
|
5514
|
-
log.userId
|
|
5515
|
-
// User id doesn't match
|
|
5516
|
-
&& !String(log.userId).includes(advancedFilterState.userId.trim())) {
|
|
5517
|
-
return;
|
|
5518
|
-
}
|
|
5519
|
-
// Learner not allowed
|
|
5520
|
-
if (
|
|
5521
|
-
// User is a learner
|
|
5522
|
-
log.isLearner
|
|
5523
|
-
// Learners aren't included
|
|
5524
|
-
&& !advancedFilterState.includeLearners) {
|
|
5525
|
-
return;
|
|
5526
|
-
}
|
|
5527
|
-
// TTM not allowed
|
|
5528
|
-
if (
|
|
5529
|
-
// User is a ttm
|
|
5530
|
-
log.isTTM
|
|
5531
|
-
// TTMs aren't included
|
|
5532
|
-
&& !advancedFilterState.includeTTMs) {
|
|
5533
|
-
return;
|
|
5534
|
-
}
|
|
5535
|
-
// Admin not allowed
|
|
5536
|
-
if (
|
|
5537
|
-
// User is an admin
|
|
5538
|
-
log.isAdmin
|
|
5539
|
-
// Admins aren't included
|
|
5540
|
-
&& !advancedFilterState.includeAdmins) {
|
|
5541
|
-
return;
|
|
5542
|
-
}
|
|
5543
|
-
// Course Id doesn't match
|
|
5544
|
-
if (
|
|
5545
|
-
// Course Id exists
|
|
5546
|
-
log.courseId
|
|
5547
|
-
// Course Id doesn't match
|
|
5548
|
-
&& !String(log.courseId).includes(advancedFilterState.courseId.trim())) {
|
|
5549
|
-
return;
|
|
5550
|
-
}
|
|
5551
|
-
// Course name doesn't match
|
|
5552
|
-
if (
|
|
5553
|
-
// Course name exists
|
|
5554
|
-
log.courseName
|
|
5555
|
-
// Course name doesn't match
|
|
5556
|
-
&& !String(log.courseName).includes(advancedFilterState.courseName.trim())) {
|
|
5557
|
-
return;
|
|
5558
|
-
}
|
|
5559
|
-
// Mobile filter doesn't match
|
|
5560
|
-
if (
|
|
5561
|
-
// Mobile filter exists
|
|
5562
|
-
advancedFilterState.isMobile !== undefined
|
|
5563
|
-
// Device info exists
|
|
5564
|
-
&& log.device
|
|
5565
|
-
// Mobile filter doesn't match
|
|
5566
|
-
&& (advancedFilterState.isMobile !== log.device.isMobile)) {
|
|
5567
|
-
return;
|
|
5568
|
-
}
|
|
5569
|
-
// Log source doesn't match
|
|
5570
|
-
if (
|
|
5571
|
-
// Source filter exists
|
|
5572
|
-
advancedFilterState.source !== undefined
|
|
5573
|
-
// Source info exists
|
|
5574
|
-
&& log.source
|
|
5575
|
-
// Source filter doesn't match
|
|
5576
|
-
&& (advancedFilterState.source !== log.source)) {
|
|
5577
|
-
return;
|
|
5578
|
-
}
|
|
5579
|
-
// Route path doesn't match (Only for server source)
|
|
5580
|
-
if (
|
|
5581
|
-
// Source is server
|
|
5582
|
-
(log.source === LogSource$1.Server)
|
|
5583
|
-
// Route path is being filtered
|
|
5584
|
-
&& (advancedFilterState.routePath.trim().length)
|
|
5585
|
-
// Route path doesn't match
|
|
5586
|
-
&& !(log.routePath.includes(advancedFilterState.routePath.trim()))) {
|
|
5587
|
-
return;
|
|
5588
|
-
}
|
|
5589
|
-
// Route template doesn't match (Only for server source)
|
|
5590
|
-
if (
|
|
5591
|
-
// Source is server
|
|
5592
|
-
(log.source === LogSource$1.Server)
|
|
5593
|
-
// Route template is being filtered
|
|
5594
|
-
&& (advancedFilterState.routeTemplate.trim().length)
|
|
5595
|
-
// Route template doesn't match
|
|
5596
|
-
&& !(log.routeTemplate.includes(advancedFilterState.routeTemplate.trim()))) {
|
|
5597
|
-
return;
|
|
5598
|
-
}
|
|
5599
|
-
/* -------------- Done -------------- */
|
|
5600
|
-
// Made it past all filters. Add to the list
|
|
5601
|
-
logs.push(log);
|
|
5602
|
-
});
|
|
5603
|
-
});
|
|
5604
|
-
});
|
|
5605
|
-
/*----------------------------------------*/
|
|
5606
|
-
/* ---------------- Data ---------------- */
|
|
5607
|
-
/*----------------------------------------*/
|
|
5608
|
-
// Nothing to show notice
|
|
5609
|
-
const noLogsNotice = (logs.length === 0
|
|
5610
|
-
? (React__default["default"].createElement("div", { className: "alert alert-warning text-center mt-2" },
|
|
5611
|
-
React__default["default"].createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
5612
|
-
React__default["default"].createElement("div", null, "Either your filters are too strict or no matching logs have been created yet.")))
|
|
5613
|
-
: undefined);
|
|
5614
|
-
// Create intelliTable
|
|
5615
|
-
const dataTable = (React__default["default"].createElement(IntelliTable, { title: "Matching Logs:", csvName: `Logs from ${getHumanReadableDate()}`, id: "logs", data: logs, columns: columns }));
|
|
5616
|
-
// Main body
|
|
5617
|
-
body = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5618
|
-
filters,
|
|
5619
|
-
React__default["default"].createElement("div", { className: "mt-2" },
|
|
5620
|
-
dataTable,
|
|
5621
|
-
noLogsNotice)));
|
|
5622
5351
|
}
|
|
5352
|
+
// Filters UI
|
|
5353
|
+
const filters = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5354
|
+
filterToggles,
|
|
5355
|
+
filterDrawer && (React__default["default"].createElement(Drawer, { customBackgroundColor: "#eee" }, filterDrawer))));
|
|
5356
|
+
// Body that will be filled with the contents of the panel
|
|
5357
|
+
const body = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5358
|
+
loading && (React__default["default"].createElement("div", { className: "text-center p-5" },
|
|
5359
|
+
React__default["default"].createElement(LoadingSpinner, null))),
|
|
5360
|
+
!loading && (React__default["default"].createElement("div", null, filters)),
|
|
5361
|
+
!loading && logs.length === 0 && (React__default["default"].createElement("div", { className: "alert alert-warning text-center mt-2" },
|
|
5362
|
+
React__default["default"].createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
5363
|
+
React__default["default"].createElement("div", null, "Either your filters are too strict or no matching logs have been created yet."))),
|
|
5364
|
+
React__default["default"].createElement("div", { className: loading || logs.length === 0 ? 'd-none' : undefined },
|
|
5365
|
+
React__default["default"].createElement(IntelliTable, { title: "Matching Logs", csvName: `Logs from ${getHumanReadableDate()}`, id: "logs", data: logs, columns: columns })),
|
|
5366
|
+
!loading && logs.length > 0 && paginationControls));
|
|
5623
5367
|
/* ---------- Wrap in Modal --------- */
|
|
5624
5368
|
return (React__default["default"].createElement("div", { className: "LogReviewer-outer-container" },
|
|
5625
5369
|
React__default["default"].createElement("style", null, style$2),
|
|
5626
5370
|
React__default["default"].createElement("div", { className: "LogReviewer-inner-container" },
|
|
5627
5371
|
React__default["default"].createElement("div", { className: "LogReviewer-header" },
|
|
5628
5372
|
React__default["default"].createElement("div", { className: "LogReviewer-header-title" },
|
|
5629
|
-
React__default["default"].createElement("h3", { className: "text-center
|
|
5373
|
+
React__default["default"].createElement("h3", { className: "text-center" }, "Log Review Dashboard")),
|
|
5630
5374
|
React__default["default"].createElement("div", { style: { width: 0 } },
|
|
5631
5375
|
React__default["default"].createElement("button", { type: "button", className: "LogReviewer-header-close-button btn btn-dark btn-lg pe-0", "aria-label": "close log reviewer panel", onClick: onClose },
|
|
5632
5376
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes })))),
|
|
@@ -15302,6 +15046,12 @@ const HOUR_IN_MS = 3600000;
|
|
|
15302
15046
|
*/
|
|
15303
15047
|
const DAY_IN_MS = 86400000;
|
|
15304
15048
|
|
|
15049
|
+
/**
|
|
15050
|
+
* Path of the route for storing client-side logs
|
|
15051
|
+
* @author Gabe Abrams
|
|
15052
|
+
*/
|
|
15053
|
+
const LOG_REVIEW_ROUTE_PATH_PREFIX = `/admin${ROUTE_PATH_PREFIX}/logs`;
|
|
15054
|
+
|
|
15305
15055
|
/**
|
|
15306
15056
|
* Route for checking the status of the current user's
|
|
15307
15057
|
* access to log review
|
|
@@ -15476,6 +15226,24 @@ const padDecimalZeros = (num, numDigits) => {
|
|
|
15476
15226
|
return out;
|
|
15477
15227
|
};
|
|
15478
15228
|
|
|
15229
|
+
/**
|
|
15230
|
+
* Pad a number with zeros on the left (e.g. 5 becomes 05 with 2 digit padding)
|
|
15231
|
+
* @author Gabe Abrams
|
|
15232
|
+
* @param num the number to pad
|
|
15233
|
+
* @param numDigits the minimum number of digits before the decimal
|
|
15234
|
+
* @returns padded number
|
|
15235
|
+
*/
|
|
15236
|
+
const padZerosLeft = (num, numDigits) => {
|
|
15237
|
+
// Convert to string
|
|
15238
|
+
let out = String(num);
|
|
15239
|
+
// Add zeros
|
|
15240
|
+
while (out.split('.')[0].length < numDigits) {
|
|
15241
|
+
out = `0${out}`;
|
|
15242
|
+
}
|
|
15243
|
+
// Return
|
|
15244
|
+
return out;
|
|
15245
|
+
};
|
|
15246
|
+
|
|
15479
15247
|
/**
|
|
15480
15248
|
* Stub a server endpoint response
|
|
15481
15249
|
* @author Gabe Abrams
|
|
@@ -16365,6 +16133,7 @@ exports.ErrorWithCode = ErrorWithCode;
|
|
|
16365
16133
|
exports.HOUR_IN_MS = HOUR_IN_MS;
|
|
16366
16134
|
exports.IntelliTable = IntelliTable;
|
|
16367
16135
|
exports.ItemPicker = ItemPicker;
|
|
16136
|
+
exports.LOG_REVIEW_GET_LOGS_ROUTE = LOG_REVIEW_GET_LOGS_ROUTE;
|
|
16368
16137
|
exports.LOG_REVIEW_ROUTE_PATH_PREFIX = LOG_REVIEW_ROUTE_PATH_PREFIX;
|
|
16369
16138
|
exports.LOG_REVIEW_STATUS_ROUTE = LOG_REVIEW_STATUS_ROUTE;
|
|
16370
16139
|
exports.LOG_ROUTE_PATH = LOG_ROUTE_PATH;
|
|
@@ -16388,7 +16157,6 @@ exports.PopSuccessMark = PopSuccessMark;
|
|
|
16388
16157
|
exports.RadioButton = RadioButton;
|
|
16389
16158
|
exports.ReactKitErrorCode = ReactKitErrorCode$1;
|
|
16390
16159
|
exports.SimpleDateChooser = SimpleDateChooser;
|
|
16391
|
-
exports.SimpleTimeChooser = SimpleTimeChooser;
|
|
16392
16160
|
exports.TabBox = TabBox;
|
|
16393
16161
|
exports.ToggleSwitch = ToggleSwitch;
|
|
16394
16162
|
exports.Tooltip = Tooltip;
|
|
@@ -16400,6 +16168,7 @@ exports.avg = avg;
|
|
|
16400
16168
|
exports.canReviewLogs = canReviewLogs;
|
|
16401
16169
|
exports.capitalize = capitalize;
|
|
16402
16170
|
exports.ceilToNumDecimals = ceilToNumDecimals;
|
|
16171
|
+
exports.cloneDeep = cloneDeep;
|
|
16403
16172
|
exports.combineClassNames = combineClassNames;
|
|
16404
16173
|
exports.compareArraysByProp = compareArraysByProp;
|
|
16405
16174
|
exports.confirm = confirm;
|