Add sub groups to group table
This commit is contained in:
parent
ab800150ec
commit
05968c1964
@ -5,7 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babylonjs/core": "^4.2.0",
|
"@babylonjs/core": "^4.2.0",
|
||||||
"@babylonjs/loaders": "^4.2.0",
|
"@babylonjs/loaders": "^4.2.0",
|
||||||
"@dnd-kit/core": "^3.0.2",
|
"@dnd-kit/core": "3.0.2",
|
||||||
"@dnd-kit/sortable": "^3.0.1",
|
"@dnd-kit/sortable": "^3.0.1",
|
||||||
"@mitchemmc/dexie-export-import": "^1.0.1",
|
"@mitchemmc/dexie-export-import": "^1.0.1",
|
||||||
"@msgpack/msgpack": "^2.4.1",
|
"@msgpack/msgpack": "^2.4.1",
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Flex, Image as UIImage, IconButton, Box, Text, Badge } from "theme-ui";
|
import { Flex, IconButton, Box, Text, Badge, Grid } from "theme-ui";
|
||||||
|
|
||||||
import EditTileIcon from "../icons/EditTileIcon";
|
import EditTileIcon from "../icons/EditTileIcon";
|
||||||
|
|
||||||
function Tile({
|
function Tile({
|
||||||
src,
|
|
||||||
title,
|
title,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
@ -13,6 +12,8 @@ function Tile({
|
|||||||
canEdit,
|
canEdit,
|
||||||
badges,
|
badges,
|
||||||
editTitle,
|
editTitle,
|
||||||
|
columns,
|
||||||
|
children,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@ -34,21 +35,21 @@ function Tile({
|
|||||||
onSelect();
|
onSelect();
|
||||||
}}
|
}}
|
||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
|
aria-label={title}
|
||||||
>
|
>
|
||||||
{src && (
|
<Grid
|
||||||
<UIImage
|
columns={columns}
|
||||||
sx={{
|
sx={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
objectFit: "contain",
|
position: "absolute",
|
||||||
position: "absolute",
|
top: 0,
|
||||||
top: 0,
|
left: 0,
|
||||||
left: 0,
|
gridGap: 0,
|
||||||
}}
|
}}
|
||||||
src={src}
|
>
|
||||||
alt={title}
|
{children}
|
||||||
/>
|
</Grid>
|
||||||
)}
|
|
||||||
<Flex
|
<Flex
|
||||||
sx={{
|
sx={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
@ -116,7 +117,6 @@ function Tile({
|
|||||||
}
|
}
|
||||||
|
|
||||||
Tile.defaultProps = {
|
Tile.defaultProps = {
|
||||||
src: "",
|
|
||||||
title: "",
|
title: "",
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
onSelect: () => {},
|
onSelect: () => {},
|
||||||
@ -126,6 +126,7 @@ Tile.defaultProps = {
|
|||||||
canEdit: false,
|
canEdit: false,
|
||||||
badges: [],
|
badges: [],
|
||||||
editTitle: "Edit",
|
editTitle: "Edit",
|
||||||
|
columns: "1fr",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tile;
|
export default Tile;
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { Image } from "theme-ui";
|
||||||
|
|
||||||
import Tile from "../Tile";
|
import Tile from "../Tile";
|
||||||
|
|
||||||
function DiceTile({ dice, isSelected, onDiceSelect, onDone }) {
|
function DiceTile({ dice, isSelected, onDiceSelect, onDone }) {
|
||||||
return (
|
return (
|
||||||
<Tile
|
<Tile
|
||||||
src={dice.preview}
|
|
||||||
title={dice.name}
|
title={dice.name}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
onSelect={() => onDiceSelect(dice)}
|
onSelect={() => onDiceSelect(dice)}
|
||||||
onDoubleClick={() => onDone(dice)}
|
onDoubleClick={() => onDone(dice)}
|
||||||
/>
|
>
|
||||||
|
<Image src={dice.preview}></Image>
|
||||||
|
</Tile>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ function SortableTiles({ groups, onGroupChange, renderTile, children }) {
|
|||||||
function handleDragEnd({ active, over }) {
|
function handleDragEnd({ active, over }) {
|
||||||
setDragId();
|
setDragId();
|
||||||
if (active && over && active.id !== over.id) {
|
if (active && over && active.id !== over.id) {
|
||||||
const oldIndex = groups.indexOf(active.id);
|
const oldIndex = groups.findIndex((group) => group.id === active.id);
|
||||||
const newIndex = groups.indexOf(over.id);
|
const newIndex = groups.findIndex((group) => group.id === over.id);
|
||||||
onGroupChange(arrayMove(groups, oldIndex, newIndex));
|
onGroupChange(arrayMove(groups, oldIndex, newIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ function SortableTiles({ groups, onGroupChange, renderTile, children }) {
|
|||||||
<DragOverlay dropAnimation={null}>
|
<DragOverlay dropAnimation={null}>
|
||||||
{dragId && (
|
{dragId && (
|
||||||
<animated.div style={dragBounce}>
|
<animated.div style={dragBounce}>
|
||||||
{renderTile(dragId)}
|
{renderTile(groups.find((group) => group.id === dragId))}
|
||||||
</animated.div>
|
</animated.div>
|
||||||
)}
|
)}
|
||||||
</DragOverlay>,
|
</DragOverlay>,
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Tile from "../Tile";
|
import Tile from "../Tile";
|
||||||
|
import MapTileImage from "./MapTileImage";
|
||||||
import { useDataURL } from "../../contexts/AssetsContext";
|
|
||||||
import { mapSources as defaultMapSources } from "../../maps";
|
|
||||||
|
|
||||||
function MapTile({
|
function MapTile({
|
||||||
map,
|
map,
|
||||||
@ -14,16 +12,8 @@ function MapTile({
|
|||||||
canEdit,
|
canEdit,
|
||||||
badges,
|
badges,
|
||||||
}) {
|
}) {
|
||||||
const mapURL = useDataURL(
|
|
||||||
map,
|
|
||||||
defaultMapSources,
|
|
||||||
undefined,
|
|
||||||
map.type === "file"
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tile
|
<Tile
|
||||||
src={mapURL}
|
|
||||||
title={map.name}
|
title={map.name}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
onSelect={() => onMapSelect(map)}
|
onSelect={() => onMapSelect(map)}
|
||||||
@ -32,7 +22,9 @@ function MapTile({
|
|||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
badges={badges}
|
badges={badges}
|
||||||
editTitle="Edit Map"
|
editTitle="Edit Map"
|
||||||
/>
|
>
|
||||||
|
<MapTileImage map={map} />
|
||||||
|
</Tile>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
src/components/map/MapTileGroup.js
Normal file
33
src/components/map/MapTileGroup.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Tile from "../Tile";
|
||||||
|
import MapTileImage from "./MapTileImage";
|
||||||
|
|
||||||
|
function MapTileGroup({
|
||||||
|
group,
|
||||||
|
maps,
|
||||||
|
isSelected,
|
||||||
|
onGroupSelect,
|
||||||
|
onOpen,
|
||||||
|
canOpen,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Tile
|
||||||
|
title={group.name}
|
||||||
|
isSelected={isSelected}
|
||||||
|
// onSelect={() => onGroupSelect(group)}
|
||||||
|
// onDoubleClick={() => canOpen && onOpen()}
|
||||||
|
columns="1fr 1fr"
|
||||||
|
>
|
||||||
|
{maps.slice(0, 4).map((map) => (
|
||||||
|
<MapTileImage
|
||||||
|
sx={{ padding: 1, borderRadius: "8px" }}
|
||||||
|
map={map}
|
||||||
|
key={map.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tile>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MapTileGroup;
|
18
src/components/map/MapTileImage.js
Normal file
18
src/components/map/MapTileImage.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Image } from "theme-ui";
|
||||||
|
|
||||||
|
import { useDataURL } from "../../contexts/AssetsContext";
|
||||||
|
import { mapSources as defaultMapSources } from "../../maps";
|
||||||
|
|
||||||
|
function MapTileImage({ map, sx }) {
|
||||||
|
const mapURL = useDataURL(
|
||||||
|
map,
|
||||||
|
defaultMapSources,
|
||||||
|
undefined,
|
||||||
|
map.type === "file"
|
||||||
|
);
|
||||||
|
|
||||||
|
return <Image sx={sx} src={mapURL}></Image>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MapTileImage;
|
@ -6,6 +6,7 @@ import RemoveMapIcon from "../../icons/RemoveMapIcon";
|
|||||||
import ResetMapIcon from "../../icons/ResetMapIcon";
|
import ResetMapIcon from "../../icons/ResetMapIcon";
|
||||||
|
|
||||||
import MapTile from "./MapTile";
|
import MapTile from "./MapTile";
|
||||||
|
import MapTileGroup from "./MapTileGroup";
|
||||||
import Link from "../Link";
|
import Link from "../Link";
|
||||||
import FilterBar from "../FilterBar";
|
import FilterBar from "../FilterBar";
|
||||||
|
|
||||||
@ -53,24 +54,35 @@ function MapTiles({
|
|||||||
(map) => map.type === "default"
|
(map) => map.type === "default"
|
||||||
);
|
);
|
||||||
|
|
||||||
function mapToTile(mapId) {
|
function groupToMapTile(group) {
|
||||||
const map = maps.find((map) => map.id === mapId);
|
if (group.type === "item") {
|
||||||
const isSelected = selectedMaps.includes(map);
|
const map = maps.find((map) => map.id === group.id);
|
||||||
return (
|
const isSelected = selectedMaps.includes(map);
|
||||||
<MapTile
|
return (
|
||||||
key={map.id}
|
<MapTile
|
||||||
map={map}
|
key={map.id}
|
||||||
isSelected={isSelected}
|
map={map}
|
||||||
onMapSelect={onMapSelect}
|
isSelected={isSelected}
|
||||||
onMapEdit={onMapEdit}
|
onMapSelect={onMapSelect}
|
||||||
onDone={onDone}
|
onMapEdit={onMapEdit}
|
||||||
size={layout.tileSize}
|
onDone={onDone}
|
||||||
canEdit={
|
canEdit={
|
||||||
isSelected && selectMode === "single" && selectedMaps.length === 1
|
isSelected && selectMode === "single" && selectedMaps.length === 1
|
||||||
}
|
}
|
||||||
badges={[`${map.grid.size.x}x${map.grid.size.y}`]}
|
badges={[`${map.grid.size.x}x${map.grid.size.y}`]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<MapTileGroup
|
||||||
|
key={group.id}
|
||||||
|
group={group}
|
||||||
|
maps={group.items.map((item) =>
|
||||||
|
maps.find((map) => map.id === item.id)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const multipleSelected = selectedMaps.length > 1;
|
const multipleSelected = selectedMaps.length > 1;
|
||||||
@ -79,7 +91,7 @@ function MapTiles({
|
|||||||
<SortableTiles
|
<SortableTiles
|
||||||
groups={groups}
|
groups={groups}
|
||||||
onGroupChange={onMapsGroup}
|
onGroupChange={onMapsGroup}
|
||||||
renderTile={mapToTile}
|
renderTile={groupToMapTile}
|
||||||
>
|
>
|
||||||
<Box sx={{ position: "relative" }}>
|
<Box sx={{ position: "relative" }}>
|
||||||
<FilterBar
|
<FilterBar
|
||||||
@ -110,9 +122,9 @@ function MapTiles({
|
|||||||
columns={layout.gridTemplate}
|
columns={layout.gridTemplate}
|
||||||
onClick={() => onMapSelect()}
|
onClick={() => onMapSelect()}
|
||||||
>
|
>
|
||||||
{groups.map((mapId) => (
|
{groups.map((group) => (
|
||||||
<Sortable id={mapId} key={mapId}>
|
<Sortable id={group.id} key={group.id}>
|
||||||
{mapToTile(mapId)}
|
{groupToMapTile(group)}
|
||||||
</Sortable>
|
</Sortable>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -29,6 +29,7 @@ function TokenBar({ onMapTokenStateCreate }) {
|
|||||||
function handleDragEnd({ active }) {
|
function handleDragEnd({ active }) {
|
||||||
setDragId(null);
|
setDragId(null);
|
||||||
const token = tokensById[active.id];
|
const token = tokensById[active.id];
|
||||||
|
console.log("Drag", active);
|
||||||
if (token) {
|
if (token) {
|
||||||
// TODO: Get drag position
|
// TODO: Get drag position
|
||||||
const tokenState = createTokenState(token, { x: 0, y: 0 }, userId);
|
const tokenState = createTokenState(token, { x: 0, y: 0 }, userId);
|
||||||
@ -36,8 +37,9 @@ function TokenBar({ onMapTokenStateCreate }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const tokens = tokenGroups
|
const tokens = tokenGroups
|
||||||
.map((tokenId) => tokensById[tokenId])
|
.map((group) => tokensById[group.id])
|
||||||
.filter((token) => !token.hideInSidebar)
|
// TODO: Add group support
|
||||||
|
.filter((token) => token && !token.hideInSidebar)
|
||||||
.map((token) => (
|
.map((token) => (
|
||||||
<Draggable id={token.id} key={token.id}>
|
<Draggable id={token.id} key={token.id}>
|
||||||
<ListToken token={token} />
|
<ListToken token={token} />
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import Tile from "../Tile";
|
import Tile from "../Tile";
|
||||||
|
import TokenTileImage from "./TokenTileImage";
|
||||||
import { useDataURL } from "../../contexts/AssetsContext";
|
|
||||||
|
|
||||||
import { tokenSources as defaultTokenSources } from "../../tokens";
|
|
||||||
|
|
||||||
function TokenTile({
|
function TokenTile({
|
||||||
token,
|
token,
|
||||||
@ -14,16 +11,8 @@ function TokenTile({
|
|||||||
canEdit,
|
canEdit,
|
||||||
badges,
|
badges,
|
||||||
}) {
|
}) {
|
||||||
const tokenURL = useDataURL(
|
|
||||||
token,
|
|
||||||
defaultTokenSources,
|
|
||||||
undefined,
|
|
||||||
token.type === "file"
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tile
|
<Tile
|
||||||
src={tokenURL}
|
|
||||||
title={token.name}
|
title={token.name}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
onSelect={() => onTokenSelect(token)}
|
onSelect={() => onTokenSelect(token)}
|
||||||
@ -31,7 +20,9 @@ function TokenTile({
|
|||||||
canEdit={canEdit}
|
canEdit={canEdit}
|
||||||
badges={badges}
|
badges={badges}
|
||||||
editTitle="Edit Token"
|
editTitle="Edit Token"
|
||||||
/>
|
>
|
||||||
|
<TokenTileImage token={token} />
|
||||||
|
</Tile>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
src/components/token/TokenTileGroup.js
Normal file
33
src/components/token/TokenTileGroup.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Tile from "../Tile";
|
||||||
|
import TokenTileImage from "./TokenTileImage";
|
||||||
|
|
||||||
|
function TokenTileGroup({
|
||||||
|
group,
|
||||||
|
tokens,
|
||||||
|
isSelected,
|
||||||
|
onGroupSelect,
|
||||||
|
onOpen,
|
||||||
|
canOpen,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Tile
|
||||||
|
title={group.name}
|
||||||
|
isSelected={isSelected}
|
||||||
|
// onSelect={() => onGroupSelect(group)}
|
||||||
|
// onDoubleClick={() => canOpen && onOpen()}
|
||||||
|
columns="1fr 1fr"
|
||||||
|
>
|
||||||
|
{tokens.slice(0, 4).map((token) => (
|
||||||
|
<TokenTileImage
|
||||||
|
sx={{ padding: 1, borderRadius: "8px" }}
|
||||||
|
token={token}
|
||||||
|
key={token.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Tile>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TokenTileGroup;
|
19
src/components/token/TokenTileImage.js
Normal file
19
src/components/token/TokenTileImage.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Image } from "theme-ui";
|
||||||
|
|
||||||
|
import { useDataURL } from "../../contexts/AssetsContext";
|
||||||
|
|
||||||
|
import { tokenSources as defaultTokenSources } from "../../tokens";
|
||||||
|
|
||||||
|
function TokenTileImage({ token, sx }) {
|
||||||
|
const tokenURL = useDataURL(
|
||||||
|
token,
|
||||||
|
defaultTokenSources,
|
||||||
|
undefined,
|
||||||
|
token.type === "file"
|
||||||
|
);
|
||||||
|
|
||||||
|
return <Image sx={sx} src={tokenURL}></Image>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TokenTileImage;
|
@ -7,6 +7,7 @@ import TokenHideIcon from "../../icons/TokenHideIcon";
|
|||||||
import TokenShowIcon from "../../icons/TokenShowIcon";
|
import TokenShowIcon from "../../icons/TokenShowIcon";
|
||||||
|
|
||||||
import TokenTile from "./TokenTile";
|
import TokenTile from "./TokenTile";
|
||||||
|
import TokenTileGroup from "./TokenTileGroup";
|
||||||
import Link from "../Link";
|
import Link from "../Link";
|
||||||
import FilterBar from "../FilterBar";
|
import FilterBar from "../FilterBar";
|
||||||
|
|
||||||
@ -40,25 +41,37 @@ function TokenTiles({
|
|||||||
);
|
);
|
||||||
let allTokensVisible = selectedTokens.every((token) => !token.hideInSidebar);
|
let allTokensVisible = selectedTokens.every((token) => !token.hideInSidebar);
|
||||||
|
|
||||||
function tokenToTile(tokenId) {
|
function groupToTokenTile(group) {
|
||||||
const token = tokens.find((token) => token.id === tokenId);
|
if (group.type === "item") {
|
||||||
const isSelected = selectedTokens.includes(token);
|
const token = tokens.find((token) => token.id === group.id);
|
||||||
return (
|
const isSelected = selectedTokens.includes(token);
|
||||||
<TokenTile
|
return (
|
||||||
key={token.id}
|
<TokenTile
|
||||||
token={token}
|
key={token.id}
|
||||||
isSelected={isSelected}
|
token={token}
|
||||||
onTokenSelect={onTokenSelect}
|
isSelected={isSelected}
|
||||||
onTokenEdit={onTokenEdit}
|
onTokenSelect={onTokenSelect}
|
||||||
canEdit={
|
onTokenEdit={onTokenEdit}
|
||||||
isSelected &&
|
canEdit={
|
||||||
token.type !== "default" &&
|
isSelected &&
|
||||||
selectMode === "single" &&
|
token.type !== "default" &&
|
||||||
selectedTokens.length === 1
|
selectMode === "single" &&
|
||||||
}
|
selectedTokens.length === 1
|
||||||
badges={[`${token.defaultSize}x`]}
|
}
|
||||||
/>
|
badges={[`${token.defaultSize}x`]}
|
||||||
);
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<TokenTileGroup
|
||||||
|
key={group.id}
|
||||||
|
group={group}
|
||||||
|
tokens={group.items.map((item) =>
|
||||||
|
tokens.find((token) => token.id === item.id)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const multipleSelected = selectedTokens.length > 1;
|
const multipleSelected = selectedTokens.length > 1;
|
||||||
@ -82,7 +95,7 @@ function TokenTiles({
|
|||||||
<SortableTiles
|
<SortableTiles
|
||||||
groups={groups}
|
groups={groups}
|
||||||
onGroupChange={onTokensGroup}
|
onGroupChange={onTokensGroup}
|
||||||
renderTile={tokenToTile}
|
renderTile={groupToTokenTile}
|
||||||
>
|
>
|
||||||
<Box sx={{ position: "relative" }}>
|
<Box sx={{ position: "relative" }}>
|
||||||
<FilterBar
|
<FilterBar
|
||||||
@ -112,9 +125,9 @@ function TokenTiles({
|
|||||||
columns={layout.gridTemplate}
|
columns={layout.gridTemplate}
|
||||||
onClick={() => onTokenSelect()}
|
onClick={() => onTokenSelect()}
|
||||||
>
|
>
|
||||||
{groups.map((tokenId) => (
|
{groups.map((group) => (
|
||||||
<Sortable id={tokenId} key={tokenId}>
|
<Sortable id={group.id} key={group.id}>
|
||||||
{tokenToTile(tokenId)}
|
{groupToTokenTile(group)}
|
||||||
</Sortable>
|
</Sortable>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -47,7 +47,7 @@ export function MapDataProvider({ children }) {
|
|||||||
const storedStates = await database.table("states").toArray();
|
const storedStates = await database.table("states").toArray();
|
||||||
setMapStates(storedStates);
|
setMapStates(storedStates);
|
||||||
const group = await database.table("groups").get("maps");
|
const group = await database.table("groups").get("maps");
|
||||||
const storedGroups = group.data;
|
const storedGroups = group.items;
|
||||||
setMapGroups(storedGroups);
|
setMapGroups(storedGroups);
|
||||||
setMapsLoading(false);
|
setMapsLoading(false);
|
||||||
}
|
}
|
||||||
@ -82,9 +82,9 @@ export function MapDataProvider({ children }) {
|
|||||||
await database.table("maps").add(map);
|
await database.table("maps").add(map);
|
||||||
await database.table("states").add(state);
|
await database.table("states").add(state);
|
||||||
const group = await database.table("groups").get("maps");
|
const group = await database.table("groups").get("maps");
|
||||||
await database
|
await database.table("groups").update("maps", {
|
||||||
.table("groups")
|
items: [{ id: map.id, type: "item" }, ...group.items],
|
||||||
.update("maps", { data: [map.id, ...group.data] });
|
});
|
||||||
},
|
},
|
||||||
[database]
|
[database]
|
||||||
);
|
);
|
||||||
@ -146,7 +146,7 @@ export function MapDataProvider({ children }) {
|
|||||||
async (groups) => {
|
async (groups) => {
|
||||||
// Update group state immediately to avoid animation delay
|
// Update group state immediately to avoid animation delay
|
||||||
setMapGroups(groups);
|
setMapGroups(groups);
|
||||||
await database.table("groups").update("maps", { data: groups });
|
await database.table("groups").update("maps", { items: groups });
|
||||||
},
|
},
|
||||||
[database]
|
[database]
|
||||||
);
|
);
|
||||||
@ -207,7 +207,7 @@ export function MapDataProvider({ children }) {
|
|||||||
}
|
}
|
||||||
if (change.table === "groups") {
|
if (change.table === "groups") {
|
||||||
if (change.type === 2 && change.key === "maps") {
|
if (change.type === 2 && change.key === "maps") {
|
||||||
setMapGroups(change.obj.data);
|
setMapGroups(change.obj.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export function TokenDataProvider({ children }) {
|
|||||||
}
|
}
|
||||||
setTokens(storedTokens);
|
setTokens(storedTokens);
|
||||||
const group = await database.table("groups").get("tokens");
|
const group = await database.table("groups").get("tokens");
|
||||||
const storedGroups = group.data;
|
const storedGroups = group.items;
|
||||||
setTokenGroups(storedGroups);
|
setTokenGroups(storedGroups);
|
||||||
setTokensLoading(false);
|
setTokensLoading(false);
|
||||||
}
|
}
|
||||||
@ -54,9 +54,9 @@ export function TokenDataProvider({ children }) {
|
|||||||
async (token) => {
|
async (token) => {
|
||||||
await database.table("tokens").add(token);
|
await database.table("tokens").add(token);
|
||||||
const group = await database.table("groups").get("tokens");
|
const group = await database.table("groups").get("tokens");
|
||||||
await database
|
await database.table("groups").update("tokens", {
|
||||||
.table("groups")
|
items: [{ id: token.id, type: "item" }, ...group.items],
|
||||||
.update("tokens", { data: [token.id, ...group.data] });
|
});
|
||||||
},
|
},
|
||||||
[database]
|
[database]
|
||||||
);
|
);
|
||||||
@ -99,7 +99,7 @@ export function TokenDataProvider({ children }) {
|
|||||||
async (groups) => {
|
async (groups) => {
|
||||||
// Update group state immediately to avoid animation delay
|
// Update group state immediately to avoid animation delay
|
||||||
setTokenGroups(groups);
|
setTokenGroups(groups);
|
||||||
await database.table("groups").update("tokens", { data: groups });
|
await database.table("groups").update("tokens", { items: groups });
|
||||||
},
|
},
|
||||||
[database]
|
[database]
|
||||||
);
|
);
|
||||||
@ -139,7 +139,7 @@ export function TokenDataProvider({ children }) {
|
|||||||
}
|
}
|
||||||
if (change.table === "groups") {
|
if (change.table === "groups") {
|
||||||
if (change.type === 2 && change.key === "tokens") {
|
if (change.type === 2 && change.key === "tokens") {
|
||||||
setTokenGroups(change.obj.data);
|
setTokenGroups(change.obj.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,11 @@ function populate(db) {
|
|||||||
const tokens = getDefaultTokens(userId);
|
const tokens = getDefaultTokens(userId);
|
||||||
db.table("tokens").bulkAdd(tokens);
|
db.table("tokens").bulkAdd(tokens);
|
||||||
db.table("groups").bulkAdd([
|
db.table("groups").bulkAdd([
|
||||||
{ id: "maps", data: maps.map((map) => map.id) },
|
{ id: "maps", items: maps.map((map) => ({ id: map.id, type: "item" })) },
|
||||||
{ id: "tokens", data: tokens.map((token) => token.id) },
|
{
|
||||||
|
id: "tokens",
|
||||||
|
items: tokens.map((token) => ({ id: token.id, type: "item" })),
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -639,23 +639,59 @@ export const versions = {
|
|||||||
tx.table("tokens").bulkAdd(tokens);
|
tx.table("tokens").bulkAdd(tokens);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// v1.9.0 -
|
// v1.9.0 - Add new group table
|
||||||
33(v) {
|
33(v) {
|
||||||
v.stores({ groups: "id" }).upgrade(async (tx) => {
|
v.stores({ groups: "id" }).upgrade(async (tx) => {
|
||||||
|
function groupItems(items) {
|
||||||
|
let groups = [];
|
||||||
|
let subGroups = {};
|
||||||
|
for (let item of items) {
|
||||||
|
if (!item.group) {
|
||||||
|
groups.push({ id: item.id, type: "item" });
|
||||||
|
} else if (item.group in subGroups) {
|
||||||
|
subGroups[item.group].items.push({ id: item.id, type: "item" });
|
||||||
|
} else {
|
||||||
|
subGroups[item.group] = {
|
||||||
|
id: uuid(),
|
||||||
|
type: "group",
|
||||||
|
name: item.group,
|
||||||
|
items: [{ id: item.id, type: "item" }],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groups.push(...Object.values(subGroups));
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
let maps = await Dexie.waitFor(tx.table("maps").toArray());
|
let maps = await Dexie.waitFor(tx.table("maps").toArray());
|
||||||
maps = maps.sort((a, b) => b.created - a.created);
|
maps = maps.sort((a, b) => b.created - a.created);
|
||||||
const mapIds = maps.map((map) => map.id);
|
const mapGroupItems = groupItems(maps);
|
||||||
tx.table("groups").add({ id: "maps", data: mapIds });
|
tx.table("groups").add({ id: "maps", items: mapGroupItems });
|
||||||
|
|
||||||
let tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
let tokens = await Dexie.waitFor(tx.table("tokens").toArray());
|
||||||
tokens = tokens.sort((a, b) => b.created - a.created);
|
tokens = tokens.sort((a, b) => b.created - a.created);
|
||||||
const tokenIds = tokens.map((token) => token.id);
|
const tokenGroupItems = groupItems(tokens);
|
||||||
tx.table("groups").add({ id: "tokens", data: tokenIds });
|
tx.table("groups").add({ id: "tokens", items: tokenGroupItems });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// v1.9.0 - Remove map and token group in respective tables
|
||||||
|
34(v) {
|
||||||
|
v.stores({}).upgrade((tx) => {
|
||||||
|
tx.table("maps")
|
||||||
|
.toCollection()
|
||||||
|
.modify((map) => {
|
||||||
|
delete map.group;
|
||||||
|
});
|
||||||
|
tx.table("tokens")
|
||||||
|
.toCollection()
|
||||||
|
.modify((token) => {
|
||||||
|
delete token.group;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const latestVersion = 33;
|
export const latestVersion = 34;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load versions onto a database up to a specific version number
|
* Load versions onto a database up to a specific version number
|
||||||
|
@ -1803,7 +1803,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@dnd-kit/core@^3.0.0", "@dnd-kit/core@^3.0.2":
|
"@dnd-kit/core@3.0.2", "@dnd-kit/core@^3.0.0":
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-3.0.2.tgz#e46ae11ef667aa5c31fddab21cf36ffd80d3ce5b"
|
resolved "https://registry.yarnpkg.com/@dnd-kit/core/-/core-3.0.2.tgz#e46ae11ef667aa5c31fddab21cf36ffd80d3ce5b"
|
||||||
integrity sha512-L+rGnDYBb4BfYKDylzIBeODRIlJ+YVvo2iL9pVXsh317Nq7c9irCvi3XK8JnWD5QBw/3WZ5FmbPmTE91EKwKeA==
|
integrity sha512-L+rGnDYBb4BfYKDylzIBeODRIlJ+YVvo2iL9pVXsh317Nq7c9irCvi3XK8JnWD5QBw/3WZ5FmbPmTE91EKwKeA==
|
||||||
@ -11894,6 +11894,7 @@ simple-peer@feross/simple-peer#694/head:
|
|||||||
resolved "https://codeload.github.com/feross/simple-peer/tar.gz/0d08d07b83ff3b8c60401688d80642d24dfeffe2"
|
resolved "https://codeload.github.com/feross/simple-peer/tar.gz/0d08d07b83ff3b8c60401688d80642d24dfeffe2"
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.0.1"
|
debug "^4.0.1"
|
||||||
|
err-code "^2.0.3"
|
||||||
get-browser-rtc "^1.0.0"
|
get-browser-rtc "^1.0.0"
|
||||||
queue-microtask "^1.1.0"
|
queue-microtask "^1.1.0"
|
||||||
randombytes "^2.0.3"
|
randombytes "^2.0.3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user