dce-reactkit 4.0.1 → 4.1.0
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 +662 -771
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/Pagination.d.ts +13 -0
- 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 -1
- package/dist/cjs/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +17 -0
- package/dist/cjs/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +21 -0
- package/dist/cjs/types/types/LogReviewerFilterState/ContextFilterState.d.ts +10 -0
- package/dist/cjs/types/types/LogReviewerFilterState/DateFilterState.d.ts +17 -0
- package/dist/cjs/types/types/LogReviewerFilterState/TagFilterState.d.ts +8 -0
- package/dist/cjs/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/esm/index.js +661 -773
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/Pagination.d.ts +13 -0
- 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 -1
- package/dist/esm/types/types/LogReviewerFilterState/ActionErrorFilterState.d.ts +17 -0
- package/dist/esm/types/types/LogReviewerFilterState/AdvancedFilterState.d.ts +21 -0
- package/dist/esm/types/types/LogReviewerFilterState/ContextFilterState.d.ts +10 -0
- package/dist/esm/types/types/LogReviewerFilterState/DateFilterState.d.ts +17 -0
- package/dist/esm/types/types/LogReviewerFilterState/TagFilterState.d.ts +8 -0
- package/dist/esm/types/types/LogReviewerFilterState/index.d.ts +17 -0
- package/dist/index.d.ts +98 -1
- package/package.json +2 -1
- package/src/components/LogReviewer.tsx +1133 -1307
- package/src/components/Pagination.tsx +172 -0
- package/src/constants/LOG_REVIEW_GET_LOGS_ROUTE.ts +9 -0
- package/src/helpers/cloneDeep.ts +11 -0
- package/src/index.ts +6 -0
- package/src/types/LogReviewerFilterState/ActionErrorFilterState.ts +24 -0
- package/src/types/LogReviewerFilterState/AdvancedFilterState.ts +36 -0
- package/src/types/LogReviewerFilterState/ContextFilterState.ts +16 -0
- package/src/types/LogReviewerFilterState/DateFilterState.ts +26 -0
- package/src/types/LogReviewerFilterState/TagFilterState.ts +9 -0
- package/src/types/LogReviewerFilterState/index.ts +24 -0
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.
|
|
@@ -3650,10 +3652,10 @@ const getHumanReadableDate = (dateOrTimestamp) => {
|
|
|
3650
3652
|
};
|
|
3651
3653
|
|
|
3652
3654
|
/**
|
|
3653
|
-
* Path of the route for
|
|
3655
|
+
* Path of the route for getting logs for log review
|
|
3654
3656
|
* @author Gabe Abrams
|
|
3655
3657
|
*/
|
|
3656
|
-
const
|
|
3658
|
+
const LOG_REVIEW_GET_LOGS_ROUTE = `/admin${ROUTE_PATH_PREFIX}/logs`;
|
|
3657
3659
|
|
|
3658
3660
|
/**
|
|
3659
3661
|
* Source of a log event
|
|
@@ -4258,6 +4260,71 @@ const IntelliTable = (props) => {
|
|
|
4258
4260
|
} }, table)));
|
|
4259
4261
|
};
|
|
4260
4262
|
|
|
4263
|
+
// Import React
|
|
4264
|
+
/*------------------------------------------------------------------------*/
|
|
4265
|
+
/* ------------------------------ Component ----------------------------- */
|
|
4266
|
+
/*------------------------------------------------------------------------*/
|
|
4267
|
+
const Pagination = (props) => {
|
|
4268
|
+
/*------------------------------------------------------------------------*/
|
|
4269
|
+
/* -------------------------------- Setup ------------------------------- */
|
|
4270
|
+
/*------------------------------------------------------------------------*/
|
|
4271
|
+
/* -------------- Props ------------- */
|
|
4272
|
+
// Destructure props
|
|
4273
|
+
const { currentPage, numPages, loading = false, onPageChanged, } = props;
|
|
4274
|
+
/*------------------------------------------------------------------------*/
|
|
4275
|
+
/* ------------------------------- Render ------------------------------- */
|
|
4276
|
+
/*------------------------------------------------------------------------*/
|
|
4277
|
+
// Compute pages to display
|
|
4278
|
+
const pages = [];
|
|
4279
|
+
const delta = 2; // how many pages to show on either side of current
|
|
4280
|
+
let start = Math.max(1, currentPage - delta);
|
|
4281
|
+
let end = Math.min(numPages, currentPage + delta);
|
|
4282
|
+
// If we are too close to the beginning or end, shift the window.
|
|
4283
|
+
if (currentPage - delta < 1) {
|
|
4284
|
+
end = Math.min(numPages, end + (1 - (currentPage - delta)));
|
|
4285
|
+
}
|
|
4286
|
+
if (currentPage + delta > numPages) {
|
|
4287
|
+
start = Math.max(1, start - ((currentPage + delta) - numPages));
|
|
4288
|
+
}
|
|
4289
|
+
for (let i = start; i <= end; i++) {
|
|
4290
|
+
pages.push(i);
|
|
4291
|
+
}
|
|
4292
|
+
// Render
|
|
4293
|
+
return (React__default["default"].createElement("nav", { "aria-label": "Page navigation for logs", className: "mt-3" },
|
|
4294
|
+
React__default["default"].createElement("ul", { className: "pagination justify-content-center" },
|
|
4295
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage <= 1 || loading) ? 'disabled' : ''}` },
|
|
4296
|
+
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" },
|
|
4297
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowLeft }),
|
|
4298
|
+
' ',
|
|
4299
|
+
"Prev")),
|
|
4300
|
+
(currentPage > 3 && pages[0] !== 1) && (React__default["default"].createElement("li", { className: "page-item" },
|
|
4301
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(1); }, disabled: loading, "aria-label": "Go to page 1" }, "1"))),
|
|
4302
|
+
currentPage > 4 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
4303
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
4304
|
+
pages.map((pageNum) => {
|
|
4305
|
+
return (React__default["default"].createElement("li", { key: pageNum, className: `page-item ${pageNum === currentPage ? 'active' : ''}` },
|
|
4306
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(pageNum); }, disabled: loading, "aria-label": `Go to page ${pageNum}` }, pageNum)));
|
|
4307
|
+
}),
|
|
4308
|
+
currentPage < numPages - 3 && (React__default["default"].createElement("li", { className: "page-item disabled" },
|
|
4309
|
+
React__default["default"].createElement("span", { className: "page-link" }, "..."))),
|
|
4310
|
+
(currentPage < numPages - 2
|
|
4311
|
+
&& pages[pages.length - 1] !== numPages) && (React__default["default"].createElement("li", { className: "page-item" },
|
|
4312
|
+
React__default["default"].createElement("button", { type: "button", className: "page-link", onClick: () => { return onPageChanged(numPages); }, disabled: loading, "aria-label": "Go to last page" }, numPages))),
|
|
4313
|
+
React__default["default"].createElement("li", { className: `page-item ${(currentPage >= numPages || loading) ? 'disabled' : ''}` },
|
|
4314
|
+
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" },
|
|
4315
|
+
"Next",
|
|
4316
|
+
' ',
|
|
4317
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faArrowRight }))))));
|
|
4318
|
+
};
|
|
4319
|
+
|
|
4320
|
+
/**
|
|
4321
|
+
* Deeply clones an object
|
|
4322
|
+
* @author Yuen Ler Chow
|
|
4323
|
+
* @param obj the object to clone
|
|
4324
|
+
* @returns a deep clone of the object
|
|
4325
|
+
*/
|
|
4326
|
+
const cloneDeep = clone__default["default"];
|
|
4327
|
+
|
|
4261
4328
|
/**
|
|
4262
4329
|
* Log reviewer panel that allows users (must be approved admins) to
|
|
4263
4330
|
* review logs written by dce-reactkit
|
|
@@ -4613,7 +4680,7 @@ var ActionType$6;
|
|
|
4613
4680
|
(function (ActionType) {
|
|
4614
4681
|
// Show the loading bar
|
|
4615
4682
|
ActionType["StartLoading"] = "start-loading";
|
|
4616
|
-
// Finish loading
|
|
4683
|
+
// Finish loading logs
|
|
4617
4684
|
ActionType["FinishLoading"] = "finish-loading";
|
|
4618
4685
|
// Reset filters to initial values
|
|
4619
4686
|
ActionType["ResetFilters"] = "reset-filters";
|
|
@@ -4631,6 +4698,14 @@ var ActionType$6;
|
|
|
4631
4698
|
ActionType["UpdateActionErrorFilterState"] = "update-action-error-filter-state";
|
|
4632
4699
|
// Update the advanced filter state
|
|
4633
4700
|
ActionType["UpdateAdvancedFilterState"] = "update-advanced-filter-state";
|
|
4701
|
+
// Set has another page
|
|
4702
|
+
ActionType["SetHasAnotherPage"] = "set-has-another-page";
|
|
4703
|
+
// Set the number of pages
|
|
4704
|
+
ActionType["SetNumPages"] = "set-num-pages";
|
|
4705
|
+
// Set page number
|
|
4706
|
+
ActionType["SetPageNumber"] = "set-page-number";
|
|
4707
|
+
// Reset user made filter change indicator
|
|
4708
|
+
ActionType["ResetUserMadeFilterChange"] = "reset-user-made-filter-change";
|
|
4634
4709
|
})(ActionType$6 || (ActionType$6 = {}));
|
|
4635
4710
|
/**
|
|
4636
4711
|
* Reducer that executes actions
|
|
@@ -4644,7 +4719,7 @@ const reducer$7 = (state, action) => {
|
|
|
4644
4719
|
return Object.assign(Object.assign({}, state), { loading: true });
|
|
4645
4720
|
}
|
|
4646
4721
|
case ActionType$6.FinishLoading: {
|
|
4647
|
-
return Object.assign(Object.assign({}, state), { loading: false,
|
|
4722
|
+
return Object.assign(Object.assign({}, state), { loading: false, logs: action.logs });
|
|
4648
4723
|
}
|
|
4649
4724
|
case ActionType$6.ToggleFilterDrawer: {
|
|
4650
4725
|
return Object.assign(Object.assign({}, state), { expandedFilterDrawer: (state.expandedFilterDrawer === action.filterDrawer
|
|
@@ -4655,22 +4730,34 @@ const reducer$7 = (state, action) => {
|
|
|
4655
4730
|
return Object.assign(Object.assign({}, state), { expandedFilterDrawer: undefined });
|
|
4656
4731
|
}
|
|
4657
4732
|
case ActionType$6.ResetFilters: {
|
|
4658
|
-
return Object.assign(Object.assign({}, state), {
|
|
4733
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.initDateFilterState, pendingContextFilterState: action.initContextFilterState, pendingTagFilterState: action.initTagFilterState, pendingActionErrorFilterState: action.initActionErrorFilterState, pendingAdvancedFilterState: action.initAdvancedFilterState, pageNumber: 1 });
|
|
4659
4734
|
}
|
|
4660
4735
|
case ActionType$6.UpdateDateFilterState: {
|
|
4661
|
-
return Object.assign(Object.assign({}, state), {
|
|
4736
|
+
return Object.assign(Object.assign({}, state), { pendingDateFilterState: action.dateFilterState, userMadeFilterChange: true });
|
|
4662
4737
|
}
|
|
4663
4738
|
case ActionType$6.UpdateContextFilterState: {
|
|
4664
|
-
return Object.assign(Object.assign({}, state), {
|
|
4739
|
+
return Object.assign(Object.assign({}, state), { pendingContextFilterState: action.contextFilterState, userMadeFilterChange: true });
|
|
4665
4740
|
}
|
|
4666
4741
|
case ActionType$6.UpdateTagFilterState: {
|
|
4667
|
-
return Object.assign(Object.assign({}, state), {
|
|
4742
|
+
return Object.assign(Object.assign({}, state), { pendingTagFilterState: action.tagFilterState, userMadeFilterChange: true });
|
|
4668
4743
|
}
|
|
4669
4744
|
case ActionType$6.UpdateActionErrorFilterState: {
|
|
4670
|
-
return Object.assign(Object.assign({}, state), {
|
|
4745
|
+
return Object.assign(Object.assign({}, state), { pendingActionErrorFilterState: action.actionErrorFilterState, userMadeFilterChange: true });
|
|
4671
4746
|
}
|
|
4672
4747
|
case ActionType$6.UpdateAdvancedFilterState: {
|
|
4673
|
-
return Object.assign(Object.assign({}, state), {
|
|
4748
|
+
return Object.assign(Object.assign({}, state), { pendingAdvancedFilterState: action.advancedFilterState, userMadeFilterChange: true });
|
|
4749
|
+
}
|
|
4750
|
+
case ActionType$6.SetHasAnotherPage: {
|
|
4751
|
+
return Object.assign(Object.assign({}, state), { hasAnotherPage: action.hasAnotherPage });
|
|
4752
|
+
}
|
|
4753
|
+
case ActionType$6.SetNumPages: {
|
|
4754
|
+
return Object.assign(Object.assign({}, state), { numPages: action.numPages });
|
|
4755
|
+
}
|
|
4756
|
+
case ActionType$6.SetPageNumber: {
|
|
4757
|
+
return Object.assign(Object.assign({}, state), { pageNumber: action.pageNumber });
|
|
4758
|
+
}
|
|
4759
|
+
case ActionType$6.ResetUserMadeFilterChange: {
|
|
4760
|
+
return Object.assign(Object.assign({}, state), { userMadeFilterChange: false });
|
|
4674
4761
|
}
|
|
4675
4762
|
default: {
|
|
4676
4763
|
return state;
|
|
@@ -4741,7 +4828,7 @@ const LogReviewer = (props) => {
|
|
|
4741
4828
|
else {
|
|
4742
4829
|
// Case: subcontexts exist
|
|
4743
4830
|
initContextFilterState[context] = {};
|
|
4744
|
-
Object.
|
|
4831
|
+
Object.keys(contextMap[context]).forEach((subcontext) => {
|
|
4745
4832
|
// Skip self ("_")
|
|
4746
4833
|
if (subcontext === '_') {
|
|
4747
4834
|
return;
|
|
@@ -4789,125 +4876,105 @@ const LogReviewer = (props) => {
|
|
|
4789
4876
|
// Initial state
|
|
4790
4877
|
const initialState = {
|
|
4791
4878
|
loading: true,
|
|
4792
|
-
|
|
4879
|
+
logs: [],
|
|
4793
4880
|
expandedFilterDrawer: undefined,
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4881
|
+
pendingDateFilterState: initDateFilterState,
|
|
4882
|
+
pendingContextFilterState: initContextFilterState,
|
|
4883
|
+
pendingTagFilterState: initTagFilterState,
|
|
4884
|
+
pendingActionErrorFilterState: initActionErrorFilterState,
|
|
4885
|
+
pendingAdvancedFilterState: initAdvancedFilterState,
|
|
4886
|
+
pageNumber: 1,
|
|
4887
|
+
hasAnotherPage: false,
|
|
4888
|
+
numPages: 1,
|
|
4889
|
+
userMadeFilterChange: false,
|
|
4799
4890
|
};
|
|
4800
4891
|
// Initialize state
|
|
4801
4892
|
const [state, dispatch] = React.useReducer(reducer$7, initialState);
|
|
4802
4893
|
// Destructure common state
|
|
4803
|
-
const { loading,
|
|
4894
|
+
const { loading, logs, expandedFilterDrawer, pendingDateFilterState, pendingContextFilterState, pendingTagFilterState, pendingActionErrorFilterState, pendingAdvancedFilterState, pageNumber, numPages, userMadeFilterChange, } = state;
|
|
4895
|
+
/* -------------- Refs -------------- */
|
|
4896
|
+
// Initialize refs
|
|
4897
|
+
const activeFiltersRef = React.useRef({
|
|
4898
|
+
dateFilterState: JSON.parse(JSON.stringify(pendingDateFilterState)),
|
|
4899
|
+
contextFilterState: JSON.parse(JSON.stringify(pendingContextFilterState)),
|
|
4900
|
+
tagFilterState: JSON.parse(JSON.stringify(pendingTagFilterState)),
|
|
4901
|
+
actionErrorFilterState: JSON.parse(JSON.stringify(pendingActionErrorFilterState)),
|
|
4902
|
+
advancedFilterState: JSON.parse(JSON.stringify(pendingAdvancedFilterState)),
|
|
4903
|
+
});
|
|
4804
4904
|
/*------------------------------------------------------------------------*/
|
|
4805
4905
|
/* ------------------------- Component Functions ------------------------ */
|
|
4806
4906
|
/*------------------------------------------------------------------------*/
|
|
4807
4907
|
/**
|
|
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
|
|
4908
|
+
* Fetch logs from the server based on current filters
|
|
4909
|
+
* @author Yuen Ler Chow
|
|
4910
|
+
* @param opts object containing all arguments
|
|
4911
|
+
* @param opts.filters the filters to apply
|
|
4912
|
+
* @param opts.pageNum the page number to fetch
|
|
4913
|
+
* @param opts.filtersChanged if true, the filters have changed
|
|
4847
4914
|
*/
|
|
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
|
|
4915
|
+
const fetchLogs = (opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
4916
|
+
const { filters, pageNum, filtersChanged, } = opts;
|
|
4861
4917
|
dispatch({
|
|
4862
4918
|
type: ActionType$6.StartLoading,
|
|
4863
4919
|
});
|
|
4864
|
-
// Load required months
|
|
4865
4920
|
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;
|
|
4921
|
+
// Send filters to the server
|
|
4922
|
+
let fetchedLogs = [];
|
|
4923
|
+
// Get logs from server
|
|
4924
|
+
const response = yield visitServerEndpoint({
|
|
4925
|
+
path: LOG_REVIEW_GET_LOGS_ROUTE,
|
|
4926
|
+
method: 'GET',
|
|
4927
|
+
params: {
|
|
4928
|
+
pageNumber: pageNum,
|
|
4929
|
+
filters,
|
|
4930
|
+
countDocuments: filtersChanged,
|
|
4931
|
+
},
|
|
4932
|
+
});
|
|
4933
|
+
fetchedLogs = fetchedLogs.concat(response.items);
|
|
4934
|
+
dispatch({
|
|
4935
|
+
type: ActionType$6.SetHasAnotherPage,
|
|
4936
|
+
hasAnotherPage: response.hasAnotherPage,
|
|
4937
|
+
});
|
|
4938
|
+
if (filtersChanged && response.numPages !== undefined) {
|
|
4939
|
+
dispatch({
|
|
4940
|
+
type: ActionType$6.SetNumPages,
|
|
4941
|
+
numPages: response.numPages,
|
|
4942
|
+
});
|
|
4890
4943
|
}
|
|
4944
|
+
// Update logs in state
|
|
4945
|
+
dispatch({
|
|
4946
|
+
type: ActionType$6.FinishLoading,
|
|
4947
|
+
logs: fetchedLogs,
|
|
4948
|
+
});
|
|
4949
|
+
// Update page number
|
|
4950
|
+
dispatch({
|
|
4951
|
+
type: ActionType$6.SetPageNumber,
|
|
4952
|
+
pageNumber: pageNum,
|
|
4953
|
+
});
|
|
4891
4954
|
}
|
|
4892
4955
|
catch (err) {
|
|
4893
4956
|
return showFatalError(err);
|
|
4894
4957
|
}
|
|
4895
|
-
// Finish loading
|
|
4896
|
-
dispatch({
|
|
4897
|
-
type: ActionType$6.FinishLoading,
|
|
4898
|
-
logMap,
|
|
4899
|
-
});
|
|
4900
4958
|
});
|
|
4901
4959
|
/*------------------------------------------------------------------------*/
|
|
4902
4960
|
/* ------------------------- Lifecycle Functions ------------------------ */
|
|
4903
4961
|
/*------------------------------------------------------------------------*/
|
|
4904
4962
|
/**
|
|
4905
|
-
*
|
|
4906
|
-
* @author
|
|
4963
|
+
* Fetch logs on mount
|
|
4964
|
+
* @author Yuen Ler Chow
|
|
4907
4965
|
*/
|
|
4908
4966
|
React.useEffect(() => {
|
|
4909
|
-
|
|
4910
|
-
|
|
4967
|
+
fetchLogs({
|
|
4968
|
+
filters: {
|
|
4969
|
+
dateFilterState: pendingDateFilterState,
|
|
4970
|
+
contextFilterState: pendingContextFilterState,
|
|
4971
|
+
tagFilterState: pendingTagFilterState,
|
|
4972
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
4973
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
4974
|
+
},
|
|
4975
|
+
pageNum: 1,
|
|
4976
|
+
filtersChanged: true,
|
|
4977
|
+
});
|
|
4911
4978
|
}, []);
|
|
4912
4979
|
/*------------------------------------------------------------------------*/
|
|
4913
4980
|
/* ------------------------------- Render ------------------------------- */
|
|
@@ -4915,718 +4982,534 @@ const LogReviewer = (props) => {
|
|
|
4915
4982
|
/*----------------------------------------*/
|
|
4916
4983
|
/* --------------- Main UI -------------- */
|
|
4917
4984
|
/*----------------------------------------*/
|
|
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
|
-
|
|
4985
|
+
/*----------------------------------------*/
|
|
4986
|
+
/* ------------ Pagination -------------- */
|
|
4987
|
+
/*----------------------------------------*/
|
|
4988
|
+
const paginationControls = logs.length > 0 && (React__default["default"].createElement(Pagination, { currentPage: pageNumber, numPages: numPages, loading: loading, onPageChanged: (targetPage) => {
|
|
4989
|
+
const { current: activeFilters } = activeFiltersRef;
|
|
4990
|
+
fetchLogs({
|
|
4991
|
+
filters: {
|
|
4992
|
+
dateFilterState: activeFilters.dateFilterState,
|
|
4993
|
+
contextFilterState: activeFilters.contextFilterState,
|
|
4994
|
+
tagFilterState: activeFilters.tagFilterState,
|
|
4995
|
+
actionErrorFilterState: activeFilters.actionErrorFilterState,
|
|
4996
|
+
advancedFilterState: activeFilters.advancedFilterState,
|
|
4997
|
+
},
|
|
4998
|
+
pageNum: targetPage,
|
|
4999
|
+
filtersChanged: false,
|
|
5000
|
+
});
|
|
5001
|
+
} }));
|
|
5002
|
+
/*----------------------------------------*/
|
|
5003
|
+
/* --------------- Filters -------------- */
|
|
5004
|
+
/*----------------------------------------*/
|
|
5005
|
+
// Filter toggle
|
|
5006
|
+
const filterToggles = (React__default["default"].createElement("div", { className: "LogReviewer-filter-toggles" },
|
|
5007
|
+
React__default["default"].createElement("div", { className: "LogReviewer-filter-toggle-buttons alert alert-secondary p-2 m-0" },
|
|
5008
|
+
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: () => {
|
|
5009
|
+
dispatch({
|
|
5010
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
5011
|
+
filterDrawer: FilterDrawer.Date,
|
|
5012
|
+
});
|
|
5013
|
+
} },
|
|
5014
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCalendar, className: "me-2" }),
|
|
5015
|
+
"Date"),
|
|
5016
|
+
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: () => {
|
|
5017
|
+
dispatch({
|
|
5018
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
5019
|
+
filterDrawer: FilterDrawer.Context,
|
|
5020
|
+
});
|
|
5021
|
+
} },
|
|
5022
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faCircle, className: "me-2" }),
|
|
5023
|
+
"Context"),
|
|
5024
|
+
(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: () => {
|
|
5025
|
+
dispatch({
|
|
5026
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
5027
|
+
filterDrawer: FilterDrawer.Tag,
|
|
5028
|
+
});
|
|
5029
|
+
} },
|
|
5030
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTag, className: "me-2" }),
|
|
5031
|
+
"Tag")),
|
|
5032
|
+
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: () => {
|
|
5033
|
+
dispatch({
|
|
5034
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
5035
|
+
filterDrawer: FilterDrawer.Action,
|
|
5036
|
+
});
|
|
5037
|
+
} },
|
|
5038
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faHammer, className: "me-2" }),
|
|
5039
|
+
"Action"),
|
|
5040
|
+
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: () => {
|
|
5041
|
+
dispatch({
|
|
5042
|
+
type: ActionType$6.ToggleFilterDrawer,
|
|
5043
|
+
filterDrawer: FilterDrawer.Advanced,
|
|
5044
|
+
});
|
|
5045
|
+
} },
|
|
5046
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faList, className: "me-2" }),
|
|
5047
|
+
"Advanced"),
|
|
5048
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-reset-filters-button", className: "btn btn-light", "aria-label": "reset filters", onClick: () => {
|
|
5049
|
+
// Save active filters
|
|
5050
|
+
// Deep clone the initial filter states to avoid any reference issues
|
|
5051
|
+
// if the filter states are modified later
|
|
5052
|
+
activeFiltersRef.current = cloneDeep({
|
|
5053
|
+
dateFilterState: initDateFilterState,
|
|
5054
|
+
contextFilterState: initContextFilterState,
|
|
5055
|
+
tagFilterState: initTagFilterState,
|
|
5056
|
+
actionErrorFilterState: initActionErrorFilterState,
|
|
5057
|
+
advancedFilterState: initAdvancedFilterState,
|
|
5058
|
+
});
|
|
5059
|
+
fetchLogs({
|
|
5060
|
+
filters: {
|
|
5061
|
+
dateFilterState: initDateFilterState,
|
|
5062
|
+
contextFilterState: initContextFilterState,
|
|
5063
|
+
tagFilterState: initTagFilterState,
|
|
5064
|
+
actionErrorFilterState: initActionErrorFilterState,
|
|
5065
|
+
advancedFilterState: initAdvancedFilterState,
|
|
5066
|
+
},
|
|
5067
|
+
pageNum: 1,
|
|
5068
|
+
filtersChanged: true,
|
|
5069
|
+
});
|
|
5070
|
+
dispatch({
|
|
5071
|
+
type: ActionType$6.ResetFilters,
|
|
5072
|
+
initActionErrorFilterState,
|
|
5073
|
+
initAdvancedFilterState,
|
|
5074
|
+
initContextFilterState,
|
|
5075
|
+
initDateFilterState,
|
|
5076
|
+
initTagFilterState,
|
|
5077
|
+
});
|
|
5078
|
+
dispatch({
|
|
5079
|
+
type: ActionType$6.HideFilterDrawer,
|
|
5080
|
+
});
|
|
5081
|
+
} },
|
|
5082
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes }),
|
|
5083
|
+
' ',
|
|
5084
|
+
"Reset"),
|
|
5085
|
+
userMadeFilterChange && (React__default["default"].createElement("button", { type: "button", id: "LogReviewer-submit-filters-button", className: "btn btn-primary ms-2", "aria-label": "submit filters", onClick: () => {
|
|
5086
|
+
dispatch({
|
|
5087
|
+
type: ActionType$6.HideFilterDrawer,
|
|
5088
|
+
});
|
|
5089
|
+
// Reset user made filter change indicator
|
|
5090
|
+
dispatch({
|
|
5091
|
+
type: ActionType$6.ResetUserMadeFilterChange,
|
|
5092
|
+
});
|
|
5093
|
+
// Save active filters
|
|
5094
|
+
// Deep clone the pending filter states to avoid any reference issues
|
|
5095
|
+
// if the filter states are modified later
|
|
5096
|
+
activeFiltersRef.current = cloneDeep({
|
|
5097
|
+
dateFilterState: pendingDateFilterState,
|
|
5098
|
+
contextFilterState: pendingContextFilterState,
|
|
5099
|
+
tagFilterState: pendingTagFilterState,
|
|
5100
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
5101
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
5102
|
+
});
|
|
5103
|
+
fetchLogs({
|
|
5104
|
+
filters: {
|
|
5105
|
+
dateFilterState: pendingDateFilterState,
|
|
5106
|
+
contextFilterState: pendingContextFilterState,
|
|
5107
|
+
tagFilterState: pendingTagFilterState,
|
|
5108
|
+
actionErrorFilterState: pendingActionErrorFilterState,
|
|
5109
|
+
advancedFilterState: pendingAdvancedFilterState,
|
|
5110
|
+
},
|
|
5111
|
+
pageNum: 1,
|
|
5112
|
+
filtersChanged: true,
|
|
5113
|
+
});
|
|
5114
|
+
} },
|
|
5115
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faSearch }),
|
|
5116
|
+
' ',
|
|
5117
|
+
"Apply Filters")))));
|
|
5118
|
+
// Filter drawer
|
|
5119
|
+
let filterDrawer;
|
|
5120
|
+
if (expandedFilterDrawer) {
|
|
5121
|
+
if (expandedFilterDrawer === FilterDrawer.Date) {
|
|
5122
|
+
filterDrawer = (React__default["default"].createElement(TabBox, { title: "Date" },
|
|
5123
|
+
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, dontAllowFuture: true, numMonthsToShow: 36, onChange: (month, day, year) => {
|
|
5124
|
+
const newDateFilterState = Object.assign(Object.assign({}, pendingDateFilterState), { startDate: { month, day, year } });
|
|
4967
5125
|
dispatch({
|
|
4968
|
-
type: ActionType$6.
|
|
4969
|
-
|
|
5126
|
+
type: ActionType$6.UpdateDateFilterState,
|
|
5127
|
+
dateFilterState: newDateFilterState,
|
|
4970
5128
|
});
|
|
4971
|
-
} },
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
5129
|
+
} }),
|
|
5130
|
+
' ',
|
|
5131
|
+
"to",
|
|
5132
|
+
' ',
|
|
5133
|
+
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, dontAllowFuture: true, numMonthsToShow: 12, onChange: (month, day, year) => {
|
|
5134
|
+
if (year < pendingDateFilterState.startDate.year
|
|
5135
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
5136
|
+
&& month < pendingDateFilterState.startDate.month)
|
|
5137
|
+
|| (year === pendingDateFilterState.startDate.year
|
|
5138
|
+
&& month === pendingDateFilterState.startDate.month
|
|
5139
|
+
&& day < pendingDateFilterState.startDate.day)) {
|
|
5140
|
+
return alert('Invalid End Date', 'The end date cannot be before the start date.');
|
|
5141
|
+
}
|
|
5142
|
+
const newDateFilterState = Object.assign(Object.assign({}, pendingDateFilterState), { endDate: { month, day, year } });
|
|
4975
5143
|
dispatch({
|
|
4976
|
-
type: ActionType$6.
|
|
4977
|
-
|
|
4978
|
-
initAdvancedFilterState,
|
|
4979
|
-
initContextFilterState,
|
|
4980
|
-
initDateFilterState,
|
|
4981
|
-
initTagFilterState,
|
|
5144
|
+
type: ActionType$6.UpdateDateFilterState,
|
|
5145
|
+
dateFilterState: newDateFilterState,
|
|
4982
5146
|
});
|
|
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
|
-
}));
|
|
5147
|
+
} })));
|
|
5148
|
+
}
|
|
5149
|
+
else if (expandedFilterDrawer === FilterDrawer.Context) {
|
|
5150
|
+
// Create item picker items
|
|
5151
|
+
const builtInPickableItem = {
|
|
5152
|
+
id: 'built-in-contexts',
|
|
5153
|
+
name: 'Auto-logged',
|
|
5154
|
+
isGroup: true,
|
|
5155
|
+
children: [],
|
|
5156
|
+
};
|
|
5157
|
+
const pickableItems = [];
|
|
5158
|
+
Object.keys(contextMap)
|
|
5159
|
+
.forEach((context) => {
|
|
5160
|
+
const value = contextMap[context];
|
|
5161
|
+
if (typeof value === 'string') {
|
|
5162
|
+
// No subcategories
|
|
5059
5163
|
const item = {
|
|
5060
5164
|
id: context,
|
|
5061
5165
|
name: genHumanReadableName(context),
|
|
5062
|
-
isGroup:
|
|
5063
|
-
|
|
5166
|
+
isGroup: false,
|
|
5167
|
+
checked: !!pendingContextFilterState[context],
|
|
5064
5168
|
};
|
|
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
|
-
|
|
5169
|
+
// Add built-in items to its own folder
|
|
5170
|
+
const isBuiltIn = context in LogBuiltInMetadata.Context;
|
|
5171
|
+
if (isBuiltIn) {
|
|
5172
|
+
// Add to built-in pickable item
|
|
5173
|
+
builtInPickableItem.children.push(item);
|
|
5174
|
+
}
|
|
5175
|
+
else {
|
|
5176
|
+
// Add to pickable items list
|
|
5177
|
+
pickableItems.push(item);
|
|
5178
|
+
}
|
|
5179
|
+
return;
|
|
5180
|
+
}
|
|
5181
|
+
// Has subcategories
|
|
5182
|
+
const children = (Object.keys(value)
|
|
5183
|
+
// Remove parent name
|
|
5184
|
+
.filter((subcontext) => {
|
|
5185
|
+
return (subcontext !== '_');
|
|
5186
|
+
})
|
|
5187
|
+
// Create child pickable items
|
|
5188
|
+
.map((subcontext) => {
|
|
5189
|
+
return {
|
|
5190
|
+
id: subcontext,
|
|
5191
|
+
name: genHumanReadableName(subcontext),
|
|
5192
|
+
isGroup: false,
|
|
5193
|
+
checked: pendingContextFilterState[context][subcontext],
|
|
5194
|
+
};
|
|
5195
|
+
}));
|
|
5196
|
+
const item = {
|
|
5197
|
+
id: context,
|
|
5198
|
+
name: genHumanReadableName(context),
|
|
5199
|
+
isGroup: true,
|
|
5200
|
+
children,
|
|
5201
|
+
};
|
|
5202
|
+
pickableItems.push(item);
|
|
5203
|
+
});
|
|
5204
|
+
// Add built-in contexts to end of list
|
|
5205
|
+
pickableItems.push(builtInPickableItem);
|
|
5206
|
+
// Create filter UI
|
|
5207
|
+
filterDrawer = (React__default["default"].createElement(ItemPicker, { title: "Context", items: pickableItems, onChanged: (updatedItems) => {
|
|
5208
|
+
// Update our state
|
|
5209
|
+
const newContextFilterState = Object.assign({}, pendingContextFilterState);
|
|
5210
|
+
updatedItems.forEach((pickableItem) => {
|
|
5211
|
+
if (pickableItem.isGroup) {
|
|
5212
|
+
// Has subcontexts
|
|
5213
|
+
if (pickableItem.id === 'built-in-contexts') {
|
|
5214
|
+
// Built-in
|
|
5215
|
+
// Treat as if these were top-level contexts
|
|
5216
|
+
pickableItem.children.forEach((subcontextItem) => {
|
|
5217
|
+
newContextFilterState[subcontextItem.id] = ('checked' in subcontextItem
|
|
5218
|
+
&& subcontextItem.checked);
|
|
5219
|
+
});
|
|
5091
5220
|
}
|
|
5092
5221
|
else {
|
|
5093
|
-
//
|
|
5094
|
-
|
|
5222
|
+
// Not built-in
|
|
5223
|
+
pickableItem.children.forEach((subcontextItem) => {
|
|
5224
|
+
if (!subcontextItem.isGroup) {
|
|
5225
|
+
newContextFilterState[pickableItem.id][subcontextItem.id] = (subcontextItem.checked);
|
|
5226
|
+
}
|
|
5227
|
+
});
|
|
5095
5228
|
}
|
|
5096
|
-
}
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
}
|
|
5101
|
-
}
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5229
|
+
}
|
|
5230
|
+
else {
|
|
5231
|
+
// No subcontexts
|
|
5232
|
+
newContextFilterState[pickableItem.id] = (pickableItem.checked);
|
|
5233
|
+
}
|
|
5234
|
+
});
|
|
5235
|
+
// Update state
|
|
5236
|
+
dispatch({
|
|
5237
|
+
type: ActionType$6.UpdateContextFilterState,
|
|
5238
|
+
contextFilterState: newContextFilterState,
|
|
5239
|
+
});
|
|
5240
|
+
} }));
|
|
5241
|
+
}
|
|
5242
|
+
else if (expandedFilterDrawer === FilterDrawer.Tag) {
|
|
5243
|
+
// Create filter UI
|
|
5244
|
+
filterDrawer = (React__default["default"].createElement(TabBox, { title: "Tags" },
|
|
5245
|
+
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."),
|
|
5246
|
+
React__default["default"].createElement("div", { className: "d-flex gap-1 flex-wrap" }, Object.keys((_d = LogMetadata.Tag) !== null && _d !== void 0 ? _d : {})
|
|
5247
|
+
.map((tag) => {
|
|
5248
|
+
const description = genHumanReadableName(tag);
|
|
5249
|
+
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) => {
|
|
5250
|
+
const newTagFilterState = Object.assign(Object.assign({}, pendingTagFilterState), { [tag]: checked });
|
|
5251
|
+
dispatch({
|
|
5252
|
+
type: ActionType$6.UpdateTagFilterState,
|
|
5253
|
+
tagFilterState: newTagFilterState,
|
|
5254
|
+
});
|
|
5255
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5256
|
+
}))));
|
|
5257
|
+
}
|
|
5258
|
+
else if (expandedFilterDrawer === FilterDrawer.Action) {
|
|
5259
|
+
// Create filter UI
|
|
5260
|
+
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5261
|
+
React__default["default"].createElement(TabBox, { title: "Log Type" },
|
|
5262
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-all", text: "All Logs", onSelected: () => {
|
|
5263
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: undefined });
|
|
5264
|
+
dispatch({
|
|
5265
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5266
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5267
|
+
});
|
|
5268
|
+
}, ariaLabel: "show logs of all types", selected: pendingActionErrorFilterState.type === undefined, unselectedVariant: Variant$1.Light }),
|
|
5269
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-action-only", text: "Action Logs Only", onSelected: () => {
|
|
5270
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: LogType$1.Action });
|
|
5271
|
+
dispatch({
|
|
5272
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5273
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5274
|
+
});
|
|
5275
|
+
}, ariaLabel: "only show action logs", selected: pendingActionErrorFilterState.type === LogType$1.Action, unselectedVariant: Variant$1.Light }),
|
|
5276
|
+
React__default["default"].createElement(RadioButton, { id: "LogReviewer-type-error-only", text: "Action Error Only", onSelected: () => {
|
|
5277
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { type: LogType$1.Error });
|
|
5278
|
+
dispatch({
|
|
5279
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5280
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5281
|
+
});
|
|
5282
|
+
}, ariaLabel: "only show error logs", selected: pendingActionErrorFilterState.type === LogType$1.Error, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
5283
|
+
(pendingActionErrorFilterState.type === undefined
|
|
5284
|
+
|| pendingActionErrorFilterState.type === LogType$1.Action) && (React__default["default"].createElement(TabBox, { title: "Action Log Details" },
|
|
5285
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Action", className: "mb-2", wrapButtonsAndAddGaps: true }, Object.keys(LogAction$1)
|
|
5286
|
+
.map((action) => {
|
|
5287
|
+
const description = genHumanReadableName(action);
|
|
5288
|
+
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) => {
|
|
5289
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { action: Object.assign(Object.assign({}, pendingActionErrorFilterState.action), { [action]: checked }) });
|
|
5112
5290
|
dispatch({
|
|
5113
|
-
type: ActionType$6.
|
|
5114
|
-
|
|
5291
|
+
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5292
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5115
5293
|
});
|
|
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;
|
|
5294
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5295
|
+
})),
|
|
5296
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Target", wrapButtonsAndAddGaps: true }, Object.keys(targetMap)
|
|
5297
|
+
.map((target) => {
|
|
5298
|
+
const description = genHumanReadableName(target);
|
|
5299
|
+
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) => {
|
|
5300
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { target: Object.assign(Object.assign({}, pendingActionErrorFilterState.target), { [target]: checked }) });
|
|
5125
5301
|
dispatch({
|
|
5126
5302
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5127
|
-
actionErrorFilterState,
|
|
5303
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5128
5304
|
});
|
|
5129
|
-
},
|
|
5130
|
-
|
|
5131
|
-
|
|
5305
|
+
}, checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }));
|
|
5306
|
+
})))),
|
|
5307
|
+
(pendingActionErrorFilterState.type === undefined
|
|
5308
|
+
|| pendingActionErrorFilterState.type === LogType$1.Error) && (React__default["default"].createElement(TabBox, { title: "Error Log Details" },
|
|
5309
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5310
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Message"),
|
|
5311
|
+
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) => {
|
|
5312
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { errorMessage: e.target.value });
|
|
5132
5313
|
dispatch({
|
|
5133
5314
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5134
|
-
actionErrorFilterState,
|
|
5315
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5135
5316
|
});
|
|
5136
|
-
}
|
|
5137
|
-
|
|
5138
|
-
|
|
5317
|
+
} })),
|
|
5318
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5319
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Error Code"),
|
|
5320
|
+
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) => {
|
|
5321
|
+
const newActionErrorFilterState = Object.assign(Object.assign({}, pendingActionErrorFilterState), { errorCode: ((e.target.value)
|
|
5322
|
+
.trim()
|
|
5323
|
+
.toUpperCase()) });
|
|
5139
5324
|
dispatch({
|
|
5140
5325
|
type: ActionType$6.UpdateActionErrorFilterState,
|
|
5141
|
-
actionErrorFilterState,
|
|
5326
|
+
actionErrorFilterState: newActionErrorFilterState,
|
|
5142
5327
|
});
|
|
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;
|
|
5328
|
+
} }))))));
|
|
5329
|
+
}
|
|
5330
|
+
else if (expandedFilterDrawer === FilterDrawer.Advanced) {
|
|
5331
|
+
// Create advanced filter ui
|
|
5332
|
+
filterDrawer = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5333
|
+
React__default["default"].createElement(TabBox, { title: "User" },
|
|
5334
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5335
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User First Name"),
|
|
5336
|
+
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) => {
|
|
5337
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userFirstName: e.target.value });
|
|
5338
|
+
dispatch({
|
|
5339
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5340
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5341
|
+
});
|
|
5342
|
+
} })),
|
|
5343
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5344
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Last Name"),
|
|
5345
|
+
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) => {
|
|
5346
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userLastName: e.target.value });
|
|
5347
|
+
dispatch({
|
|
5348
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5349
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5350
|
+
});
|
|
5351
|
+
} })),
|
|
5352
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5353
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Email"),
|
|
5354
|
+
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) => {
|
|
5355
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userEmail: ((e.target.value)
|
|
5356
|
+
.trim()) });
|
|
5357
|
+
dispatch({
|
|
5358
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5359
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5360
|
+
});
|
|
5361
|
+
} })),
|
|
5362
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5363
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "User Canvas Id"),
|
|
5364
|
+
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) => {
|
|
5365
|
+
const { value } = e.target;
|
|
5366
|
+
// Only update if value contains only numbers
|
|
5367
|
+
if (/^\d+$/.test(value) || value === '') {
|
|
5368
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { userId: ((e.target.value)
|
|
5369
|
+
.trim()) });
|
|
5247
5370
|
dispatch({
|
|
5248
5371
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5249
|
-
advancedFilterState,
|
|
5372
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5250
5373
|
});
|
|
5251
|
-
}
|
|
5252
|
-
|
|
5253
|
-
|
|
5374
|
+
}
|
|
5375
|
+
} })),
|
|
5376
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Role" },
|
|
5377
|
+
React__default["default"].createElement(CheckboxButton, { text: "Students", onChanged: (checked) => {
|
|
5378
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeLearners: checked });
|
|
5379
|
+
dispatch({
|
|
5380
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5381
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5382
|
+
});
|
|
5383
|
+
}, checked: pendingAdvancedFilterState.includeLearners, ariaLabel: "show logs from students", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
5384
|
+
React__default["default"].createElement(CheckboxButton, { text: "Teaching Team Members", onChanged: (checked) => {
|
|
5385
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeTTMs: checked });
|
|
5386
|
+
dispatch({
|
|
5387
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5388
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5389
|
+
});
|
|
5390
|
+
}, checked: pendingAdvancedFilterState.includeTTMs, ariaLabel: "show logs from teaching team members", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }),
|
|
5391
|
+
React__default["default"].createElement(CheckboxButton, { text: "Admins", onChanged: (checked) => {
|
|
5392
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { includeAdmins: checked });
|
|
5393
|
+
dispatch({
|
|
5394
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5395
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5396
|
+
});
|
|
5397
|
+
}, checked: pendingAdvancedFilterState.includeAdmins, ariaLabel: "show logs from admins", checkedVariant: Variant$1.Light, uncheckedVariant: Variant$1.Light }))),
|
|
5398
|
+
React__default["default"].createElement(TabBox, { title: "Course" },
|
|
5399
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5400
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Name"),
|
|
5401
|
+
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) => {
|
|
5402
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { courseName: e.target.value });
|
|
5403
|
+
dispatch({
|
|
5404
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5405
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5406
|
+
});
|
|
5407
|
+
} })),
|
|
5408
|
+
React__default["default"].createElement("div", { className: "input-group mb-2" },
|
|
5409
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Course Canvas Id"),
|
|
5410
|
+
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) => {
|
|
5411
|
+
const { value } = e.target;
|
|
5412
|
+
// Only update if value contains only numbers
|
|
5413
|
+
if (/^\d+$/.test(value) || value === '') {
|
|
5414
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { courseId: ((e.target.value)
|
|
5415
|
+
.trim()) });
|
|
5254
5416
|
dispatch({
|
|
5255
5417
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5256
|
-
advancedFilterState,
|
|
5418
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5257
5419
|
});
|
|
5258
|
-
}
|
|
5259
|
-
|
|
5420
|
+
}
|
|
5421
|
+
} }))),
|
|
5422
|
+
React__default["default"].createElement(TabBox, { title: "Device" },
|
|
5423
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Device Type" },
|
|
5424
|
+
React__default["default"].createElement(RadioButton, { text: "All Devices", ariaLabel: "show logs from all devices", selected: pendingAdvancedFilterState.isMobile === undefined, onSelected: () => {
|
|
5425
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: undefined });
|
|
5426
|
+
dispatch({
|
|
5427
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5428
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5429
|
+
});
|
|
5430
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5431
|
+
React__default["default"].createElement(RadioButton, { text: "Mobile Only", ariaLabel: "show logs from mobile devices", selected: pendingAdvancedFilterState.isMobile === true, onSelected: () => {
|
|
5432
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: true });
|
|
5433
|
+
dispatch({
|
|
5434
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5435
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5436
|
+
});
|
|
5437
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5438
|
+
React__default["default"].createElement(RadioButton, { text: "Desktop Only", ariaLabel: "show logs from desktop devices", selected: pendingAdvancedFilterState.isMobile === false, onSelected: () => {
|
|
5439
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { isMobile: false });
|
|
5440
|
+
dispatch({
|
|
5441
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5442
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5443
|
+
});
|
|
5444
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }))),
|
|
5445
|
+
React__default["default"].createElement(TabBox, { title: "Source" },
|
|
5446
|
+
React__default["default"].createElement(ButtonInputGroup, { label: "Source Type" },
|
|
5447
|
+
React__default["default"].createElement(RadioButton, { text: "Both", ariaLabel: "show logs from all sources", selected: pendingAdvancedFilterState.source === undefined, onSelected: () => {
|
|
5448
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: undefined });
|
|
5449
|
+
dispatch({
|
|
5450
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5451
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5452
|
+
});
|
|
5453
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5454
|
+
React__default["default"].createElement(RadioButton, { text: "Client Only", ariaLabel: "show logs from client source", selected: pendingAdvancedFilterState.source === LogSource$1.Client, onSelected: () => {
|
|
5455
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: LogSource$1.Client });
|
|
5456
|
+
dispatch({
|
|
5457
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5458
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5459
|
+
});
|
|
5460
|
+
}, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light }),
|
|
5461
|
+
React__default["default"].createElement(RadioButton, { text: "Server Only", ariaLabel: "show logs from server source", selected: pendingAdvancedFilterState.source === LogSource$1.Server, onSelected: () => {
|
|
5462
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { source: LogSource$1.Server });
|
|
5463
|
+
dispatch({
|
|
5464
|
+
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5465
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5466
|
+
});
|
|
5467
|
+
}, noMarginOnRight: true, selectedVariant: Variant$1.Light, unselectedVariant: Variant$1.Light })),
|
|
5468
|
+
pendingAdvancedFilterState.source !== LogSource$1.Client && (React__default["default"].createElement("div", { className: "mt-2" },
|
|
5260
5469
|
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
|
-
|
|
5470
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Path"),
|
|
5471
|
+
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) => {
|
|
5472
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { routePath: ((e.target.value)
|
|
5473
|
+
.trim()) });
|
|
5264
5474
|
dispatch({
|
|
5265
5475
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5266
|
-
advancedFilterState,
|
|
5476
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5267
5477
|
});
|
|
5268
5478
|
} })),
|
|
5269
5479
|
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;
|
|
5317
|
-
dispatch({
|
|
5318
|
-
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5319
|
-
advancedFilterState,
|
|
5320
|
-
});
|
|
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;
|
|
5480
|
+
React__default["default"].createElement("span", { className: "input-group-text" }, "Server Route Template"),
|
|
5481
|
+
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) => {
|
|
5482
|
+
const newAdvancedFilterState = Object.assign(Object.assign({}, pendingAdvancedFilterState), { routeTemplate: ((e.target.value)
|
|
5483
|
+
.trim()) });
|
|
5324
5484
|
dispatch({
|
|
5325
5485
|
type: ActionType$6.UpdateAdvancedFilterState,
|
|
5326
|
-
advancedFilterState,
|
|
5486
|
+
advancedFilterState: newAdvancedFilterState,
|
|
5327
5487
|
});
|
|
5328
|
-
}
|
|
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
|
-
}
|
|
5488
|
+
} })))))));
|
|
5351
5489
|
}
|
|
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
5490
|
}
|
|
5491
|
+
// Filters UI
|
|
5492
|
+
const filters = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5493
|
+
filterToggles,
|
|
5494
|
+
filterDrawer && (React__default["default"].createElement(Drawer, { customBackgroundColor: "#eee" }, filterDrawer))));
|
|
5495
|
+
// Body that will be filled with the contents of the panel
|
|
5496
|
+
const body = (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
5497
|
+
loading && (React__default["default"].createElement("div", { className: "text-center p-5" },
|
|
5498
|
+
React__default["default"].createElement(LoadingSpinner, null))),
|
|
5499
|
+
!loading && (React__default["default"].createElement("div", null, filters)),
|
|
5500
|
+
!loading && logs.length === 0 && (React__default["default"].createElement("div", { className: "alert alert-warning text-center mt-2" },
|
|
5501
|
+
React__default["default"].createElement("h4", { className: "m-1" }, "No Logs to Show"),
|
|
5502
|
+
React__default["default"].createElement("div", null, "Either your filters are too strict or no matching logs have been created yet."))),
|
|
5503
|
+
React__default["default"].createElement("div", { className: loading || logs.length === 0 ? 'd-none' : undefined },
|
|
5504
|
+
React__default["default"].createElement(IntelliTable, { title: "Matching Logs", csvName: `Logs from ${getHumanReadableDate()}`, id: "logs", data: logs, columns: columns })),
|
|
5505
|
+
!loading && logs.length > 0 && paginationControls));
|
|
5623
5506
|
/* ---------- Wrap in Modal --------- */
|
|
5624
5507
|
return (React__default["default"].createElement("div", { className: "LogReviewer-outer-container" },
|
|
5625
5508
|
React__default["default"].createElement("style", null, style$2),
|
|
5626
5509
|
React__default["default"].createElement("div", { className: "LogReviewer-inner-container" },
|
|
5627
5510
|
React__default["default"].createElement("div", { className: "LogReviewer-header" },
|
|
5628
5511
|
React__default["default"].createElement("div", { className: "LogReviewer-header-title" },
|
|
5629
|
-
React__default["default"].createElement("h3", { className: "text-center
|
|
5512
|
+
React__default["default"].createElement("h3", { className: "text-center" }, "Log Review Dashboard")),
|
|
5630
5513
|
React__default["default"].createElement("div", { style: { width: 0 } },
|
|
5631
5514
|
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
5515
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes })))),
|
|
@@ -15302,6 +15185,12 @@ const HOUR_IN_MS = 3600000;
|
|
|
15302
15185
|
*/
|
|
15303
15186
|
const DAY_IN_MS = 86400000;
|
|
15304
15187
|
|
|
15188
|
+
/**
|
|
15189
|
+
* Path of the route for storing client-side logs
|
|
15190
|
+
* @author Gabe Abrams
|
|
15191
|
+
*/
|
|
15192
|
+
const LOG_REVIEW_ROUTE_PATH_PREFIX = `/admin${ROUTE_PATH_PREFIX}/logs`;
|
|
15193
|
+
|
|
15305
15194
|
/**
|
|
15306
15195
|
* Route for checking the status of the current user's
|
|
15307
15196
|
* access to log review
|
|
@@ -16365,6 +16254,7 @@ exports.ErrorWithCode = ErrorWithCode;
|
|
|
16365
16254
|
exports.HOUR_IN_MS = HOUR_IN_MS;
|
|
16366
16255
|
exports.IntelliTable = IntelliTable;
|
|
16367
16256
|
exports.ItemPicker = ItemPicker;
|
|
16257
|
+
exports.LOG_REVIEW_GET_LOGS_ROUTE = LOG_REVIEW_GET_LOGS_ROUTE;
|
|
16368
16258
|
exports.LOG_REVIEW_ROUTE_PATH_PREFIX = LOG_REVIEW_ROUTE_PATH_PREFIX;
|
|
16369
16259
|
exports.LOG_REVIEW_STATUS_ROUTE = LOG_REVIEW_STATUS_ROUTE;
|
|
16370
16260
|
exports.LOG_ROUTE_PATH = LOG_ROUTE_PATH;
|
|
@@ -16400,6 +16290,7 @@ exports.avg = avg;
|
|
|
16400
16290
|
exports.canReviewLogs = canReviewLogs;
|
|
16401
16291
|
exports.capitalize = capitalize;
|
|
16402
16292
|
exports.ceilToNumDecimals = ceilToNumDecimals;
|
|
16293
|
+
exports.cloneDeep = cloneDeep;
|
|
16403
16294
|
exports.combineClassNames = combineClassNames;
|
|
16404
16295
|
exports.compareArraysByProp = compareArraysByProp;
|
|
16405
16296
|
exports.confirm = confirm;
|