mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 16:02:28 +00:00
feat: add inline-editable summary field to group header
Click the group name in edit mode to rename it inline. The input replaces the label, saves on blur/Enter, and cancels on Escape. Wired from both GroupOverlay and CollapsedGroupNode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { getNodeColorClasses } from '$lib/components/graph'
|
||||
import { NOTE_COLORS, NoteColor } from './noteColors'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { preventDefault, stopPropagation } from 'svelte/legacy'
|
||||
import GroupNoteArea from './GroupNoteArea.svelte'
|
||||
|
||||
interface Props {
|
||||
@@ -14,6 +15,7 @@
|
||||
note?: string
|
||||
showNote?: boolean
|
||||
editMode?: boolean
|
||||
onSummaryUpdate?: (text: string) => void
|
||||
onNoteUpdate?: (text: string) => void
|
||||
onHeightChange?: (height: number) => void
|
||||
}
|
||||
@@ -27,6 +29,7 @@
|
||||
note,
|
||||
showNote = false,
|
||||
editMode = false,
|
||||
onSummaryUpdate,
|
||||
onNoteUpdate,
|
||||
onHeightChange
|
||||
}: Props = $props()
|
||||
@@ -37,6 +40,37 @@
|
||||
|
||||
let defaultColorClasses = $derived(getNodeColorClasses(undefined, selected))
|
||||
|
||||
// Inline summary editing
|
||||
let editingSummary = $state(false)
|
||||
let summaryInput = $state('')
|
||||
let summaryInputElement: HTMLInputElement | undefined = $state(undefined)
|
||||
|
||||
function startEditingSummary() {
|
||||
if (!editMode) return
|
||||
editingSummary = true
|
||||
summaryInput = summary ?? ''
|
||||
requestAnimationFrame(() => {
|
||||
summaryInputElement?.focus()
|
||||
summaryInputElement?.select()
|
||||
})
|
||||
}
|
||||
|
||||
function saveSummary() {
|
||||
editingSummary = false
|
||||
const trimmed = summaryInput.trim()
|
||||
if (trimmed !== (summary ?? '')) {
|
||||
onSummaryUpdate?.(trimmed)
|
||||
}
|
||||
}
|
||||
|
||||
function handleSummaryKeydown(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter') {
|
||||
saveSummary()
|
||||
} else if (event.key === 'Escape') {
|
||||
editingSummary = false
|
||||
}
|
||||
}
|
||||
|
||||
// Reset height to 0 when note is hidden
|
||||
$effect(() => {
|
||||
if (!showNote) {
|
||||
@@ -63,7 +97,27 @@
|
||||
></div>
|
||||
<div class="flex items-center w-full gap-1.5 px-2 h-[34px] relative z-1">
|
||||
<Group size={14} />
|
||||
<span class="text-2xs font-medium truncate">{summary || 'Group'}</span>
|
||||
{#if editingSummary}
|
||||
<input
|
||||
bind:this={summaryInputElement}
|
||||
bind:value={summaryInput}
|
||||
class="text-2xs font-medium bg-transparent border-none p-0 m-0 outline-none min-w-0 flex-1 nodrag nowheel"
|
||||
placeholder="Group"
|
||||
onblur={saveSummary}
|
||||
onkeydown={handleSummaryKeydown}
|
||||
onclick={stopPropagation(preventDefault(() => {}))}
|
||||
onpointerdown={stopPropagation(() => {})}
|
||||
spellcheck="false"
|
||||
/>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<span
|
||||
class="text-2xs font-medium truncate {editMode ? 'cursor-text hover:opacity-80' : ''}"
|
||||
onclick={editMode ? stopPropagation(preventDefault(startEditingSummary)) : undefined}
|
||||
onpointerdown={editMode ? stopPropagation(preventDefault(() => {})) : undefined}
|
||||
>{summary || 'Group'}</span>
|
||||
{/if}
|
||||
{#if stepCount != null}
|
||||
<span class="text-2xs opacity-60">{stepCount} node{stepCount !== 1 ? 's' : ''}</span>
|
||||
{/if}
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
note={group.note}
|
||||
showNote={showNotes && group.note != null}
|
||||
{editMode}
|
||||
onSummaryUpdate={(text) => groupEditorContext?.groupEditor.updateSummary(group.id, text)}
|
||||
onNoteUpdate={(text) => groupEditorContext?.groupEditor.updateNote(group.id, text)}
|
||||
onHeightChange={(h) => groupEditorContext?.groupEditor.setNoteHeight(group.id, h)}
|
||||
/>
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
note={data.note}
|
||||
showNote={data.showNotes && data.note != null}
|
||||
editMode={data.editMode}
|
||||
onSummaryUpdate={(text) =>
|
||||
groupEditorContext?.groupEditor.updateSummary(data.groupId, text)}
|
||||
onNoteUpdate={(text) =>
|
||||
groupEditorContext?.groupEditor.updateNote(data.groupId, text)}
|
||||
onHeightChange={(h) =>
|
||||
|
||||
Reference in New Issue
Block a user