mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-12 00:54:53 -07:00
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:
parent
294229622d
commit
8db9475804
47 changed files with 127 additions and 76 deletions
3
webclient/src/containers/Logs/LogResults.css
Normal file
3
webclient/src/containers/Logs/LogResults.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.log-results {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
122
webclient/src/containers/Logs/LogResults.tsx
Normal file
122
webclient/src/containers/Logs/LogResults.tsx
Normal 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;
|
||||
14
webclient/src/containers/Logs/Logs.css
Normal file
14
webclient/src/containers/Logs/Logs.css
Normal 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%;
|
||||
}
|
||||
99
webclient/src/containers/Logs/Logs.tsx
Normal file
99
webclient/src/containers/Logs/Logs.tsx
Normal 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));
|
||||
Loading…
Add table
Add a link
Reference in a new issue