From 2701df1e3b03c7c605ccf212a02987d53fbd0609 Mon Sep 17 00:00:00 2001 From: notoraptor Date: Wed, 17 Jul 2019 15:16:43 -0400 Subject: [web] Make button "Delete all" remove only orders from current se… (#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Make button "Delete all" remove only orders from current selected power. - Reorganize code - [web] Remove bugged and useless function gameReloaded() from game page. - This function caused error `engine.getPhaseType is not a function` for games with deadlines. - Move function saveGameToDisk into its own file. - [web] Add documentation to methods involved in orders management to help understand what happens. - Move methods getServerOrders() from game GUI component to game engine object. - Rename method onSetNoOrders to onSetEmptyOrdersSet. - Rename property in PowerActionsForm: onNoOrders => onPass. - [web] Update sending orders to send request clearOrders when local orders list is null. - Renamed local file: - components/power_order => power_orders - forms/power_actions_form => power_order_creation_form - Move power orders buttons bar to a separate file: - components/power_orders_actions_bar - [web] Improve messages about local/server defined orders. --- diplomacy/web/src/gui/utils/dipStorage.jsx | 140 ++++++++++++++ diplomacy/web/src/gui/utils/inline_game_view.jsx | 158 +++++++++++++++ diplomacy/web/src/gui/utils/load_game_from_disk.js | 83 ++++++++ diplomacy/web/src/gui/utils/map_data.js | 98 ++++++++++ diplomacy/web/src/gui/utils/order.js | 24 +++ diplomacy/web/src/gui/utils/order_building.js | 211 +++++++++++++++++++++ diplomacy/web/src/gui/utils/power_view.jsx | 65 +++++++ diplomacy/web/src/gui/utils/province.js | 117 ++++++++++++ diplomacy/web/src/gui/utils/saveGameToDisk.js | 18 ++ 9 files changed, 914 insertions(+) create mode 100644 diplomacy/web/src/gui/utils/dipStorage.jsx create mode 100644 diplomacy/web/src/gui/utils/inline_game_view.jsx create mode 100644 diplomacy/web/src/gui/utils/load_game_from_disk.js create mode 100644 diplomacy/web/src/gui/utils/map_data.js create mode 100644 diplomacy/web/src/gui/utils/order.js create mode 100644 diplomacy/web/src/gui/utils/order_building.js create mode 100644 diplomacy/web/src/gui/utils/power_view.jsx create mode 100644 diplomacy/web/src/gui/utils/province.js create mode 100644 diplomacy/web/src/gui/utils/saveGameToDisk.js (limited to 'diplomacy/web/src/gui/utils') diff --git a/diplomacy/web/src/gui/utils/dipStorage.jsx b/diplomacy/web/src/gui/utils/dipStorage.jsx new file mode 100644 index 0000000..db5baad --- /dev/null +++ b/diplomacy/web/src/gui/utils/dipStorage.jsx @@ -0,0 +1,140 @@ +// ============================================================================== +// Copyright (C) 2019 - Philip Paquette, Steven Bocco +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU Affero General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +// details. +// +// You should have received a copy of the GNU Affero General Public License along +// with this program. If not, see . +// ============================================================================== +/* DipStorage scheme: +global +- connection + - username + - hostname + - port + - showServerFields +users +- (username) + - games + - (game_id) + - phase: string + - local_orders: {power_name => [orders]} +*/ + +let STORAGE = null; + +export class DipStorage { + static load() { + if (!STORAGE) { + const global = window.localStorage.global; + const users = window.localStorage.users; + STORAGE = { + global: (global && JSON.parse(global)) || { + connection: { + username: null, + hostname: null, + port: null, + showServerFields: null + } + }, + users: (users && JSON.parse(users)) || {} + }; + } + } + + static save() { + if (STORAGE) { + window.localStorage.global = JSON.stringify(STORAGE.global); + window.localStorage.users = JSON.stringify(STORAGE.users); + } + } + + static getConnectionForm() { + DipStorage.load(); + return Object.assign({}, STORAGE.global.connection); + } + + static getUserGames(username) { + DipStorage.load(); + if (STORAGE.users[username]) + return Object.keys(STORAGE.users[username].games); + return null; + } + + static getUserGameOrders(username, gameID, gamePhase) { + DipStorage.load(); + if (STORAGE.users[username] && STORAGE.users[username].games[gameID] + && STORAGE.users[username].games[gameID].phase === gamePhase) + return Object.assign({}, STORAGE.users[username].games[gameID].local_orders); + return null; + } + + static setConnectionUsername(username) { + DipStorage.load(); + STORAGE.global.connection.username = username; + DipStorage.save(); + } + + static setConnectionHostname(hostname) { + DipStorage.load(); + STORAGE.global.connection.hostname = hostname; + DipStorage.save(); + } + + static setConnectionPort(port) { + DipStorage.load(); + STORAGE.global.connection.port = port; + DipStorage.save(); + } + + static setConnectionshowServerFields(showServerFields) { + DipStorage.load(); + STORAGE.global.connection.showServerFields = showServerFields; + DipStorage.save(); + } + + static addUserGame(username, gameID) { + DipStorage.load(); + if (!STORAGE.users[username]) + STORAGE.users[username] = {games: {}}; + if (!STORAGE.users[username].games[gameID]) + STORAGE.users[username].games[gameID] = {phase: null, local_orders: {}}; + DipStorage.save(); + } + + static addUserGameOrders(username, gameID, gamePhase, powerName, orders) { + DipStorage.addUserGame(username, gameID); + if (STORAGE.users[username].games[gameID].phase !== gamePhase) + STORAGE.users[username].games[gameID] = {phase: null, local_orders: {}}; + STORAGE.users[username].games[gameID].phase = gamePhase; + STORAGE.users[username].games[gameID].local_orders[powerName] = orders; + DipStorage.save(); + } + + static removeUserGame(username, gameID) { + DipStorage.load(); + if (STORAGE.users[username] && STORAGE.users[username].games[gameID]) { + delete STORAGE.users[username].games[gameID]; + DipStorage.save(); + } + } + + static clearUserGameOrders(username, gameID, powerName) { + DipStorage.addUserGame(username, gameID); + if (powerName) { + if (STORAGE.users[username].games[gameID].local_orders[powerName]) + delete STORAGE.users[username].games[gameID].local_orders[powerName]; + } else { + STORAGE.users[username].games[gameID] = {phase: null, local_orders: {}}; + } + DipStorage.save(); + } +} diff --git a/diplomacy/web/src/gui/utils/inline_game_view.jsx b/diplomacy/web/src/gui/utils/inline_game_view.jsx new file mode 100644 index 0000000..ec2ca46 --- /dev/null +++ b/diplomacy/web/src/gui/utils/inline_game_view.jsx @@ -0,0 +1,158 @@ +// ============================================================================== +// Copyright (C) 2019 - Philip Paquette, Steven Bocco +// +// This program is free software: you can redistribute it and/or modify it under +// the terms of the GNU Affero General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +// details. +// +// You should have received a copy of the GNU Affero General Public License along +// with this program. If not, see . +// ============================================================================== +import React from "react"; +import {JoinForm} from "../forms/join_form"; +import {STRINGS} from "../../diplomacy/utils/strings"; +import {ContentGame} from "../pages/content_game"; +import {Button} from "../components/button"; +import {DeleteButton} from "../components/delete_button"; + +export class InlineGameView { + constructor(page, gameData) { + this.page = page; + this.game = gameData; + this.get = this.get.bind(this); + this.joinGame = this.joinGame.bind(this); + this.showGame = this.showGame.bind(this); + } + + joinGame(formData) { + const form = { + power_name: formData[`power_name_${this.game.game_id}`], + registration_password: formData[`registration_password_${this.game.game_id}`] + }; + if (!form.power_name) + form.power_name = null; + if (!form.registration_password) + form.registration_password = null; + form.game_id = this.game.game_id; + this.page.channel.joinGame(form) + .then((networkGame) => { + this.game = networkGame.local; + this.page.addToMyGames(this.game); + return networkGame.getAllPossibleOrders(); + }) + .then(allPossibleOrders => { + this.game.setPossibleOrders(allPossibleOrders); + this.page.load( + `game: ${this.game.game_id}`, + , + {success: 'Game joined.'} + ); + }) + .catch((error) => { + this.page.error('Error when joining game ' + this.game.game_id + ': ' + error); + }); + } + + showGame() { + this.page.load(`game: ${this.game.game_id}`, ); + } + + getJoinUI() { + if (this.game.role) { + // Game already joined. + return ( +
+
+ ); + } else { + // Game not yet joined. + return ; + } + } + + getActionButtons() { + const buttons = []; + // Button to add/remove game from "My games" list. + if (this.page.hasMyGame(this.game.game_id)) { + if (!this.game.client) { + // Game in My Games and not joined. We can remove it. + buttons.push(