From 10c259a6b36c6ba70a3fb26389c7fe69f5596183 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 23 Apr 2020 20:32:33 +1000 Subject: [PATCH] Added state to default maps and added clear state option to map tile --- src/components/map/MapTile.js | 143 +++++++++++++++++++++++++++++++++ src/components/map/MapTiles.js | 83 +++++++------------ src/icons/ExpandMoreDotIcon.js | 18 +++++ src/icons/RemoveIcon.js | 18 ----- src/icons/RemoveMapIcon.js | 18 +++++ src/icons/ResetMapIcon.js | 18 +++++ src/maps/index.js | 12 +-- src/modals/SelectMapModal.js | 20 ++++- 8 files changed, 250 insertions(+), 80 deletions(-) create mode 100644 src/components/map/MapTile.js create mode 100644 src/icons/ExpandMoreDotIcon.js delete mode 100644 src/icons/RemoveIcon.js create mode 100644 src/icons/RemoveMapIcon.js create mode 100644 src/icons/ResetMapIcon.js diff --git a/src/components/map/MapTile.js b/src/components/map/MapTile.js new file mode 100644 index 0000000..b06fc4c --- /dev/null +++ b/src/components/map/MapTile.js @@ -0,0 +1,143 @@ +import React, { useState, useEffect } from "react"; +import { Flex, Image as UIImage, IconButton, Box } from "theme-ui"; + +import db from "../../database"; + +import RemoveMapIcon from "../../icons/RemoveMapIcon"; +import ResetMapIcon from "../../icons/ResetMapIcon"; +import ExpandMoreDotIcon from "../../icons/ExpandMoreDotIcon"; + +function MapTile({ map, isSelected, onMapSelect, onMapRemove, onMapReset }) { + const [isMapTileMenuOpen, setIsTileMenuOpen] = useState(false); + const [hasMapState, setHasMapState] = useState(false); + + useEffect(() => { + async function checkForMapState() { + const state = await db.table("states").get(map.id); + if ( + state && + (Object.values(state.tokens).length > 0 || state.drawActions.length > 0) + ) { + setHasMapState(true); + } + } + + checkForMapState(); + }, [map]); + + const expandButton = ( + { + e.preventDefault(); + e.stopPropagation(); + setIsTileMenuOpen(true); + }} + bg="overlay" + sx={{ borderRadius: "50%" }} + m={1} + > + + + ); + + function removeButton(map) { + return ( + { + e.preventDefault(); + e.stopPropagation(); + setIsTileMenuOpen(false); + onMapRemove(map.id); + }} + bg="overlay" + sx={{ borderRadius: "50%" }} + m={1} + > + + + ); + } + + function resetButton(map) { + return ( + { + e.preventDefault(); + e.stopPropagation(); + setHasMapState(false); + setIsTileMenuOpen(false); + onMapReset(map.id); + }} + bg="overlay" + sx={{ borderRadius: "50%" }} + m={1} + > + + + ); + } + + return ( + { + setIsTileMenuOpen(false); + onMapSelect(map); + }} + > + + {/* Show expand button only if both reset and remove is available */} + {isSelected && ( + + {map.default && hasMapState && resetButton(map)} + {!map.default && hasMapState && !isMapTileMenuOpen && expandButton} + {!map.default && !hasMapState && removeButton(map)} + + )} + {/* Tile menu for two actions */} + {!map.default && isMapTileMenuOpen && isSelected && ( + setIsTileMenuOpen(false)} + > + {!map.default && removeButton(map)} + {hasMapState && resetButton(map)} + + )} + + ); +} + +export default MapTile; diff --git a/src/components/map/MapTiles.js b/src/components/map/MapTiles.js index a2bc073..796ae8e 100644 --- a/src/components/map/MapTiles.js +++ b/src/components/map/MapTiles.js @@ -1,60 +1,18 @@ import React from "react"; -import { Flex, Image as UIImage, IconButton } from "theme-ui"; +import { Flex } from "theme-ui"; import AddIcon from "../../icons/AddIcon"; -import RemoveIcon from "../../icons/RemoveIcon"; -function MapTiles({ maps, selectedMap, onMapSelect, onMapAdd, onMapRemove }) { - const tileProps = { - m: 2, - bg: "muted", - }; - - const tileStyle = { - width: "150px", - height: "150px", - borderRadius: "4px", - justifyContent: "center", - alignItems: "center", - cursor: "pointer", - }; - - function tile(map) { - return ( - onMapSelect(map)} - > - - {!map.default && map.id === selectedMap && ( - { - e.preventDefault(); - e.stopPropagation(); - onMapRemove(map.id); - }} - sx={{ position: "absolute", top: 0, right: 0 }} - > - - - )} - - ); - } +import MapTile from "./MapTile"; +function MapTiles({ + maps, + selectedMap, + onMapSelect, + onMapAdd, + onMapRemove, + onMapReset, +}) { return ( - {maps.map(tile)} + {maps.map((map) => ( + + ))} ); } diff --git a/src/icons/ExpandMoreDotIcon.js b/src/icons/ExpandMoreDotIcon.js new file mode 100644 index 0000000..6259f07 --- /dev/null +++ b/src/icons/ExpandMoreDotIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function ExpandMoreDotIcon() { + return ( + + + + + ); +} + +export default ExpandMoreDotIcon; diff --git a/src/icons/RemoveIcon.js b/src/icons/RemoveIcon.js deleted file mode 100644 index d09fbc8..0000000 --- a/src/icons/RemoveIcon.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; - -function RemoveIcon() { - return ( - - - - - ); -} - -export default RemoveIcon; diff --git a/src/icons/RemoveMapIcon.js b/src/icons/RemoveMapIcon.js new file mode 100644 index 0000000..a7dd3f3 --- /dev/null +++ b/src/icons/RemoveMapIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function RemoveMapIcon() { + return ( + + + + + ); +} + +export default RemoveMapIcon; diff --git a/src/icons/ResetMapIcon.js b/src/icons/ResetMapIcon.js new file mode 100644 index 0000000..02ac13b --- /dev/null +++ b/src/icons/ResetMapIcon.js @@ -0,0 +1,18 @@ +import React from "react"; + +function ResetMapIcon() { + return ( + + + + + ); +} + +export default ResetMapIcon; diff --git a/src/maps/index.js b/src/maps/index.js index 4a9524d..1c0eb07 100644 --- a/src/maps/index.js +++ b/src/maps/index.js @@ -16,35 +16,35 @@ const defaultProps = { export const blank = { ...defaultProps, source: blankImage, - id: "Blank Grid 22x22", + id: "__default_blank", }; export const grass = { ...defaultProps, source: grassImage, - id: "Grass Grid 22x22", + id: "__default_grass", }; export const sand = { ...defaultProps, source: sandImage, - id: "Sand Grid 22x22", + id: "__default_sand", }; export const stone = { ...defaultProps, source: stoneImage, - id: "Stone Grid 22x22", + id: "__default_stone", }; export const water = { ...defaultProps, source: waterImage, - id: "Water Grid 22x22", + id: "__default_water", }; export const wood = { ...defaultProps, source: woodImage, - id: "Wood Grid 22x22", + id: "__default_wood", }; diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js index 970e7df..c1dbc71 100644 --- a/src/modals/SelectMapModal.js +++ b/src/modals/SelectMapModal.js @@ -23,7 +23,7 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) { const [currentMap, setCurrentMap] = useState(null); const [maps, setMaps] = useState(Object.values(defaultMaps)); - // Load maps from the database + // Load maps from the database and ensure state is properly setup useEffect(() => { async function loadMaps() { let storedMaps = await db.table("maps").toArray(); @@ -35,7 +35,20 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) { } setMaps((prevMaps) => [...storedMaps, ...prevMaps]); } + + async function setupDefaultMapStatesIfNeeded() { + for (let defaultMap of Object.values(defaultMaps)) { + let state = await db.table("states").get(defaultMap.id); + if (!state) { + await db + .table("states") + .add({ ...defaultMapState, mapId: defaultMap.id }); + } + } + } + loadMaps(); + setupDefaultMapStatesIfNeeded(); }, []); const [gridX, setGridX] = useState(defaultMapSize); @@ -111,6 +124,10 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) { setGridY(map.gridY); } + async function handleMapReset(id) { + await db.table("states").put({ ...defaultMapState, mapId: id }); + } + async function handleSubmit(e) { e.preventDefault(); if (currentMap) { @@ -199,6 +216,7 @@ function SelectMapModal({ isOpen, onRequestClose, onDone }) { onMapRemove={handleMapRemove} selectedMap={currentMap && currentMap.id} onMapSelect={handleMapSelect} + onMapReset={handleMapReset} />