2 changed files with 249 additions and 263 deletions
@ -0,0 +1,156 @@ |
|||||
|
import { ConfigSelectButton } from "@app/components/UI/ConfigSelectButton"; |
||||
|
import { useToast } from "@app/core/hooks/useToast"; |
||||
|
import { ConfigPreset, useAppStore } from "@app/core/stores/appStore"; |
||||
|
import { PlusIcon, Edit3Icon, Trash2Icon, UploadIcon, DownloadIcon } from "lucide-react"; |
||||
|
import { useState } from "react"; |
||||
|
|
||||
|
export const ConfigList = ({rootConfig, setTotalConfigCountDiff}: {rootConfig: ConfigPreset, setTotalConfigCountDiff: (val: number) => void}) => { |
||||
|
const { configPresetRoot, setConfigPresetRoot, configPresetSelected, setConfigPresetSelected } = useAppStore(); |
||||
|
const [ editSelected, setEditSelected ] = useState(false); |
||||
|
const { toast } = useToast(); |
||||
|
if(configPresetSelected === undefined) { |
||||
|
setConfigPresetSelected(configPresetRoot); |
||||
|
return (<div/>); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div className="flex flex-col min-w-[400px] rounded-md border border-dashed border-slate-200 p-3 mb-2 dark:border-slate-700"> |
||||
|
<div className="flex justify-between"> |
||||
|
<div className="flex gap-2"> |
||||
|
<button |
||||
|
className="transition-all hover:text-accent mb-4" |
||||
|
title="Add new configuration as child" |
||||
|
onClick={() => { |
||||
|
const newPreset = new ConfigPreset("New Preset", configPresetSelected); |
||||
|
configPresetSelected?.children.push(newPreset); |
||||
|
setConfigPresetRoot(Object.create(configPresetRoot)); |
||||
|
setConfigPresetSelected(newPreset); |
||||
|
setEditSelected(true); |
||||
|
newPreset.saveConfigTree(); |
||||
|
}} |
||||
|
> |
||||
|
<PlusIcon/> |
||||
|
</button> |
||||
|
<button |
||||
|
className="transition-all hover:text-accent mb-4" |
||||
|
title="Rename" |
||||
|
onClick={() => { |
||||
|
setEditSelected(true); |
||||
|
}} |
||||
|
> |
||||
|
<Edit3Icon/> |
||||
|
</button> |
||||
|
<button |
||||
|
className="transition-all hover:text-accent mb-4" |
||||
|
title="Delete" |
||||
|
onClick={() => { |
||||
|
if(configPresetSelected.parent === undefined) { |
||||
|
if(!confirm(`Are you sure you want to reset the preset list to default?`)) |
||||
|
return; |
||||
|
const newDefault = new ConfigPreset("Default"); |
||||
|
setConfigPresetRoot(newDefault); |
||||
|
newDefault.saveConfigTree(); |
||||
|
return; |
||||
|
} |
||||
|
// TEMP: Replace with proper dialog.
|
||||
|
if(!confirm(`Are you sure you want to remove "${configPresetSelected.name}" and all its children?`)) |
||||
|
return; |
||||
|
configPresetSelected.parent.children = configPresetSelected.parent.children.filter(c => c != configPresetSelected); |
||||
|
setConfigPresetSelected(configPresetSelected.parent); |
||||
|
configPresetSelected.saveConfigTree(); |
||||
|
}} |
||||
|
> |
||||
|
<Trash2Icon/> |
||||
|
</button> |
||||
|
</div> |
||||
|
<div className="flex gap-2"> |
||||
|
<button |
||||
|
className="transition-all hover:text-accent mb-4" |
||||
|
title="Import" |
||||
|
onClick={() => { |
||||
|
ConfigPreset.importConfigTree().then( |
||||
|
(root) => { |
||||
|
if(root) { |
||||
|
setConfigPresetRoot(root); |
||||
|
root.saveConfigTree(); |
||||
|
toast({ |
||||
|
title: `Presets successfully imported.` |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
() => {toast({ |
||||
|
title: `This is not a valid configuration file.` |
||||
|
});} |
||||
|
); |
||||
|
}} |
||||
|
> |
||||
|
<UploadIcon/> |
||||
|
</button> |
||||
|
<button |
||||
|
className="transition-all hover:text-accent mb-4" |
||||
|
title="Export" |
||||
|
onClick={() => { |
||||
|
rootConfig.exportConfigTree(); |
||||
|
}} |
||||
|
> |
||||
|
<DownloadIcon/> |
||||
|
</button> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div className='overflow-y-auto'> |
||||
|
{rootConfig && |
||||
|
<ConfigEntry |
||||
|
config={rootConfig} |
||||
|
configPresetSelected={configPresetSelected} |
||||
|
setConfigPresetSelected={setConfigPresetSelected} |
||||
|
editSelected={editSelected} |
||||
|
onConfigCountChanged={(val, diff) => setTotalConfigCountDiff(diff)} |
||||
|
onEditDone={(val) => { |
||||
|
configPresetSelected.name = val; |
||||
|
setEditSelected(false); |
||||
|
configPresetSelected.saveConfigTree(); |
||||
|
} |
||||
|
} |
||||
|
/> |
||||
|
}</div> |
||||
|
</div> |
||||
|
) |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
const ConfigEntry = ({config, configPresetSelected, setConfigPresetSelected, editSelected, onEditDone, onConfigCountChanged}: |
||||
|
{config: ConfigPreset, |
||||
|
configPresetSelected: ConfigPreset, |
||||
|
setConfigPresetSelected: (selection: ConfigPreset) => void, |
||||
|
editSelected: boolean, onEditDone: (value: string) => void, |
||||
|
onConfigCountChanged: (val: number, diff: number) => void |
||||
|
}) => { |
||||
|
const [configCount, setConfigCount] = useState(config.count); |
||||
|
return ( |
||||
|
<div> |
||||
|
<ConfigSelectButton |
||||
|
label={config.name} |
||||
|
active={config == configPresetSelected} |
||||
|
setValue={(value) => {const diff = value - config.count; config.count = value; setConfigCount(value); onConfigCountChanged(value, diff);}} |
||||
|
value={configCount} |
||||
|
editing={editSelected && config == configPresetSelected} |
||||
|
onClick={() => setConfigPresetSelected(config)} |
||||
|
onChangeDone={onEditDone} |
||||
|
/> |
||||
|
<div className="ml-[20px]"> |
||||
|
{config.children.map(c => |
||||
|
(<ConfigEntry |
||||
|
config={c} |
||||
|
configPresetSelected={configPresetSelected} |
||||
|
setConfigPresetSelected={setConfigPresetSelected} |
||||
|
editSelected={editSelected} |
||||
|
onEditDone={onEditDone} |
||||
|
onConfigCountChanged={onConfigCountChanged} |
||||
|
/>) |
||||
|
)} |
||||
|
</div> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
Loading…
Reference in new issue