-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(homebrew): Assets, moves, and oracles can now be moved between c…
…ollections and categories
- Loading branch information
1 parent
460aef2
commit 37f64d4
Showing
15 changed files
with
772 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
183 changes: 183 additions & 0 deletions
183
src/pages/Homebrew/HomebrewEditorPage/AssetsSection/AssetPreviewCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import { Datasworn } from "@datasworn/core"; | ||
import { Box, Card, IconButton, Tooltip } from "@mui/material"; | ||
import { AssetAbilities } from "components/features/assets/NewAssetCard/AssetAbilities"; | ||
import { AssetControls } from "components/features/assets/NewAssetCard/AssetControls"; | ||
import { AssetHeader } from "components/features/assets/NewAssetCard/AssetHeader"; | ||
import { AssetNameAndDescription } from "components/features/assets/NewAssetCard/AssetNameAndDescription"; | ||
import { AssetOptions } from "components/features/assets/NewAssetCard/AssetOptions"; | ||
import { convertIdPart } from "functions/dataswornIdEncoder"; | ||
import { StoredHomebrewAsset } from "types/homebrew/HomebrewAssets.type"; | ||
import EditIcon from "@mui/icons-material/Edit"; | ||
import MoveIcon from "@mui/icons-material/DriveFileMove"; | ||
|
||
export interface AssetPreviewCardProps { | ||
storedAsset: StoredHomebrewAsset; | ||
collectionName: string; | ||
handleDeleteAsset: () => void; | ||
handleEditAsset: () => void; | ||
handleMoveAsset: () => void; | ||
} | ||
|
||
export function AssetPreviewCard(props: AssetPreviewCardProps) { | ||
const { | ||
storedAsset, | ||
collectionName, | ||
handleDeleteAsset, | ||
handleEditAsset, | ||
handleMoveAsset, | ||
} = props; | ||
|
||
const { label, requirement, abilities, options, controls } = storedAsset; | ||
|
||
const dataswornAbilities: Datasworn.AssetAbility[] = abilities.map( | ||
(ability, index) => ({ | ||
_id: index + "", | ||
text: ability.text, | ||
name: ability.name, | ||
enabled: ability.defaultEnabled ?? false, | ||
}) | ||
); | ||
|
||
const dataswornOptions: Record<string, Datasworn.AssetOptionField> = {}; | ||
options?.forEach((option) => { | ||
let optionId: string; | ||
|
||
try { | ||
optionId = convertIdPart(option.label); | ||
} catch (e) { | ||
return; | ||
} | ||
if (option.type === "text") { | ||
dataswornOptions[optionId] = { | ||
label: option.label, | ||
field_type: "text", | ||
value: "", | ||
}; | ||
} else { | ||
const choices: Record<string, Datasworn.SelectEnhancementFieldChoice> = | ||
{}; | ||
|
||
(option.options ?? []).forEach((optionChoice) => { | ||
choices[optionChoice] = { | ||
label: optionChoice, | ||
choice_type: "choice", | ||
}; | ||
}); | ||
|
||
dataswornOptions[optionId] = { | ||
label: option.label, | ||
field_type: "select_enhancement", | ||
value: "", | ||
choices, | ||
}; | ||
} | ||
}); | ||
|
||
const dataswornControls: Record<string, Datasworn.AssetControlField> = {}; | ||
controls?.forEach((control) => { | ||
let controlId: string; | ||
|
||
try { | ||
controlId = convertIdPart(control.label); | ||
} catch (e) { | ||
return; | ||
} | ||
if (control.type === "checkbox") { | ||
dataswornControls[controlId] = { | ||
field_type: "checkbox", | ||
label: control.label, | ||
value: false, | ||
is_impact: false, | ||
disables_asset: false, | ||
}; | ||
} else if (control.type === "select") { | ||
const choices: Record<string, Datasworn.SelectEnhancementFieldChoice> = | ||
{}; | ||
|
||
(control.options ?? []).forEach((optionChoice) => { | ||
choices[optionChoice] = { | ||
label: optionChoice, | ||
choice_type: "choice", | ||
}; | ||
}); | ||
|
||
dataswornControls[controlId] = { | ||
label: control.label, | ||
field_type: "select_enhancement", | ||
value: "", | ||
choices, | ||
}; | ||
} else if (control.type === "conditionMeter") { | ||
dataswornControls[controlId] = { | ||
label: control.label, | ||
field_type: "condition_meter", | ||
value: control.max, | ||
max: control.max, | ||
min: control.min, | ||
rollable: true, | ||
}; | ||
} | ||
}); | ||
|
||
const asset: Datasworn.Asset = { | ||
_id: "", | ||
name: label, | ||
count_as_impact: false, | ||
shared: false, | ||
_source: { title: "", authors: [], date: "", url: "", license: "" }, | ||
|
||
requirement: requirement, | ||
category: collectionName, | ||
abilities: dataswornAbilities, | ||
options: dataswornOptions, | ||
controls: dataswornControls, | ||
}; | ||
|
||
return ( | ||
<Card | ||
variant={"outlined"} | ||
sx={{ | ||
position: "relative", | ||
height: "100%", | ||
display: "flex", | ||
flexDirection: "column", | ||
borderWidth: 0, | ||
}} | ||
> | ||
<AssetHeader | ||
asset={asset} | ||
onAssetRemove={handleDeleteAsset} | ||
actions={ | ||
<> | ||
<Tooltip title={"Move asset to another collection"}> | ||
<IconButton onClick={handleMoveAsset} color={"inherit"}> | ||
<MoveIcon /> | ||
</IconButton> | ||
</Tooltip> | ||
<Tooltip title={"Edit Asset"}> | ||
<IconButton onClick={handleEditAsset} color={"inherit"}> | ||
<EditIcon /> | ||
</IconButton> | ||
</Tooltip> | ||
</> | ||
} | ||
/> | ||
<Box | ||
flexGrow={1} | ||
display={"flex"} | ||
flexDirection={"column"} | ||
p={1} | ||
border={(theme) => `1px solid ${theme.palette.divider}`} | ||
sx={(theme) => ({ | ||
borderBottomLeftRadius: theme.shape.borderRadius, | ||
borderBottomRightRadius: theme.shape.borderRadius, | ||
})} | ||
> | ||
<AssetNameAndDescription asset={asset} /> | ||
<AssetOptions asset={asset} onAssetOptionChange={() => {}} /> | ||
<AssetAbilities asset={asset} /> | ||
<AssetControls controls={asset.controls} onControlChange={() => {}} /> | ||
</Box> | ||
</Card> | ||
); | ||
} |
83 changes: 83 additions & 0 deletions
83
src/pages/Homebrew/HomebrewEditorPage/AssetsSection/Assets/MoveAssetDialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { | ||
Autocomplete, | ||
Box, | ||
Button, | ||
Dialog, | ||
DialogActions, | ||
DialogContent, | ||
ListItemText, | ||
TextField, | ||
} from "@mui/material"; | ||
import { DialogTitleWithCloseButton } from "components/shared/DialogTitleWithCloseButton"; | ||
import { useEffect, useState } from "react"; | ||
import { useStore } from "stores/store"; | ||
import { StoredHomebrewAssetCollection } from "types/homebrew/HomebrewAssets.type"; | ||
|
||
export interface MoveAssetDialogProps { | ||
onClose: () => void; | ||
state?: { | ||
assetId: string; | ||
assetCollectionId: string; | ||
}; | ||
collections: Record<string, StoredHomebrewAssetCollection>; | ||
} | ||
|
||
export function MoveAssetDialog(props: MoveAssetDialogProps) { | ||
const { state, onClose, collections } = props; | ||
const { assetId, assetCollectionId } = state ?? {}; | ||
|
||
const [selectedAssetCollection, setSelectedAssetCollection] = | ||
useState(assetCollectionId); | ||
|
||
useEffect(() => { | ||
setSelectedAssetCollection(assetCollectionId); | ||
}, [assetCollectionId]); | ||
|
||
const updateAsset = useStore((store) => store.homebrew.updateAsset); | ||
|
||
const handleSave = () => { | ||
if (assetId && selectedAssetCollection) { | ||
updateAsset(assetId, { categoryKey: selectedAssetCollection }) | ||
.then(() => { | ||
onClose(); | ||
}) | ||
.catch(() => {}); | ||
} | ||
}; | ||
|
||
return ( | ||
<Dialog open={!!assetId} onClose={onClose} maxWidth={"xs"} fullWidth> | ||
<DialogTitleWithCloseButton onClose={onClose}> | ||
Move Asset | ||
</DialogTitleWithCloseButton> | ||
<DialogContent> | ||
<Autocomplete | ||
sx={{ mt: 1 }} | ||
options={Object.keys(collections)} | ||
getOptionKey={(option) => option} | ||
getOptionLabel={(key) => collections[key]?.label} | ||
renderInput={(params) => ( | ||
<TextField {...params} label={"Asset Collections"} /> | ||
)} | ||
renderOption={(props, option) => ( | ||
<Box component={"li"} {...props}> | ||
<ListItemText primary={collections[option].label} /> | ||
</Box> | ||
)} | ||
value={selectedAssetCollection ?? null} | ||
onChange={(evt, value) => { | ||
setSelectedAssetCollection(value ?? undefined); | ||
}} | ||
/> | ||
</DialogContent> | ||
<DialogActions> | ||
<Button color={"inherit"} onClick={onClose}> | ||
Cancel | ||
</Button> | ||
<Button variant={"contained"} onClick={handleSave}> | ||
Move Asset | ||
</Button> | ||
</DialogActions> | ||
</Dialog> | ||
); | ||
} |
Oops, something went wrong.