diff --git a/modules/marketplace/src/components/ModuleCard/index.tsx b/modules/marketplace/src/components/ModuleCard/index.tsx index c57abec..23a0a58 100644 --- a/modules/marketplace/src/components/ModuleCard/index.tsx +++ b/modules/marketplace/src/components/ModuleCard/index.tsx @@ -1,4 +1,5 @@ import { React } from "/modules/stdlib/src/expose/React.ts"; +import { MdDeleteSweep, MdAddCircleOutline } from "https://esm.sh/react-icons/md"; import AuthorsDiv from "./AuthorsDiv.tsx"; import TagsDiv from "./TagsDiv.tsx"; import { @@ -33,11 +34,16 @@ interface ModuleCardProps { moduleInstance: ModuleInstance; selectModule: (moduleIdentifier: ModuleIdentifier | null) => void; isSelected: boolean; + removeModule: (module: Module) => void; updateModule: (module: Module) => void; + addModule: (module: Module) => void; + selectInstance: (moduleInstance: ModuleInstance) => void; } const ModuleCard = (props: ModuleCardProps) => { const { moduleInstance, isSelected } = props; + const module = moduleInstance.getModule(); + const noMetadata = moduleInstance.metadata === null; const metadataURL = moduleInstance.getMetadataURL(); @@ -87,10 +93,7 @@ const ModuleCard = (props: ModuleCardProps) => { const enabledLocalInstance = localModule?.getEnabledInstance(); const showLoaded = enabledLocalInstance?.isInstalled() ?? false; - const isLoaded = React.useCallback( - () => moduleInstance.isLoaded(), - [moduleInstance], - ); + const isLoaded = React.useCallback(() => moduleInstance.isLoaded(), [moduleInstance]); const [loaded, setLoaded, updateLoaded] = useUpdate(isLoaded); @@ -100,13 +103,11 @@ const ModuleCard = (props: ModuleCardProps) => { if (moduleInstance.canLoad()) { setLoaded(true); hasChanged = await moduleInstance.load(); - } } else { if (moduleInstance.canUnload()) { setLoaded(false); hasChanged = await moduleInstance.unload(); - } } @@ -117,9 +118,98 @@ const ModuleCard = (props: ModuleCardProps) => { } }; - // TODO: implement (add, install, enable) and (disable, delete, remove) buttons - const buttons = ( + const fastDelete = async () => { + const module = moduleInstance.getModule(); + + dis: if (moduleInstance.isEnabled()) { + if (module.canDisable(moduleInstance)) { + if (await module.disable()) { + props.updateModule(module); + break dis; + } + } + return false; + } + + del: if (moduleInstance.isInstalled()) { + if (moduleInstance.canDelete()) { + if (await moduleInstance.delete()) { + props.updateModule(module); + break del; + } + } + return false; + } + + rem: if (moduleInstance.isLocal()) { + if (moduleInstance.canInstallRemove()) { + if (await moduleInstance.remove()) { + if (module.parent) { + props.updateModule(module); + } else { + props.removeModule(module); + } + break rem; + } + } + return false; + } + return true; + }; + const fastInstall = async () => { + let localModuleInstance = moduleInstance; + let localModule = localModuleInstance.getModule(); + + add: if (!moduleInstance.isLocal()) { + if (moduleInstance.canAdd()) { + localModuleInstance = await moduleInstance.add(); + if (localModuleInstance) { + localModule = localModuleInstance.getModule(); + props.addModule(localModule); + props.selectInstance(localModuleInstance); + break add; + } + } + return false; + } + + ins: if (!localModuleInstance.isInstalled()) { + if (localModuleInstance.canInstallRemove()) { + if (await localModuleInstance.install()) { + props.updateModule(localModule); + break ins; + } + } + return false; + } + + ena: if (!localModuleInstance.isEnabled()) { + if (localModule.canEnable(localModuleInstance)) { + if (await localModule.enable(localModuleInstance)) { + props.updateModule(localModule); + break ena; + } + } + return false; + } + return true; + }; + + const isInstalled = moduleInstance.isInstalled(); + const fastInstallDeleteButton = isInstalled ? ( <> + + Reset + + ) : ( + <> + + Install + + ); + + const footer = ( +
{showLoaded && SettingsToggle && ( { onSelected={onToggleLoaded} /> )} - + +
); return ( @@ -143,7 +247,7 @@ const ModuleCard = (props: ModuleCardProps) => { tags={tags} importantTags={importantTags} > - {buttons} + {footer} ); }; @@ -215,15 +319,9 @@ const ModuleCardContent = (props: ModuleCardContentProps) => { {description || "No description for this package"}

- -
-
- {children} +
+
{children}
diff --git a/modules/marketplace/src/pages/Marketplace.tsx b/modules/marketplace/src/pages/Marketplace.tsx index 7cae906..e386991 100644 --- a/modules/marketplace/src/pages/Marketplace.tsx +++ b/modules/marketplace/src/pages/Marketplace.tsx @@ -74,7 +74,10 @@ export default React.memo(() => { updateModules, updateModule, + removeModule, selectModule, + addModule, + selectInstance, } = useModules(); React.useEffect(() => { @@ -87,7 +90,10 @@ export default React.memo(() => { moduleToInstance={moduleToInstance} selectedModule={selectedModule} updateModule={updateModule} + removeModule={removeModule} selectModule={selectModule} + addModule={addModule} + selectInstance={selectInstance} /> ); }); @@ -97,7 +103,10 @@ interface MarketplaceContentProps { moduleToInstance: Record; selectedModule: ModuleIdentifier | null; updateModule: (module: Module) => void; + removeModule: (module: Module) => void; selectModule: (moduleIdentifier: ModuleIdentifier | null) => void; + addModule: (module: Module) => void; + selectInstance: (moduleInstance: ModuleInstance) => void; } const MarketplaceContent = (props: MarketplaceContentProps) => { const [searchbar, search] = useSearchBar({ @@ -114,7 +123,7 @@ const MarketplaceContent = (props: MarketplaceContentProps) => { selectedFilters.map(({ key }) => getProp(filterFNs, key) as typeof filterFNs); const selectedFilterFNs = React.useMemo(getSelectedFilterFNs, [selectedFilters]); - const { modules, updateModule, moduleToInstance, selectedModule, selectModule } = props; + const { modules, updateModule, selectInstance, addModule, removeModule, moduleToInstance, selectedModule, selectModule } = props; const instances = React.useMemo(() => Array.from(Object.values(moduleToInstance)), [moduleToInstance]); @@ -163,8 +172,11 @@ const MarketplaceContent = (props: MarketplaceContentProps) => { isSelected={isSelected} selectModule={selectModule} updateModule={updateModule} + removeModule={removeModule} + addModule={addModule} // @ts-ignore ensures rerender modules={modules[moduleIdentifier]} + selectInstance={selectInstance} /> ); })}