diff --git a/.changeset/purple-symbols-remain.md b/.changeset/purple-symbols-remain.md new file mode 100644 index 000000000..37fe937f1 --- /dev/null +++ b/.changeset/purple-symbols-remain.md @@ -0,0 +1,5 @@ +--- +"@workflow/web": patch +--- + +Add PostgreSQL backend support in web UI settings diff --git a/packages/web/package.json b/packages/web/package.json index f46a757d2..eec8149d3 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -28,6 +28,14 @@ "dependencies": { "next": "15.5.4" }, + "peerDependencies": { + "@workflow/world-postgres": "*" + }, + "peerDependenciesMeta": { + "@workflow/world-postgres": { + "optional": true + } + }, "devDependencies": { "@biomejs/biome": "catalog:", "@radix-ui/react-alert-dialog": "1.1.5", @@ -51,6 +59,7 @@ "react": "19.1.0", "react-dom": "19.1.0", "sonner": "2.0.7", + "swr": "2.3.6", "tailwind-merge": "2.5.5", "tailwindcss": "4", "typescript": "catalog:" diff --git a/packages/web/src/components/settings-sidebar.tsx b/packages/web/src/components/settings-sidebar.tsx index f5affa3ba..3b3682e53 100644 --- a/packages/web/src/components/settings-sidebar.tsx +++ b/packages/web/src/components/settings-sidebar.tsx @@ -1,7 +1,7 @@ /** biome-ignore-all lint/correctness/useUniqueElementIds: */ 'use client'; -import { AlertCircle, Settings, X } from 'lucide-react'; +import { AlertCircle, AlertTriangle, Settings, X } from 'lucide-react'; import { useEffect, useState } from 'react'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Button } from '@/components/ui/button'; @@ -20,6 +20,7 @@ import { validateWorldConfig, type WorldConfig, } from '@/lib/config-world'; +import { useWorldsAvailability } from '@/lib/hooks'; export function SettingsSidebar() { const config = useQueryParamConfig(); @@ -30,8 +31,12 @@ export function SettingsSidebar() { const [errors, setErrors] = useState([]); const [isValidating, setIsValidating] = useState(false); + const { data: worldsAvailability = [], isLoading: isLoadingWorlds } = + useWorldsAvailability(); + const backend = localConfig.backend || 'embedded'; const isEmbedded = backend === 'embedded'; + const isPostgres = backend === 'postgres'; // Update local config when query params change useEffect(() => { @@ -121,10 +126,48 @@ export function SettingsSidebar() { - Embedded - Vercel + {isLoadingWorlds ? ( + + Loading worlds... + + ) : worldsAvailability.length > 0 ? ( + worldsAvailability.map((world) => ( + + {world.displayName} + + )) + ) : ( + <> + Embedded + Vercel + PostgreSQL + + )} + {/* Show warning if selected world is not installed */} + {(() => { + const selectedWorld = worldsAvailability.find( + (w) => w.id === backend + ); + if (selectedWorld && !selectedWorld.isInstalled) { + return ( +
+ +
+

Package not installed

+

+ Run:{' '} + + {selectedWorld.installCommand} + +

+
+
+ ); + } + return null; + })()} {isEmbedded && ( @@ -175,7 +218,33 @@ export function SettingsSidebar() { )} - {!isEmbedded && ( + {isPostgres && ( + <> +
+ + + handleInputChange('postgresUrl', e.target.value) + } + placeholder="postgres://user:pass@host:5432/db" + className={ + getFieldError('postgresUrl') + ? 'border-destructive' + : '' + } + /> + {getFieldError('postgresUrl') && ( +

+ {getFieldError('postgresUrl')} +

+ )} +
+ + )} + + {!isEmbedded && !isPostgres && ( <>
@@ -250,7 +319,13 @@ export function SettingsSidebar() {