fix: fix id renaming in apps

This commit is contained in:
Ruben Fiszel
2025-07-27 23:15:19 +00:00
parent 99285caf87
commit 255490e4ca
4 changed files with 63 additions and 44 deletions
@@ -1,24 +1,40 @@
<script lang="ts">
import { stopPropagation, createBubbler } from 'svelte/legacy'
const bubble = createBubbler()
import { ArrowRight } from 'lucide-svelte'
import { Button } from './common'
import { createEventDispatcher } from 'svelte'
import { untrack } from 'svelte'
import { forbiddenIds } from './flows/idUtils'
import { slide } from 'svelte/transition'
export let initialId: string
export let reservedIds: string[] = []
export let label: string = 'Component ID'
export let value = initialId
export let buttonText = ''
export let btnClasses = '!p-1 !w-[34px] !ml-1'
export let acceptUnderScores = false
interface Props {
initialId: string
reservedIds?: string[]
label?: string
value?: any
buttonText?: string
btnClasses?: string
acceptUnderScores?: boolean
onSave: ({ oldId, newId }: { oldId: string; newId: string }) => void
onClose?: () => void
}
let error = ''
const dispatch = createEventDispatcher()
let {
initialId,
reservedIds = [],
label = 'Component ID',
value = $bindable(initialId),
buttonText = '',
btnClasses = '!p-1 !w-[34px] !ml-1',
acceptUnderScores = false,
onSave,
onClose
}: Props = $props()
let error = $state('')
const regex = acceptUnderScores ? /^[a-zA-Z][a-zA-Z0-9_]*$/ : /^[a-zA-Z][a-zA-Z0-9]*$/
$: validateId(value, reservedIds)
function validateId(id: string, reservedIds: string[]) {
if (id == initialId) {
error = ''
@@ -35,9 +51,14 @@
}
}
let inputDiv: HTMLInputElement | undefined = undefined
let inputDiv: HTMLInputElement | undefined = $state(undefined)
$: inputDiv?.focus()
$effect(() => {
untrack(() => validateId(value, reservedIds))
})
$effect(() => {
inputDiv?.focus()
})
</script>
<label class="block text-primary">
@@ -50,15 +71,17 @@
type="text"
bind:value
class="!w-auto grow"
on:click|stopPropagation={() => {}}
on:keydown|stopPropagation={({ key }) => {
onclick={stopPropagation(() => {})}
onkeydown={(e) => {
e.stopPropagation()
let key = e.key
if (key === 'Enter' && error === '' && value !== initialId) {
dispatch('save', value)
onSave({ oldId: initialId, newId: value })
} else if (key == 'Escape') {
dispatch('close')
onClose?.()
}
}}
on:keypress|stopPropagation
onkeypress={stopPropagation(bubble('keypress'))}
/>
<Button
size="xs"
@@ -67,8 +90,8 @@
{btnClasses}
aria-label="Save ID"
disabled={error != '' || value === initialId}
on:click={() => {
dispatch('save', value)
onclick={() => {
onSave({ oldId: initialId, newId: value })
}}
>
{buttonText}<ArrowRight size={18} />
@@ -2,7 +2,7 @@
import type { AppViewerContext } from '$lib/components/apps/types'
import { allItems } from '$lib/components/apps/utils'
import { Pencil } from 'lucide-svelte'
import { createEventDispatcher, getContext } from 'svelte'
import { getContext } from 'svelte'
import IdEditorInput from '$lib/components/IdEditorInput.svelte'
import Popover from '$lib/components/meltComponents/Popover.svelte'
@@ -10,11 +10,11 @@
interface Props {
id: string
onChange: ({ oldId, newId }: { oldId: string; newId: string }) => void
onClose?: () => void
}
let { id }: Props = $props()
const dispatch = createEventDispatcher()
let { id, onChange, onClose }: Props = $props()
let reservedIds = $derived(allItems($app.grid, $app.subgrids).map((item) => item.id))
</script>
@@ -39,10 +39,10 @@
{#snippet content({ close })}
<IdEditorInput
initialId={id}
on:close={() => close()}
on:save={(e) => {
dispatch('save', e.detail)
close()
{onClose}
onSave={(e) => {
onChange(e)
onClose?.()
}}
{reservedIds}
/>
@@ -74,7 +74,7 @@
indigo: 'bg-indigo-500 text-white'
}
function renameId(newId: string): void {
function renameId(oldId: string, newId: string): void {
const item = findGridItem($app, id)
if (!item) {
@@ -84,12 +84,12 @@
item.id = newId
const oldSubgrids = Object.keys($app.subgrids ?? {}).filter((subgrid) =>
subgrid.startsWith(id + '-')
subgrid.startsWith(oldId + '-')
)
oldSubgrids.forEach((subgrid) => {
if ($app.subgrids) {
$app.subgrids[subgrid.replace(id, newId)] = $app.subgrids[subgrid]
$app.subgrids[subgrid.replace(oldId, newId)] = $app.subgrids[subgrid]
delete $app.subgrids[subgrid]
}
})
@@ -103,11 +103,11 @@
processRunnable(from, to, x)
})
}
propagateRename(id, newId)
propagateRename(oldId, newId)
if (item?.data.type == 'tablecomponent') {
for (let c of item.data.actionButtons) {
let old = c.id
c.id = c.id.replace(id + '_', newId + '_')
c.id = c.id.replace(oldId + '_', newId + '_')
propagateRename(old, c.id)
}
}
@@ -121,7 +121,7 @@
) {
for (let c of item.data.actions ?? []) {
let old = c.id
c.id = c.id.replace(id + '_', newId + '_')
c.id = c.id.replace(oldId + '_', newId + '_')
propagateRename(old, c.id)
}
}
@@ -129,7 +129,7 @@
if (item?.data.type === 'menucomponent') {
for (let c of item.data.menuItems) {
let old = c.id
c.id = c.id.replace(id + '_', newId + '_')
c.id = c.id.replace(oldId + '_', newId + '_')
propagateRename(old, c.id)
}
}
@@ -277,11 +277,7 @@
</button>
{#if selectable && renamable && $selectedComponent?.includes(id)}
<div class="h-3">
<IdEditor
{id}
on:selected={() => ($selectedComponent = [id])}
on:save={({ detail }) => renameId(detail)}
/></div
<IdEditor {id} onChange={({ oldId, newId }) => renameId(oldId, newId)} /></div
>
{/if}
</div>
@@ -225,11 +225,11 @@
acceptUnderScores
reservedIds={dfs(flowStore?.val?.value.modules ?? [], (x) => x.id)}
bind:value={newId}
on:save={(e) => {
dispatch('changeId', { id, newId: e.detail, deps: getDeps?.dependents ?? {} })
onSave={({ oldId, newId }) => {
dispatch('changeId', { id: oldId, newId, deps: getDeps?.dependents ?? {} })
editId = false
}}
on:close={() => {
onClose={() => {
editId = false
}}
/>