Cleanup and refactor (#4361)

* fix three panel layout height issue

* rename websocket/services to websocket/persistence, implement LeaveRoom

* cleanup

* add new line eof

* move route components from /components to /containers

* remove duplicate style

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2021-05-18 22:06:41 -05:00 committed by GitHub
parent 294229622d
commit 8db9475804
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 127 additions and 76 deletions

View file

@ -0,0 +1,3 @@
.log-results {
margin-bottom: 20px;
}

View file

@ -0,0 +1,122 @@
import React from "react";
import * as _ from "lodash";
import AppBar from "@material-ui/core/AppBar";
import Box from "@material-ui/core/Box";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Tab from "@material-ui/core/Tab";
import Tabs from "@material-ui/core/Tabs";
import Typography from "@material-ui/core/Typography";
import "./LogResults.css";
const LogResults = (props) => {
const { logs } = props;
const hasRoomLogs = logs.room && logs.room.length;
const hasGameLogs = logs.game && logs.game.length;
const hasChatLogs = logs.chat && logs.chat.length;
const [value, setValue] = React.useState(0);
const handleChange = (event, newValue) => {
setValue(newValue);
};
const headerCells = [
{
label: "Time"
},
{
label: "Sender Name"
},
{
label: "Sender IP"
},
{
label: "Message"
},
{
label: "Target ID"
},
{
label: "Target Name"
}
];
return (
<div>
<AppBar position="static">
<Tabs value={value} onChange={handleChange} aria-label="simple tabs example">
<Tab label={"Rooms" + (hasRoomLogs ? ` [${logs.room.length}]` : "")} {...a11yProps(0)} />
<Tab label={"Games" + (hasGameLogs ? ` [${logs.game.length}]` : "")} {...a11yProps(1)} />
<Tab label={"Chats" + (hasChatLogs ? ` [${logs.chat.length}]` : "")} {...a11yProps(2)} />
</Tabs>
</AppBar>
<TabPanel value={value} index={0}>
<Results logs={logs.room} headerCells={headerCells} />
</TabPanel>
<TabPanel value={value} index={1}>
<Results logs={logs.game} headerCells={headerCells} />
</TabPanel>
<TabPanel value={value} index={2}>
<Results logs={logs.chat} headerCells={headerCells} />
</TabPanel>
</div>
)
};
const a11yProps = index => {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`,
};
};
const TabPanel = ({ children, value, index, ...other }) => {
return (
<Typography
component="div"
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
<Box>{children}</Box>
</Typography>
);
};
const Results = ({headerCells, logs}) => (
<Paper className="log-results">
<Table size="small">
<TableHead>
<TableRow>
{ _.map(headerCells, ({ label }) => (
<TableCell key={label}>{label}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{ _.map(logs, ({ time, senderName, senderIp, message, targetId, targetName }, index) => (
<TableRow key={index}>
<TableCell>{time}</TableCell>
<TableCell>{senderName}</TableCell>
<TableCell>{senderIp}</TableCell>
<TableCell>{message}</TableCell>
<TableCell>{targetId}</TableCell>
<TableCell>{targetName}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
);
export default LogResults;

View file

@ -0,0 +1,14 @@
.moderator-logs {
height: 100%;
display: flex;
padding: 20px;
}
.moderator-logs__form {
width: 40%;
margin-right: 20px;
}
.moderator-logs__results {
width: 100%;
}

View file

@ -0,0 +1,99 @@
// eslint-disable-next-line
import React, { Component } from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import * as _ from "lodash";
import { ModeratorService } from "api";
import { AuthGuard, ModGuard} from "components";
import { SearchForm } from "forms";
import { ServerDispatch, ServerSelectors, ServerStateLogs } from "store";
import LogResults from "./LogResults";
import "./Logs.css";
class Logs extends Component<LogsTypes> {
MAXIMUM_RESULTS = 1000;
constructor(props) {
super(props);
this.onSubmit = this.onSubmit.bind(this);
}
componentWillUnmount() {
ServerDispatch.clearLogs();
}
onSubmit(fields) {
const trimmedFields: any = this.trimFields(fields);
const { userName, ipAddress, gameName, gameId, message, logLocation } = trimmedFields;
const required = _.filter({
userName, ipAddress, gameName, gameId, message
}, field => field);
if (logLocation) {
trimmedFields.logLocation = this.flattenLogLocations(logLocation);
}
trimmedFields.maximumResults = this.MAXIMUM_RESULTS;
if (_.size(required)) {
ModeratorService.viewLogHistory(trimmedFields);
} else {
// @TODO use yet-to-be-implemented banner/alert
}
}
private trimFields(fields) {
return _.reduce(fields, (obj, field, key) => {
if (typeof field === "string") {
const trimmed = _.trim(field);
if (!!trimmed) {
obj[key] = trimmed;
}
} else {
obj[key] = field;
}
return obj;
}, {});
}
private flattenLogLocations(logLocations) {
return _.reduce(logLocations, (arr, loc, key) => {
arr.push(key);
return arr;
}, [])
}
render() {
return (
<div className="moderator-logs overflow-scroll">
<AuthGuard />
<ModGuard />
<div className="moderator-logs__form">
<SearchForm onSubmit={this.onSubmit} />
</div>
<div className="moderator-logs__results">
<LogResults logs={this.props.logs} />
</div>
</div>
)
}
}
interface LogsTypes {
logs: ServerStateLogs
}
const mapStateToProps = state => ({
logs: ServerSelectors.getLogs(state)
});
export default withRouter(connect(mapStateToProps)(Logs));