Skip to content

Commit 5740c11

Browse files
bexsoftBenjamin Perez
andauthored
Fixed some details on audit logs page (#1156)
- Changed default port to 5005 due 5000 port is not available to use in new MacOS versions - Added an option to show full log information in a modal - Fixed issue with column selector dropdown & mui v5 - Fixed advanced filters table population - Changed date range selector picker for audit logs Signed-off-by: Benjamin Perez <[email protected]> Co-authored-by: Benjamin Perez <[email protected]>
1 parent 5f1e228 commit 5740c11

File tree

6 files changed

+204
-43
lines changed

6 files changed

+204
-43
lines changed

portal-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"websocket": "^1.0.31"
6262
},
6363
"scripts": {
64-
"start": "PORT=5000 react-app-rewired start",
64+
"start": "PORT=5005 react-app-rewired start",
6565
"build": "react-scripts build",
6666
"test": "react-scripts test",
6767
"eject": "react-scripts eject"

portal-ui/src/screens/Console/Common/FormComponents/DateRangeSelector/DateRangeSelector.tsx

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ interface IDateRangeSelector {
3131
setTimeStart: (date: any) => void;
3232
timeEnd: any;
3333
setTimeEnd: (date: any) => void;
34-
triggerSync: () => void;
34+
triggerSync?: () => void;
3535
}
3636

3737
const styles = (theme: Theme) =>
@@ -97,16 +97,18 @@ const DateRangeSelector = ({
9797
noInputIcon
9898
/>
9999
</div>
100-
<Button
101-
type="button"
102-
variant="contained"
103-
color="primary"
104-
onClick={triggerSync}
105-
endIcon={<SyncIcon />}
106-
className={classes.syncButton}
107-
>
108-
Sync
109-
</Button>
100+
{triggerSync && (
101+
<Button
102+
type="button"
103+
variant="contained"
104+
color="primary"
105+
onClick={triggerSync}
106+
endIcon={<SyncIcon />}
107+
className={classes.syncButton}
108+
>
109+
Sync
110+
</Button>
111+
)}
110112
</Grid>
111113
</Fragment>
112114
);

portal-ui/src/screens/Console/Common/TableWrapper/TableWrapper.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,6 @@ const styles = () =>
208208
right: 0,
209209
top: 0,
210210
},
211-
popoverContainer: {
212-
position: "relative",
213-
},
214211
popoverContent: {
215212
maxHeight: 250,
216213
overflowY: "auto",
@@ -573,7 +570,6 @@ const TableWrapper = ({
573570
horizontal: "left",
574571
}}
575572
onClose={closeColumnSelector}
576-
className={classes.popoverContainer}
577573
>
578574
<div className={classes.shownColumnsLabel}>Shown Columns</div>
579575
<div className={classes.popoverContent}>
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2021 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
import React, { Fragment } from "react";
18+
import get from "lodash/get";
19+
import { Button, Grid } from "@mui/material";
20+
import { Theme } from "@mui/material/styles";
21+
import createStyles from "@mui/styles/createStyles";
22+
import withStyles from "@mui/styles/withStyles";
23+
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
24+
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
25+
import { IReqInfoSearchResults } from "./types";
26+
import { LogSearchColumnLabels } from "./utils";
27+
28+
interface ILogSearchFullModal {
29+
modalOpen: boolean;
30+
logSearchElement: IReqInfoSearchResults;
31+
onClose: () => void;
32+
classes: any;
33+
}
34+
35+
const styles = (theme: Theme) =>
36+
createStyles({
37+
buttonContainer: {
38+
textAlign: "right",
39+
},
40+
pathLabel: {
41+
marginTop: 0,
42+
marginBottom: 32,
43+
},
44+
objectKeyCol: {
45+
fontWeight: 700,
46+
paddingRight: "10px",
47+
textAlign: "left",
48+
},
49+
...modalBasic,
50+
});
51+
52+
const LogSearchFullModal = ({
53+
modalOpen,
54+
logSearchElement,
55+
onClose,
56+
classes,
57+
}: ILogSearchFullModal) => {
58+
const jsonItems = Object.keys(logSearchElement);
59+
60+
return (
61+
<Fragment>
62+
<ModalWrapper
63+
modalOpen={modalOpen}
64+
title="Full Log Information"
65+
onClose={() => {
66+
onClose();
67+
}}
68+
>
69+
<Grid container>
70+
<Grid item xs={12}>
71+
<table>
72+
<tbody>
73+
{jsonItems.map((objectKey: string, index: number) => (
74+
<tr key={`logSearch-${index.toString()}`}>
75+
<th className={classes.objectKeyCol}>
76+
{get(LogSearchColumnLabels, objectKey, `${objectKey}`)}
77+
</th>
78+
<td>{get(logSearchElement, objectKey, "")}</td>
79+
</tr>
80+
))}
81+
</tbody>
82+
</table>
83+
</Grid>
84+
<Grid item xs={12} className={classes.buttonContainer}>
85+
<Button
86+
type="button"
87+
variant="contained"
88+
color="primary"
89+
onClick={onClose}
90+
>
91+
Close
92+
</Button>
93+
</Grid>
94+
</Grid>
95+
</ModalWrapper>
96+
</Fragment>
97+
);
98+
};
99+
100+
export default withStyles(styles)(LogSearchFullModal);

portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ import api from "../../../../common/api";
3838
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
3939
import FilterInputWrapper from "../../Common/FormComponents/FilterInputWrapper/FilterInputWrapper";
4040
import DateTimePickerWrapper from "../../Common/FormComponents/DateTimePickerWrapper/DateTimePickerWrapper";
41+
import LogSearchFullModal from "./LogSearchFullModal";
42+
import { LogSearchColumnLabels } from "./utils";
43+
import DateRangeSelector from "../../Common/FormComponents/DateRangeSelector/DateRangeSelector";
4144

4245
interface ILogSearchProps {
4346
classes: any;
@@ -154,6 +157,10 @@ const LogsSearchMain = ({
154157
]);
155158
const [nextPage, setNextPage] = useState<number>(0);
156159
const [alreadyFetching, setAlreadyFetching] = useState<boolean>(false);
160+
const [logSearchExtrasOpen, setLogSearchExtrasOpen] =
161+
useState<boolean>(false);
162+
const [selectedItem, setSelectedItem] =
163+
useState<IReqInfoSearchResults | null>(null);
157164

158165
let recordsResp: any = null;
159166
const logSearchEnabled = features && features.includes("log-search");
@@ -188,11 +195,10 @@ const LogsSearchMain = ({
188195
)
189196
.then((res: ISearchResponse) => {
190197
const fetchedResults = res.results || [];
191-
const newResultSet = [...records, ...fetchedResults];
192198

193199
setLoading(false);
194200
setAlreadyFetching(false);
195-
setRecords(newResultSet);
201+
setRecords(fetchedResults);
196202
setNextPage(nextPage + 1);
197203

198204
if (recordsResp !== null) {
@@ -218,7 +224,6 @@ const LogsSearchMain = ({
218224
sortOrder,
219225
timeStart,
220226
timeEnd,
221-
records,
222227
recordsResp,
223228
setErrorSnackMessage,
224229
]);
@@ -262,27 +267,36 @@ const LogsSearchMain = ({
262267
});
263268
};
264269

270+
const openExtraInformation = (item: IReqInfoSearchResults) => {
271+
setSelectedItem(item);
272+
setLogSearchExtrasOpen(true);
273+
};
274+
275+
const closeViewExtraInformation = () => {
276+
setSelectedItem(null);
277+
setLogSearchExtrasOpen(false);
278+
};
279+
265280
return (
266281
<Fragment>
282+
{logSearchExtrasOpen && selectedItem !== null && (
283+
<LogSearchFullModal
284+
logSearchElement={selectedItem}
285+
modalOpen={logSearchExtrasOpen}
286+
onClose={closeViewExtraInformation}
287+
/>
288+
)}
267289
<Grid container className={classes.logsSubContainer}>
268290
<Grid
269291
item
270292
xs={12}
271293
className={`${classes.actionsTray} ${classes.timeContainers}`}
272294
>
273-
<span className={classes.label}>Start Time</span>
274-
<DateTimePickerWrapper
275-
value={timeStart}
276-
onChange={setTimeStart}
277-
forSearchBlock
278-
id="stTime"
279-
/>
280-
<span className={classes.label}>End Time</span>
281-
<DateTimePickerWrapper
282-
value={timeEnd}
283-
onChange={setTimeEnd}
284-
forSearchBlock
285-
id="endTime"
295+
<DateRangeSelector
296+
setTimeEnd={setTimeEnd}
297+
setTimeStart={setTimeStart}
298+
timeEnd={timeEnd}
299+
timeStart={timeStart}
286300
/>
287301
</Grid>
288302
<Grid item xs={12} className={`${classes.advancedLabelContainer}`}>
@@ -376,15 +390,28 @@ const LogsSearchMain = ({
376390
<Grid item xs={12}>
377391
<TableWrapper
378392
columns={[
379-
{ label: "Timestamp", elementKey: "time", enableSort: true },
380-
{ label: "API Name", elementKey: "api_name" },
381-
{ label: "Bucket", elementKey: "bucket" },
382-
{ label: "Object", elementKey: "object" },
383-
{ label: "Remote Host", elementKey: "remote_host" },
384-
{ label: "Request ID", elementKey: "request_id" },
385-
{ label: "User Agent", elementKey: "user_agent" },
386393
{
387-
label: "Response Status",
394+
label: LogSearchColumnLabels.time,
395+
elementKey: "time",
396+
enableSort: true,
397+
},
398+
{ label: LogSearchColumnLabels.api_name, elementKey: "api_name" },
399+
{ label: LogSearchColumnLabels.bucket, elementKey: "bucket" },
400+
{ label: LogSearchColumnLabels.object, elementKey: "object" },
401+
{
402+
label: LogSearchColumnLabels.remote_host,
403+
elementKey: "remote_host",
404+
},
405+
{
406+
label: LogSearchColumnLabels.request_id,
407+
elementKey: "request_id",
408+
},
409+
{
410+
label: LogSearchColumnLabels.user_agent,
411+
elementKey: "user_agent",
412+
},
413+
{
414+
label: LogSearchColumnLabels.response_status,
388415
elementKey: "response_status",
389416
renderFunction: (element) => (
390417
<Fragment>
@@ -396,17 +423,17 @@ const LogsSearchMain = ({
396423
renderFullObject: true,
397424
},
398425
{
399-
label: "Request Content Length",
426+
label: LogSearchColumnLabels.request_content_length,
400427
elementKey: "request_content_length",
401428
renderFunction: niceBytes,
402429
},
403430
{
404-
label: "Response Content Length",
431+
label: LogSearchColumnLabels.response_content_length,
405432
elementKey: "response_content_length",
406433
renderFunction: niceBytes,
407434
},
408435
{
409-
label: "Time to Response NS",
436+
label: LogSearchColumnLabels.time_to_response_ns,
410437
elementKey: "time_to_response_ns",
411438
renderFunction: nsToSeconds,
412439
contentTextAlign: "right",
@@ -432,6 +459,12 @@ const LogsSearchMain = ({
432459
recordsCount: 1000000,
433460
loadMoreRecords: loadMoreRecords,
434461
}}
462+
itemActions={[
463+
{
464+
type: "view",
465+
onClick: openExtraInformation,
466+
},
467+
]}
435468
textSelectable
436469
/>
437470
</Grid>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2021 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
export const LogSearchColumnLabels = {
18+
time: "Timestamp",
19+
api_name: "API Name",
20+
bucket: "Bucket",
21+
object: "Object",
22+
remote_host: "Remote Host",
23+
request_id: "Request ID",
24+
user_agent: "User Agent",
25+
response_status: "Response Status",
26+
response_status_code: "Response Status Code",
27+
request_content_length: "Request Content Length",
28+
response_content_length: "Response Content Length",
29+
time_to_response_ns: "Time to Response NS",
30+
};

0 commit comments

Comments
 (0)