From c64f1e5363c28363e049e1cd241d927191ca9840 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sat, 28 Mar 2026 14:43:27 +0300 Subject: [PATCH] feat: inline project editing (name, image, port, healthcheck) --- web/src/routes/projects/[id]/+page.svelte | 113 ++++++++++++++++++---- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/web/src/routes/projects/[id]/+page.svelte b/web/src/routes/projects/[id]/+page.svelte index 8d4df0a..70bab3a 100644 --- a/web/src/routes/projects/[id]/+page.svelte +++ b/web/src/routes/projects/[id]/+page.svelte @@ -7,7 +7,7 @@ import ConfirmDialog from '$lib/components/ConfirmDialog.svelte'; import EmptyState from '$lib/components/EmptyState.svelte'; import Skeleton from '$lib/components/Skeleton.svelte'; - import { IconTrash, IconKey, IconHardDrive, IconDeploy, IconChevronRight, IconClock, IconTag, IconLoader, IconPlus } from '$lib/components/icons'; + import { IconTrash, IconKey, IconHardDrive, IconDeploy, IconChevronRight, IconClock, IconTag, IconLoader, IconPlus, IconEdit, IconCheck, IconX } from '$lib/components/icons'; import FormField from '$lib/components/FormField.svelte'; import { toasts } from '$lib/stores/toast'; import { t } from '$lib/i18n'; @@ -55,6 +55,43 @@ } } + // Edit project + let editing = $state(false); + let editName = $state(''); + let editImage = $state(''); + let editPort = $state(''); + let editHealthcheck = $state(''); + let saving = $state(false); + + function startEditing() { + if (!project) return; + editName = project.name; + editImage = project.image; + editPort = String(project.port || ''); + editHealthcheck = project.healthcheck || ''; + editing = true; + } + + async function saveProject() { + if (!editName.trim() || !editImage.trim()) return; + saving = true; + try { + await api.updateProject(projectId, { + name: editName.trim(), + image: editImage.trim(), + port: parseInt(editPort) || 0, + healthcheck: editHealthcheck.trim(), + }); + toasts.success('Project updated'); + editing = false; + await loadProject(); + } catch (e) { + toasts.error(e instanceof Error ? e.message : 'Failed to update project'); + } finally { + saving = false; + } + } + async function handleDeleteStage(stageId: string, name: string) { try { await api.deleteStage(projectId, stageId); @@ -225,23 +262,63 @@ -
-
-

{$t('projects.port')}

-

{project.port || '-'}

-
-
-

{$t('projects.registry')}

-

{project.registry || '-'}

-
-
-

{$t('projects.healthcheck')}

-

{project.healthcheck || '-'}

-
-
-

{$t('projects.created')}

-

{new Date(project.created_at).toLocaleDateString()}

-
+
+ {#if editing} +
+ + + + +
+
+ + +
+ {:else} +
+
+
+

{$t('projects.port')}

+

{project.port || 'Auto'}

+
+
+

{$t('projects.healthcheck')}

+

{project.healthcheck || 'Auto'}

+
+
+

{$t('projects.registry')}

+

{project.registry || '-'}

+
+
+

{$t('projects.created')}

+

{new Date(project.created_at).toLocaleDateString()}

+
+
+ +
+ {/if}