aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/web/src/gui/pages
diff options
context:
space:
mode:
authornotoraptor <stevenbocco@gmail.com>2019-07-25 10:59:36 -0400
committerPhilip Paquette <pcpaquette@gmail.com>2019-07-25 11:15:59 -0400
commit48ee1a065debde5027fc17e49144d348258dc5e4 (patch)
treeb85be5b31a61ad911a89789c2089eaf7852ad4d9 /diplomacy/web/src/gui/pages
parent09f9589bfa1a9e19805c2cc7dc58cad4da93f17f (diff)
[Web] Added game creation interface
- Replaced fancybox with react-confirm-alert + dialog box - Removed unused code - Default map can be selected with 1-click - Added ability to select map variants
Diffstat (limited to 'diplomacy/web/src/gui/pages')
-rw-r--r--diplomacy/web/src/gui/pages/content_game.jsx74
-rw-r--r--diplomacy/web/src/gui/pages/content_games.jsx53
-rw-r--r--diplomacy/web/src/gui/pages/page.jsx33
3 files changed, 70 insertions, 90 deletions
diff --git a/diplomacy/web/src/gui/pages/content_game.jsx b/diplomacy/web/src/gui/pages/content_game.jsx
index f37bdca..457d901 100644
--- a/diplomacy/web/src/gui/pages/content_game.jsx
+++ b/diplomacy/web/src/gui/pages/content_game.jsx
@@ -33,7 +33,6 @@ import {STRINGS} from "../../diplomacy/utils/strings";
import {Diplog} from "../../diplomacy/utils/diplog";
import {Table} from "../components/table";
import {PowerView} from "../utils/power_view";
-import {FancyBox} from "../components/fancybox";
import {DipStorage} from "../utils/dipStorage";
import Helmet from 'react-helmet';
import {Navigation} from "../components/navigation";
@@ -116,14 +115,11 @@ export class ContentGame extends React.Component {
orders: orders, // {power name => {loc => {local: bool, order: str}}}
power: null,
orderBuildingType: null,
- orderBuildingPath: [],
- fancy_title: null,
- fancy_function: null,
- on_fancy_close: null,
+ orderBuildingPath: []
};
// Bind some class methods to this instance.
- this.closeFancyBox = this.closeFancyBox.bind(this);
+ this.clearOrderBuildingPath = this.clearOrderBuildingPath.bind(this);
this.displayFirstPastPhase = this.displayFirstPastPhase.bind(this);
this.displayLastPastPhase = this.displayLastPastPhase.bind(this);
this.displayLocationOrders = this.displayLocationOrders.bind(this);
@@ -202,11 +198,8 @@ export class ContentGame extends React.Component {
return this.context;
}
- closeFancyBox() {
+ clearOrderBuildingPath() {
this.setState({
- fancy_title: null,
- fancy_function: null,
- on_fancy_close: null,
orderBuildingPath: []
});
}
@@ -220,11 +213,6 @@ export class ContentGame extends React.Component {
powerName, orderType, orderPath, location,
this.onOrderBuilding, this.onOrderBuilt, this.getPage().error
);
- this.setState({
- fancy_title: null,
- fancy_function: null,
- on_fancy_close: null
- });
}
setSelectedVia(moveType, powerName, orderPath, location) {
@@ -234,33 +222,35 @@ export class ContentGame extends React.Component {
powerName, moveType, orderPath, location,
this.onOrderBuilding, this.onOrderBuilt, this.getPage().error
);
- this.setState({
- fancy_title: null,
- fancy_function: null,
- on_fancy_close: null
- });
}
onSelectLocation(possibleLocations, powerName, orderType, orderPath) {
- const title = `Select location to continue building order: ${orderPath.join(' ')} ... (press ESC or close button to cancel building)`;
- const func = () => (<SelectLocationForm locations={possibleLocations}
- onSelect={(location) => this.setSelectedLocation(location, powerName, orderType, orderPath)}/>);
- this.setState({
- fancy_title: title,
- fancy_function: func,
- on_fancy_close: this.closeFancyBox
- });
+ this.getPage().dialog(onClose => (
+ <SelectLocationForm path={orderPath}
+ locations={possibleLocations}
+ onSelect={(location) => {
+ this.setSelectedLocation(location, powerName, orderType, orderPath);
+ onClose();
+ }}
+ onClose={() => {
+ this.clearOrderBuildingPath();
+ onClose();
+ }}/>
+ ));
}
onSelectVia(location, powerName, orderPath) {
- const title = `Select move type for move order: ${orderPath.join(' ')}`;
- const func = () => (
- <SelectViaForm onSelect={(moveType) => this.setSelectedVia(moveType, powerName, orderPath, location)}/>);
- this.setState({
- fancy_title: title,
- fancy_function: func,
- on_fancy_close: this.closeFancyBox
- });
+ this.getPage().dialog(onClose => (
+ <SelectViaForm path={orderPath}
+ onSelect={(moveType) => {
+ this.setSelectedVia(moveType, powerName, orderPath, location);
+ onClose();
+ }}
+ onClose={() => {
+ this.clearOrderBuildingPath();
+ onClose();
+ }}/>
+ ));
}
// ]
@@ -682,9 +672,6 @@ export class ContentGame extends React.Component {
onOrderBuilt(powerName, orderString) {
const state = Object.assign({}, this.state);
state.orderBuildingPath = [];
- state.fancy_title = null;
- state.fancy_function = null;
- state.on_fancy_close = null;
if (!orderString) {
Diplog.warn('No order built.');
this.setState(state);
@@ -712,9 +699,6 @@ export class ContentGame extends React.Component {
this.setState({
orderBuildingType: form.order_type,
orderBuildingPath: [],
- fancy_title: null,
- fancy_function: null,
- on_fancy_close: null
});
}
@@ -1162,7 +1146,7 @@ export class ContentGame extends React.Component {
const engine = this.props.data;
const title = ContentGame.gameTitle(engine);
const navigation = [
- ['Help', () => page.loadFancyBox('Help', () => <Help/>)],
+ ['Help', () => page.dialog(onClose => <Help onClose={onClose}/>)],
['Load a game from disk', page.loadGameFromDisk],
['Save game to disk', () => saveGameToDisk(engine, page.error)],
[`${UTILS.html.UNICODE_SMALL_LEFT_ARROW} Games`, () => page.loadGames()],
@@ -1292,10 +1276,6 @@ export class ContentGame extends React.Component {
currentTabOrderCreation
)) || ''}
</Tabs>
- {this.state.fancy_title && (
- <FancyBox title={this.state.fancy_title} onClose={this.state.on_fancy_close}>
- {this.state.fancy_function()}
- </FancyBox>)}
</main>
);
}
diff --git a/diplomacy/web/src/gui/pages/content_games.jsx b/diplomacy/web/src/gui/pages/content_games.jsx
index 31bd1af..5250f03 100644
--- a/diplomacy/web/src/gui/pages/content_games.jsx
+++ b/diplomacy/web/src/gui/pages/content_games.jsx
@@ -18,15 +18,15 @@ import React from "react";
import {Tabs} from "../components/tabs";
import {Table} from "../components/table";
import {FindForm} from "../forms/find_form";
-import {CreateForm} from "../forms/create_form";
import {InlineGameView} from "../utils/inline_game_view";
-import {STRINGS} from "../../diplomacy/utils/strings";
import {Helmet} from "react-helmet";
import {Navigation} from "../components/navigation";
import {PageContext} from "../components/page_context";
import {ContentGame} from "./content_game";
import PropTypes from 'prop-types';
import {Tab} from "../components/tab";
+import {GameCreationWizard} from "../wizards/gameCreation/gameCreationWizard";
+import {Diplog} from "../../diplomacy/utils/diplog";
const TABLE_LOCAL_GAMES = {
game_id: ['Game ID', 0],
@@ -71,23 +71,6 @@ export class ContentGames extends React.Component {
}
onCreate(form) {
- for (let key of Object.keys(form)) {
- if (form[key] === '')
- form[key] = null;
- }
- if (form.n_controls !== null)
- form.n_controls = parseInt(form.n_controls, 10);
- if (form.deadline !== null)
- form.deadline = parseInt(form.deadline, 10);
- form.rules = ['POWER_CHOICE'];
- for (let rule of STRINGS.PUBLIC_RULES) {
- const rule_id = `rule_${rule.toLowerCase()}`;
- if (form.hasOwnProperty(rule_id)) {
- if (form[rule_id])
- form.rules.push(rule);
- delete form[rule_id];
- }
- }
let networkGame = null;
this.getPage().channel.createGame(form)
.then((game) => {
@@ -116,6 +99,28 @@ export class ContentGames extends React.Component {
return new InlineGameView(this.getPage(), gameData);
}
+ gameCreationButton() {
+ return (
+ <button type="button"
+ className="btn btn-danger btn-sm mx-0 mx-sm-4"
+ onClick={() => this.getPage().dialog(onClose => (
+ <GameCreationWizard availableMaps={this.getPage().availableMaps}
+ onCancel={onClose}
+ username={this.getPage().channel.username}
+ onSubmit={(form) => {
+ onClose();
+ Diplog.info(`Creating game:`);
+ for (let entry of Object.entries(form)) {
+ Diplog.info(`${entry[0]}: ${entry[1] ? entry[1].toString() : entry[1]}`);
+ }
+ this.onCreate(form);
+ }}/>
+ ))}>
+ <strong>create a game</strong>
+ </button>
+ );
+ }
+
render() {
const title = 'Games';
const page = this.getPage();
@@ -133,14 +138,10 @@ export class ContentGames extends React.Component {
<Helmet>
<title>{title} | Diplomacy</title>
</Helmet>
- <Navigation title={title} username={page.channel.username} navigation={navigation}/>
- <Tabs menu={['create', 'find', 'my-games']} titles={['Create', 'Find', 'My Games']}
+ <Navigation title={title} afterTitle={this.gameCreationButton()}
+ username={page.channel.username} navigation={navigation}/>
+ <Tabs menu={['find', 'my-games']} titles={['Find', 'My Games']}
onChange={this.changeTab} active={tab}>
- {tab === 'create' ? (
- <Tab id="tab-games-create" display={true}>
- <CreateForm onSubmit={this.onCreate}/>
- </Tab>
- ) : ''}
{tab === 'find' ? (
<Tab id="tab-games-find" display={true}>
<FindForm onSubmit={this.onFind}/>
diff --git a/diplomacy/web/src/gui/pages/page.jsx b/diplomacy/web/src/gui/pages/page.jsx
index cd36f6c..a9ff9ac 100644
--- a/diplomacy/web/src/gui/pages/page.jsx
+++ b/diplomacy/web/src/gui/pages/page.jsx
@@ -20,12 +20,13 @@ import React from "react";
import {ContentConnection} from "./content_connection";
import {UTILS} from "../../diplomacy/utils/utils";
import {Diplog} from "../../diplomacy/utils/diplog";
-import {FancyBox} from "../components/fancybox";
import {DipStorage} from "../utils/dipStorage";
import {PageContext} from "../components/page_context";
import {ContentGames} from "./content_games";
import {loadGameFromDisk} from "../utils/load_game_from_disk";
import {ContentGame} from "./content_game";
+import {confirmAlert} from 'react-confirm-alert';
+import 'react-confirm-alert/src/react-confirm-alert.css';
export class Page extends React.Component {
@@ -35,9 +36,6 @@ export class Page extends React.Component {
this.channel = null;
this.availableMaps = null;
this.state = {
- // fancybox,
- fancyTitle: null,
- onFancyBox: null,
// Page messages
error: null,
info: null,
@@ -54,7 +52,6 @@ export class Page extends React.Component {
this.success = this.success.bind(this);
this.logout = this.logout.bind(this);
this.loadGameFromDisk = this.loadGameFromDisk.bind(this);
- this.unloadFancyBox = this.unloadFancyBox.bind(this);
this._post_remove = this._post_remove.bind(this);
this._add_to_my_games = this._add_to_my_games.bind(this);
this._remove_from_my_games = this._remove_from_my_games.bind(this);
@@ -80,14 +77,22 @@ export class Page extends React.Component {
this.__disconnect(error);
}
- //// Methods to load a global fancybox.
+ /**
+ * @callback OnClose
+ */
- loadFancyBox(title, callback) {
- this.setState({fancyTitle: title, onFancyBox: callback});
- }
+ /**
+ * @callback DialogBuilder
+ * @param {OnClose} onClose
+ */
- unloadFancyBox() {
- this.setState({fancyTitle: null, onFancyBox: null});
+ /**
+ * open a dialog box
+ * @param {DialogBuilder} builder - a callback to generate dialog GUI. Will be executed with a `onClose` callback
+ * parameter to call when dialog must be closed: `builder(onClose)`.
+ */
+ dialog(builder) {
+ confirmAlert({customUI: ({onClose}) => builder(onClose)});
}
//// Methods to load a page.
@@ -275,7 +280,6 @@ export class Page extends React.Component {
}
}
-
disconnectGame(gameID) {
const game = this.getGame(gameID);
if (game) {
@@ -363,11 +367,6 @@ export class Page extends React.Component {
</div>
</div>
{this.state.body || Page.defaultPage()}
- {this.state.onFancyBox && (
- <FancyBox title={this.state.fancyTitle} onClose={this.unloadFancyBox}>
- {this.state.onFancyBox()}
- </FancyBox>
- )}
</div>
</PageContext.Provider>
);