Structure change (#4220)

* Structure change

* Remove duplicate folders from previous structure

* Cleanup websocket protocol

* Updating from based off PR

* Fixup - remove wrong files during conflict and get the websocket working

* renaming tsx to ts

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Joseph Chamish 2021-01-20 18:50:18 -05:00 committed by GitHub
parent a0deb73df6
commit 1ddc9cc929
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
123 changed files with 424 additions and 228 deletions

View file

@ -0,0 +1,30 @@
.games {
}
.games-header,
.game {
display: flex;
padding: 10px;
border-bottom: 1px solid black;
}
.games-header__cell {
max-width: 200px;
}
.games-header__label,
.game__detail {
width: 10%;
flex-grow: 0;
}
.games-header__label.description,
.game__detail.description {
width: 20%;
flex-grow: 1;
}
.games-header__label.creator,
.game__detail.creator {
width: 20%;
}

View file

@ -0,0 +1,143 @@
// eslint-disable-next-line
import React, { Component } from "react";
import { connect } from "react-redux";
import * as _ from "lodash";
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 TableSortLabel from "@material-ui/core/TableSortLabel";
import Tooltip from "@material-ui/core/Tooltip";
// import { RoomsService } from "AppShell/common/services";
import { SortUtil, RoomsDispatch, RoomsSelectors } from "store";
import { UserDisplay } from "components";
import "./Games.css";
// @TODO run interval to update timeSinceCreated
class Games extends Component<GamesProps> {
private headerCells = [
{
label: "Age",
field: "startTime"
},
{
label: "Description",
field: "description"
},
{
label: "Creator",
field: "creatorInfo.name"
},
{
label: "Type",
field: "gameType"
},
{
label: "Restrictions",
// field: "?"
},
{
label: "Players",
// field: ["maxPlayers", "playerCount"]
},
{
label: "Spectators",
field: "spectatorsCount"
},
];
handleSort(sortByField) {
const { room: { roomId }, sortBy } = this.props;
const { field, order } = SortUtil.toggleSortBy(sortByField, sortBy);
RoomsDispatch.sortGames(roomId, field, order);
}
private isUnavailableGame({ started, maxPlayers, playerCount }) {
return !started && playerCount < maxPlayers;
}
private isPasswordProtectedGame({ withPassword }) {
return !withPassword;
}
private isBuddiesOnlyGame({ onlyBuddies }) {
return !onlyBuddies;
}
render() {
const { room, sortBy } = this.props;
const games = room.gameList.filter(game => (
this.isUnavailableGame(game) &&
this.isPasswordProtectedGame(game) &&
this.isBuddiesOnlyGame(game)
));
return (
<div className="games">
<Table size="small">
<TableHead>
<TableRow>
{ _.map(this.headerCells, ({ label, field }) => {
const active = field === sortBy.field;
const order = sortBy.order.toLowerCase();
const sortDirection = active ? order : false;
return (
<TableCell sortDirection={sortDirection} key={label}>
{!field ? label : (
<TableSortLabel
active={active}
direction={order}
onClick={() => this.handleSort(field)}
>
{label}
</TableSortLabel>
)}
</TableCell>
);
})}
</TableRow>
</TableHead>
<TableBody>
{ _.map(games, ({ description, gameId, gameType, creatorInfo, maxPlayers, playerCount, spectatorsCount, startTime }) => (
<TableRow key={gameId}>
<TableCell className="games-header__cell single-line-ellipsis">{startTime}</TableCell>
<TableCell className="games-header__cell">
<Tooltip title={description} placement="bottom-start" enterDelay={500}>
<div className="single-line-ellipsis">
{description}
</div>
</Tooltip>
</TableCell>
<TableCell className="games-header__cell">
<UserDisplay user={ creatorInfo } />
</TableCell>
<TableCell className="games-header__cell single-line-ellipsis">{gameType}</TableCell>
<TableCell className="games-header__cell single-line-ellipsis">?</TableCell>
<TableCell className="games-header__cell single-line-ellipsis">{`${playerCount}/${maxPlayers}`}</TableCell>
<TableCell className="games-header__cell single-line-ellipsis">{spectatorsCount}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
}
interface GamesProps {
room: any;
sortBy: any;
}
const mapStateToProps = state => ({
sortBy: RoomsSelectors.getSortGamesBy(state)
});
export default connect(mapStateToProps)(Games);

View file

@ -0,0 +1,17 @@
.messages {
height: 100%;
width: 100%;
padding: 10px;
font-size: 12px;
line-height: 1.3;
}
.message {
padding: 5px 0;
margin: 2px 0;
border-bottom: 1px dashed rgba(0, 0, 0, 0.25);
}
.message:last-of-type {
border: 0;
}

View file

@ -0,0 +1,31 @@
// eslint-disable-next-line
import React from "react";
import "./Messages.css";
const Messages = ({ messages }) => (
<div className="messages">
{
messages && messages.map(({ message, messageType, timeOf, timeReceived }) => (
<div className="message" key={timeReceived}>
<div className="message__detail">{ParsedMessage(message)}</div>
</div>
) )
}
</div>
);
const ParsedMessage = (message) => {
const name = message.match("^[^:]+:");
if (name && name.length) {
message = message.slice(name[0].length, message.length);
}
return <div>
<strong>{name}</strong>
{message}
</div>
};
export default Messages;

View file

@ -0,0 +1,39 @@
.room-view,
.room-view__games,
.room-view__messages,
.room-view__messages-content,
.room-view__side {
height: 100%;
}
.room-view__messages,
.room-view__side {
display: flex;
flex-direction: column;
}
.room-view__messages-sayMessage {
width: 100%;
margin: 10px auto 2px;
}
.room-view__side-label {
position: sticky;
top: 0;
padding: 10px;
background: white;
z-index: 1;
}
.room-view__side-list,
.room-view__side-list .room-view__side-list__item {
height: 100%;
}
.room-view__side-list .room-view__side-list__item {
padding: 0;
}
.room-view__side-list .room-view__side-list__item .user-display__details {
padding: 0 10px;
}

View file

@ -0,0 +1,99 @@
// eslint-disable-next-line
import React, { Component } from "react";
import { connect } from "react-redux";
import { withRouter /*, RouteComponentProps */ } from "react-router-dom";
import ListItem from "@material-ui/core/ListItem";
import Paper from "@material-ui/core/Paper";
import { RoomsStateMessages, RoomsStateRooms, RoomsSelectors } from "store";
import { RoomsService } from "websocket";
import { ScrollToBottomOnChanges, ThreePaneLayout, UserDisplay, VirtualList, AuthGuard} from "components";
import Games from "./Games";
import Messages from "./Messages";
import SayMessage from "./SayMessage";
import "./Room.css";
// @TODO (3)
class Room extends Component<any> {
constructor(props) {
super(props);
this.handleRoomSay = this.handleRoomSay.bind(this);
}
handleRoomSay({ message }) {
if (message) {
const { roomId } = this.props.match.params;
RoomsService.roomSay(roomId, message);
}
}
render() {
const { match, rooms} = this.props;
const { roomId } = match.params;
const room = rooms[roomId];
const messages = this.props.messages[roomId];
const users = room.userList;
return (
<div className="room-view">
<AuthGuard />
<ThreePaneLayout
fixedHeight
top={(
<Paper className="room-view__games overflow-scroll">
<Games room={room} />
</Paper>
)}
bottom={(
<div className="room-view__messages">
<Paper className="room-view__messages-content overflow-scroll">
<ScrollToBottomOnChanges changes={messages} content={(
<Messages messages={messages} />
)} />
</Paper>
<Paper className="room-view__messages-sayMessage">
<SayMessage onSubmit={this.handleRoomSay} />
</Paper>
</div>
)}
side={(
<Paper className="room-view__side overflow-scroll">
<div className="room-view__side-label">
Users in this room: {users.length}
</div>
<VirtualList
className="room-view__side-list"
itemKey={(index, data) => users[index].name }
items={ users.map(user => (
<ListItem button className="room-view__side-list__item">
<UserDisplay user={user} />
</ListItem>
) ) }
/>
</Paper>
)}
/>
</div>
);
}
}
interface RoomProps {
messages: RoomsStateMessages;
rooms: RoomsStateRooms;
}
const mapStateToProps = state => ({
messages: RoomsSelectors.getMessages(state),
rooms: RoomsSelectors.getRooms(state)
});
export default withRouter(connect(mapStateToProps)(Room));

View file

@ -0,0 +1,18 @@
// eslint-disable-next-line
import React from "react";
import { connect } from "react-redux";
import { Form, reduxForm } from "redux-form"
import { InputAction } from 'components';
const SayMessage = ({ handleSubmit }) => (
<Form onSubmit={handleSubmit}>
<InputAction action="Say" label="Chat" name="message" />
</Form>
);
const propsMap = {
form: "sayMessage"
};
export default connect()(reduxForm(propsMap)(SayMessage));