fix(#248): resolve parent UUID to name in TagParentPicker dropdown subtitle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,14 +7,27 @@ import { createTypeahead } from '$lib/hooks/useTypeahead.svelte';
|
|||||||
|
|
||||||
type Tag = components['schemas']['Tag'];
|
type Tag = components['schemas']['Tag'];
|
||||||
|
|
||||||
|
interface FlatTagRef {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
parentId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name: string;
|
name: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
excludeIds?: string[];
|
excludeIds?: string[];
|
||||||
initialName?: string;
|
initialName?: string;
|
||||||
|
allTags?: FlatTagRef[];
|
||||||
}
|
}
|
||||||
|
|
||||||
let { name, value = $bindable(''), excludeIds = [], initialName = '' }: Props = $props();
|
let {
|
||||||
|
name,
|
||||||
|
value = $bindable(''),
|
||||||
|
excludeIds = [],
|
||||||
|
initialName = '',
|
||||||
|
allTags = []
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
// displayName must be both prop-derived AND locally writable (user typing), so $state +
|
// displayName must be both prop-derived AND locally writable (user typing), so $state +
|
||||||
// $effect is the correct pattern here — writable $derived is read-only and won't work.
|
// $effect is the correct pattern here — writable $derived is read-only and won't work.
|
||||||
@@ -135,7 +148,8 @@ function handleKeydown(e: KeyboardEvent) {
|
|||||||
>
|
>
|
||||||
<span class="block truncate font-medium">{tag.name}</span>
|
<span class="block truncate font-medium">{tag.name}</span>
|
||||||
{#if tag.parentId}
|
{#if tag.parentId}
|
||||||
<span class="block truncate text-xs text-ink-3">{tag.parentId}</span>
|
{@const parentName = allTags.find((t) => t.id === tag.parentId)?.name ?? tag.parentId}
|
||||||
|
<span class="block truncate text-xs text-ink-3">{parentName}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -162,3 +162,35 @@ describe('TagParentPicker – ARIA combobox', () => {
|
|||||||
expect(option.id).toBe('parentId-option-0');
|
expect(option.id).toBe('parentId-option-0');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ─── Parent name resolution ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe('TagParentPicker – parent name subtitle', () => {
|
||||||
|
it('shows parent name instead of UUID when allTags is provided', async () => {
|
||||||
|
mockFetchWithTags([{ id: 't2', name: 'Keller', parentId: 't1' }]);
|
||||||
|
const allTags = [
|
||||||
|
{ id: 't1', name: 'Haus', documentCount: 5 },
|
||||||
|
{ id: 't2', name: 'Keller', parentId: 't1', documentCount: 2 }
|
||||||
|
];
|
||||||
|
render(TagParentPicker, { name: 'parentId', allTags });
|
||||||
|
|
||||||
|
const input = page.getByRole('combobox');
|
||||||
|
await input.fill('K');
|
||||||
|
await vi.advanceTimersByTimeAsync(300);
|
||||||
|
|
||||||
|
await expect.element(page.getByText('Haus')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows nothing as subtitle when tag has no parentId', async () => {
|
||||||
|
mockFetchWithTags([{ id: 't1', name: 'Haus' }]);
|
||||||
|
const allTags = [{ id: 't1', name: 'Haus', documentCount: 5 }];
|
||||||
|
render(TagParentPicker, { name: 'parentId', allTags });
|
||||||
|
|
||||||
|
const input = page.getByRole('combobox');
|
||||||
|
await input.fill('H');
|
||||||
|
await vi.advanceTimersByTimeAsync(300);
|
||||||
|
|
||||||
|
// Only the tag name should appear (no subtitle)
|
||||||
|
await expect.element(page.getByRole('option', { name: 'Haus' })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ const colors = [
|
|||||||
bind:value={parentId}
|
bind:value={parentId}
|
||||||
excludeIds={[data.tag.id]}
|
excludeIds={[data.tag.id]}
|
||||||
initialName={parentName}
|
initialName={parentName}
|
||||||
|
allTags={data.tags}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user