system log + frontend update
This commit is contained in:
@@ -12,6 +12,7 @@ import './res/adminlte.min.css';
|
||||
|
||||
// views
|
||||
import View404 from "./views/404";
|
||||
import LogView from "./views/log-view";
|
||||
const Overview = lazy(() => import('./views/overview'));
|
||||
const UserListView = lazy(() => import('./views/user/user-list'));
|
||||
const UserEditView = lazy(() => import('./views/user/user-edit'));
|
||||
@@ -70,6 +71,7 @@ export default function AdminDashboard(props) {
|
||||
<Route path={"/admin/user/:userId"} element={<UserEditView {...controlObj} />}/>
|
||||
<Route path={"/admin/groups"} element={<GroupListView {...controlObj} />}/>
|
||||
<Route path={"/admin/group/:groupId"} element={<EditGroupView {...controlObj} />}/>
|
||||
<Route path={"/admin/logs"} element={<LogView {...controlObj} />}/>
|
||||
<Route path={"*"} element={<View404 />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
|
||||
142
react/admin-panel/src/views/log-view.js
Normal file
142
react/admin-panel/src/views/log-view.js
Normal file
@@ -0,0 +1,142 @@
|
||||
import {useCallback, useContext, useEffect, useState} from "react";
|
||||
import {LocaleContext} from "shared/locale";
|
||||
import {Link, useNavigate} from "react-router-dom";
|
||||
import usePagination from "shared/hooks/pagination";
|
||||
import {DataColumn, DataTable, DateTimeColumn, NumericColumn, StringColumn} from "shared/elements/data-table";
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import {Chip, TextField} from "@mui/material";
|
||||
import {DateTimePicker} from "@mui/x-date-pickers";
|
||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import {API_DATETIME_FORMAT_DAYJS} from "shared/constants";
|
||||
|
||||
export default function LogView(props) {
|
||||
|
||||
//
|
||||
const LOG_LEVELS = ['debug', 'info', 'warning', 'error', 'severe'];
|
||||
|
||||
const api = props.api;
|
||||
const showDialog = props.showDialog;
|
||||
const {translate: L, requestModules, currentLocale} = useContext(LocaleContext);
|
||||
const navigate = useNavigate();
|
||||
const pagination = usePagination();
|
||||
const [logEntries, setLogEntries] = useState([]);
|
||||
|
||||
// filters
|
||||
const [logLevel, setLogLevel] = useState(2);
|
||||
const [timestamp, setTimestamp] = useState(null);
|
||||
const [query, setQuery] = useState("");
|
||||
const [forceReload, setForceReload] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
requestModules(props.api, ["general"], currentLocale).then(data => {
|
||||
if (!data.success) {
|
||||
props.showDialog("Error fetching translations: " + data.msg);
|
||||
}
|
||||
});
|
||||
}, [currentLocale]);
|
||||
|
||||
const onFetchLogs = useCallback((page, count, orderBy, sortOrder) => {
|
||||
api.fetchLogEntries(page, count, orderBy, sortOrder, LOG_LEVELS[logLevel], timestamp?.format(API_DATETIME_FORMAT_DAYJS), query).then((res) => {
|
||||
if (res.success) {
|
||||
setLogEntries(res.logs);
|
||||
pagination.update(res.pagination);
|
||||
} else {
|
||||
showDialog(res.msg, "Error fetching log entries");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}, [api, showDialog, logLevel, timestamp, query]);
|
||||
|
||||
useEffect(() => {
|
||||
// TODO: wait for user to finish typing before force reloading
|
||||
setForceReload(forceReload + 1);
|
||||
}, [query, timestamp, logLevel]);
|
||||
|
||||
const messageColumn = (() => {
|
||||
let column = new DataColumn(L("message"), "message");
|
||||
column.renderData = (L, entry) => {
|
||||
return <pre>{entry.message}</pre>
|
||||
}
|
||||
return column;
|
||||
})();
|
||||
|
||||
const columnDefinitions = [
|
||||
new NumericColumn(L("general.id"), "id"),
|
||||
new StringColumn(L("module"), "module"),
|
||||
new StringColumn(L("severity"), "severity"),
|
||||
new DateTimeColumn(L("timestamp"), "timestamp"),
|
||||
messageColumn,
|
||||
];
|
||||
|
||||
return <>
|
||||
<div className={"content-header"}>
|
||||
<div className={"container-fluid"}>
|
||||
<div className={"row mb-2"}>
|
||||
<div className={"col-sm-6"}>
|
||||
<h1 className={"m-0 text-dark"}>System Log</h1>
|
||||
</div>
|
||||
<div className={"col-sm-6"}>
|
||||
<ol className={"breadcrumb float-sm-right"}>
|
||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||
<li className="breadcrumb-item active">System Log</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={"content overflow-auto"}>
|
||||
<div className={"row p-2"}>
|
||||
<div className={"col-2"}>
|
||||
<div className={"form-group"}>
|
||||
<label>{L("log.severity")}</label>
|
||||
<select className={"form-control"} value={logLevel} onChange={e => setLogLevel(parseInt(e.target.value))}>
|
||||
{LOG_LEVELS.map((value, index) =>
|
||||
<option key={"option-" + value} value={index}>{value}</option>)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className={"col-4"}>
|
||||
<div className={"form-group"}>
|
||||
<label>{L("log.timestamp")}</label>
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<DateTimePicker className={"form-control"}
|
||||
label="Select date time to filter..."
|
||||
value={timestamp ? dayjs(timestamp) : null}
|
||||
onChange={(newValue) => {console.log(newValue);
|
||||
setTimestamp(newValue)
|
||||
}}
|
||||
slotProps={{ textField: { size: 'small' } }}
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
</div>
|
||||
</div>
|
||||
<div className={"col-6"}>
|
||||
<div className={"form-group"}>
|
||||
<label>{L("log.query")}</label>
|
||||
<TextField
|
||||
className={"form-control"}
|
||||
placeholder={L("log.search_query") + "…"}
|
||||
value={query}
|
||||
onChange={e => setQuery(e.target.value)}
|
||||
variant={"outlined"}
|
||||
size={"small"}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={"container-fluid"}>
|
||||
<DataTable
|
||||
data={logEntries}
|
||||
pagination={pagination}
|
||||
className={"table table-striped"}
|
||||
fetchData={onFetchLogs}
|
||||
forceReload={forceReload}
|
||||
defaultSortColumn={3}
|
||||
defaultSortOrder={"desc"}
|
||||
placeholder={"No log entries to display"}
|
||||
columns={columnDefinitions} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
Reference in New Issue
Block a user