dce-reactkit 3.9.4-beta-logreviewer.2 → 3.9.4-beta-logreviewer.3
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 +105 -47
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- 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/esm/index.js +106 -48
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/constants/LOG_REVIEW_GET_LOGS_ROUTE.d.ts +6 -0
- 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/package.json +1 -1
- package/src/components/LogReviewer.tsx +40 -98
- package/src/constants/LOG_REVIEW_GET_LOGS_ROUTE.ts +9 -0
- package/src/server/initServer.ts +104 -40
- 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/dist/cjs/types/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.d.ts +0 -6
- package/dist/esm/types/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.d.ts +0 -6
- package/src/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.ts +0 -9
package/dist/cjs/index.js
CHANGED
|
@@ -2574,10 +2574,10 @@ const getHumanReadableDate = (dateOrTimestamp) => {
|
|
|
2574
2574
|
};
|
|
2575
2575
|
|
|
2576
2576
|
/**
|
|
2577
|
-
* Path of the route for
|
|
2577
|
+
* Path of the route for getting logs for log review
|
|
2578
2578
|
* @author Gabe Abrams
|
|
2579
2579
|
*/
|
|
2580
|
-
const
|
|
2580
|
+
const LOG_REVIEW_GET_LOGS_ROUTE = `/admin${ROUTE_PATH_PREFIX}/logs`;
|
|
2581
2581
|
|
|
2582
2582
|
/**
|
|
2583
2583
|
* Source of a log event
|
|
@@ -3608,6 +3608,9 @@ const reducer$7 = (state, action) => {
|
|
|
3608
3608
|
case ActionType$6.DecrementPageNumber: {
|
|
3609
3609
|
return Object.assign(Object.assign({}, state), { pageNumber: state.pageNumber - 1 });
|
|
3610
3610
|
}
|
|
3611
|
+
case ActionType$6.SetHasAnotherPage: {
|
|
3612
|
+
return Object.assign(Object.assign({}, state), { hasAnotherPage: action.hasAnotherPage });
|
|
3613
|
+
}
|
|
3611
3614
|
default: {
|
|
3612
3615
|
return state;
|
|
3613
3616
|
}
|
|
@@ -3750,8 +3753,7 @@ const LogReviewer = (props) => {
|
|
|
3750
3753
|
try {
|
|
3751
3754
|
// Prepare filter parameters
|
|
3752
3755
|
const filters = {
|
|
3753
|
-
|
|
3754
|
-
endDate: dateFilterState.endDate,
|
|
3756
|
+
dateFilterState,
|
|
3755
3757
|
contextFilterState,
|
|
3756
3758
|
tagFilterState,
|
|
3757
3759
|
actionErrorFilterState,
|
|
@@ -3759,8 +3761,9 @@ const LogReviewer = (props) => {
|
|
|
3759
3761
|
};
|
|
3760
3762
|
// Send filters to the server
|
|
3761
3763
|
let fetchedLogs = [];
|
|
3764
|
+
// Get logs from server
|
|
3762
3765
|
const response = yield visitServerEndpoint({
|
|
3763
|
-
path:
|
|
3766
|
+
path: LOG_REVIEW_GET_LOGS_ROUTE,
|
|
3764
3767
|
method: 'GET',
|
|
3765
3768
|
params: {
|
|
3766
3769
|
pageNumber,
|
|
@@ -3786,16 +3789,12 @@ const LogReviewer = (props) => {
|
|
|
3786
3789
|
/* ------------------------- Lifecycle Functions ------------------------ */
|
|
3787
3790
|
/*------------------------------------------------------------------------*/
|
|
3788
3791
|
/**
|
|
3789
|
-
* Fetch logs whenever
|
|
3792
|
+
* Fetch logs whenever page number changes
|
|
3790
3793
|
*/
|
|
3791
3794
|
React.useEffect(() => {
|
|
3792
3795
|
fetchLogs();
|
|
3793
3796
|
}, [
|
|
3794
|
-
|
|
3795
|
-
contextFilterState,
|
|
3796
|
-
tagFilterState,
|
|
3797
|
-
actionErrorFilterState,
|
|
3798
|
-
advancedFilterState,
|
|
3797
|
+
pageNumber,
|
|
3799
3798
|
]);
|
|
3800
3799
|
/*------------------------------------------------------------------------*/
|
|
3801
3800
|
/* ------------------------------- Render ------------------------------- */
|
|
@@ -3892,7 +3891,16 @@ const LogReviewer = (props) => {
|
|
|
3892
3891
|
} },
|
|
3893
3892
|
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faTimes }),
|
|
3894
3893
|
' ',
|
|
3895
|
-
"Reset")
|
|
3894
|
+
"Reset"),
|
|
3895
|
+
React__default["default"].createElement("button", { type: "button", id: "LogReviewer-submit-filters-button", className: "btn btn-primary ms-2", "aria-label": "submit filters", onClick: () => {
|
|
3896
|
+
dispatch({
|
|
3897
|
+
type: ActionType$6.HideFilterDrawer,
|
|
3898
|
+
});
|
|
3899
|
+
fetchLogs();
|
|
3900
|
+
} },
|
|
3901
|
+
React__default["default"].createElement(reactFontawesome.FontAwesomeIcon, { icon: freeSolidSvgIcons.faSearch }),
|
|
3902
|
+
' ',
|
|
3903
|
+
"Filter"))));
|
|
3896
3904
|
// Filter drawer
|
|
3897
3905
|
let filterDrawer;
|
|
3898
3906
|
if (expandedFilterDrawer) {
|
|
@@ -13790,9 +13798,11 @@ const initServer = (opts) => {
|
|
|
13790
13798
|
/**
|
|
13791
13799
|
* Get filtered logs based on provided filters
|
|
13792
13800
|
* @author Gabe Abrams, Yuen Ler Chow
|
|
13801
|
+
* @param pageNumber the page number to get
|
|
13802
|
+
* @param filters the filters to apply to the logs
|
|
13793
13803
|
* @returns {Log[]} list of logs that match the filters
|
|
13794
13804
|
*/
|
|
13795
|
-
opts.app.get(`${
|
|
13805
|
+
opts.app.get(`${LOG_REVIEW_GET_LOGS_ROUTE}`, genRouteHandler({
|
|
13796
13806
|
paramTypes: {
|
|
13797
13807
|
pageNumber: ParamType$1.Int,
|
|
13798
13808
|
filters: ParamType$1.JSON,
|
|
@@ -13800,6 +13810,7 @@ const initServer = (opts) => {
|
|
|
13800
13810
|
handler: ({ params }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
13801
13811
|
// Get user info
|
|
13802
13812
|
const { pageNumber, userId, isAdmin, filters, } = params;
|
|
13813
|
+
const { dateFilterState, contextFilterState, tagFilterState, actionErrorFilterState, advancedFilterState, } = filters;
|
|
13803
13814
|
// Validate user
|
|
13804
13815
|
const canReview = yield canReviewLogs(userId, isAdmin);
|
|
13805
13816
|
if (!canReview) {
|
|
@@ -13808,58 +13819,85 @@ const initServer = (opts) => {
|
|
|
13808
13819
|
// Build MongoDB query based on filters
|
|
13809
13820
|
const query = {};
|
|
13810
13821
|
/* -------------- Date Filter ------------- */
|
|
13811
|
-
|
|
13822
|
+
// Convert start and end dates from the dateFilterState into timestamps
|
|
13823
|
+
const { startDate, endDate } = dateFilterState;
|
|
13812
13824
|
const startTimestamp = new Date(startDate.year, startDate.month - 1, startDate.day).getTime();
|
|
13813
13825
|
const endTimestamp = new Date(endDate.year, endDate.month - 1, endDate.day + 1).getTime() - 1;
|
|
13826
|
+
// Add a date range condition to the query
|
|
13814
13827
|
query.timestamp = {
|
|
13815
13828
|
$gte: startTimestamp,
|
|
13816
13829
|
$lte: endTimestamp,
|
|
13817
13830
|
};
|
|
13818
13831
|
/* ------------ Context Filter ------------ */
|
|
13819
|
-
|
|
13820
|
-
const
|
|
13832
|
+
// Process context filters to include selected contexts and subcontexts
|
|
13833
|
+
const selectedContexts = [];
|
|
13834
|
+
const selectedSubcontexts = [];
|
|
13835
|
+
// Process each context filter
|
|
13821
13836
|
Object.keys(contextFilterState).forEach((context) => {
|
|
13822
13837
|
const value = contextFilterState[context];
|
|
13823
13838
|
if (typeof value === 'boolean') {
|
|
13824
13839
|
if (value) {
|
|
13825
|
-
|
|
13826
|
-
contextConditions.push({ context });
|
|
13840
|
+
selectedContexts.push(context);
|
|
13827
13841
|
}
|
|
13828
13842
|
}
|
|
13829
13843
|
else {
|
|
13830
|
-
//
|
|
13831
|
-
const
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
13836
|
-
|
|
13844
|
+
// At least one subcontext is selected
|
|
13845
|
+
const atLeastOneSubcontextSelected = (Object.values(value)
|
|
13846
|
+
.some((subcontextValue) => {
|
|
13847
|
+
return subcontextValue;
|
|
13848
|
+
}));
|
|
13849
|
+
if (atLeastOneSubcontextSelected) {
|
|
13850
|
+
selectedContexts.push(context);
|
|
13837
13851
|
}
|
|
13852
|
+
// Add all selected subcontexts
|
|
13853
|
+
Object.keys(value).forEach((subcontext) => {
|
|
13854
|
+
if (value[subcontext]) {
|
|
13855
|
+
selectedSubcontexts.push(subcontext);
|
|
13856
|
+
}
|
|
13857
|
+
});
|
|
13838
13858
|
}
|
|
13839
13859
|
});
|
|
13840
|
-
if
|
|
13841
|
-
|
|
13860
|
+
// Add context and subcontext conditions to the query if any are selected
|
|
13861
|
+
if (selectedContexts.length > 0) {
|
|
13862
|
+
query.context = { $in: selectedContexts };
|
|
13863
|
+
}
|
|
13864
|
+
if (selectedSubcontexts.length > 0) {
|
|
13865
|
+
query.subcontext = { $in: selectedSubcontexts };
|
|
13842
13866
|
}
|
|
13843
13867
|
/* -------------- Tag Filter -------------- */
|
|
13844
|
-
const { tagFilterState } = filters;
|
|
13845
13868
|
const selectedTags = Object.keys(tagFilterState).filter((tag) => { return tagFilterState[tag]; });
|
|
13846
13869
|
if (selectedTags.length > 0) {
|
|
13847
13870
|
query.tags = { $in: selectedTags };
|
|
13848
13871
|
}
|
|
13849
13872
|
/* --------- Action/Error Filter ---------- */
|
|
13850
|
-
const { actionErrorFilterState } = filters;
|
|
13851
13873
|
if (actionErrorFilterState.type) {
|
|
13852
13874
|
query.type = actionErrorFilterState.type;
|
|
13853
13875
|
}
|
|
13854
|
-
if (actionErrorFilterState.type ===
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13876
|
+
if (actionErrorFilterState.type === LogType$1.Error) {
|
|
13877
|
+
if (actionErrorFilterState.errorMessage) {
|
|
13878
|
+
// Add error message to the query.
|
|
13879
|
+
// $i is used for case-insensitive search, and $regex is used for partial matching
|
|
13880
|
+
query.errorMessage = {
|
|
13881
|
+
$regex: actionErrorFilterState.errorMessage,
|
|
13882
|
+
$options: 'i',
|
|
13883
|
+
};
|
|
13884
|
+
}
|
|
13885
|
+
if (actionErrorFilterState.errorCode) {
|
|
13886
|
+
query.errorCode = {
|
|
13887
|
+
$regex: actionErrorFilterState.errorCode,
|
|
13888
|
+
$options: 'i',
|
|
13889
|
+
};
|
|
13890
|
+
}
|
|
13859
13891
|
}
|
|
13860
|
-
if (actionErrorFilterState.type ===
|
|
13861
|
-
const selectedTargets = Object.keys(actionErrorFilterState.target)
|
|
13862
|
-
|
|
13892
|
+
if (actionErrorFilterState.type === LogType$1.Action) {
|
|
13893
|
+
const selectedTargets = (Object.keys(actionErrorFilterState.target)
|
|
13894
|
+
.filter((target) => {
|
|
13895
|
+
return actionErrorFilterState.target[target];
|
|
13896
|
+
}));
|
|
13897
|
+
const selectedActions = (Object.keys(actionErrorFilterState.action)
|
|
13898
|
+
.filter((action) => {
|
|
13899
|
+
return actionErrorFilterState.action[action];
|
|
13900
|
+
}));
|
|
13863
13901
|
if (selectedTargets.length > 0) {
|
|
13864
13902
|
query.target = { $in: selectedTargets };
|
|
13865
13903
|
}
|
|
@@ -13868,18 +13906,26 @@ const initServer = (opts) => {
|
|
|
13868
13906
|
}
|
|
13869
13907
|
}
|
|
13870
13908
|
/* ------------ Advanced Filter ----------- */
|
|
13871
|
-
const { advancedFilterState } = filters;
|
|
13872
13909
|
if (advancedFilterState.userFirstName) {
|
|
13873
|
-
query.userFirstName = {
|
|
13910
|
+
query.userFirstName = {
|
|
13911
|
+
$regex: advancedFilterState.userFirstName,
|
|
13912
|
+
$options: 'i',
|
|
13913
|
+
};
|
|
13874
13914
|
}
|
|
13875
13915
|
if (advancedFilterState.userLastName) {
|
|
13876
|
-
query.userLastName = {
|
|
13916
|
+
query.userLastName = {
|
|
13917
|
+
$regex: advancedFilterState.userLastName,
|
|
13918
|
+
$options: 'i',
|
|
13919
|
+
};
|
|
13877
13920
|
}
|
|
13878
13921
|
if (advancedFilterState.userEmail) {
|
|
13879
|
-
query.userEmail = {
|
|
13922
|
+
query.userEmail = {
|
|
13923
|
+
$regex: advancedFilterState.userEmail,
|
|
13924
|
+
$options: 'i',
|
|
13925
|
+
};
|
|
13880
13926
|
}
|
|
13881
13927
|
if (advancedFilterState.userId) {
|
|
13882
|
-
query.userId = parseInt(advancedFilterState.userId, 10);
|
|
13928
|
+
query.userId = Number.parseInt(advancedFilterState.userId, 10);
|
|
13883
13929
|
}
|
|
13884
13930
|
const roles = [];
|
|
13885
13931
|
if (advancedFilterState.includeLearners) {
|
|
@@ -13891,26 +13937,38 @@ const initServer = (opts) => {
|
|
|
13891
13937
|
if (advancedFilterState.includeAdmins) {
|
|
13892
13938
|
roles.push({ isAdmin: true });
|
|
13893
13939
|
}
|
|
13940
|
+
// If any roles are selected, add them to the query
|
|
13894
13941
|
if (roles.length > 0) {
|
|
13942
|
+
// The $or operator is used to match any of the roles
|
|
13943
|
+
// The $and operator is to ensure that other conditions in the query are met
|
|
13895
13944
|
query.$and = [{ $or: roles }];
|
|
13896
13945
|
}
|
|
13897
13946
|
if (advancedFilterState.courseId) {
|
|
13898
|
-
query.courseId = parseInt(advancedFilterState.courseId, 10);
|
|
13947
|
+
query.courseId = Number.parseInt(advancedFilterState.courseId, 10);
|
|
13899
13948
|
}
|
|
13900
13949
|
if (advancedFilterState.courseName) {
|
|
13901
|
-
query.courseName = {
|
|
13950
|
+
query.courseName = {
|
|
13951
|
+
$regex: advancedFilterState.courseName,
|
|
13952
|
+
$options: 'i',
|
|
13953
|
+
};
|
|
13902
13954
|
}
|
|
13903
13955
|
if (advancedFilterState.isMobile !== undefined) {
|
|
13904
|
-
query['device.isMobile'] = advancedFilterState.isMobile;
|
|
13956
|
+
query['device.isMobile'] = Boolean(advancedFilterState.isMobile);
|
|
13905
13957
|
}
|
|
13906
13958
|
if (advancedFilterState.source) {
|
|
13907
13959
|
query.source = advancedFilterState.source;
|
|
13908
13960
|
}
|
|
13909
13961
|
if (advancedFilterState.routePath) {
|
|
13910
|
-
query.routePath = {
|
|
13962
|
+
query.routePath = {
|
|
13963
|
+
$regex: advancedFilterState.routePath,
|
|
13964
|
+
$options: 'i',
|
|
13965
|
+
};
|
|
13911
13966
|
}
|
|
13912
13967
|
if (advancedFilterState.routeTemplate) {
|
|
13913
|
-
query.routeTemplate = {
|
|
13968
|
+
query.routeTemplate = {
|
|
13969
|
+
$regex: advancedFilterState.routeTemplate,
|
|
13970
|
+
$options: 'i',
|
|
13971
|
+
};
|
|
13914
13972
|
}
|
|
13915
13973
|
// Query for logs
|
|
13916
13974
|
const response = yield _logCollection.findPaged({
|