feat: mark already-added images as disabled in EntityPicker

This commit is contained in:
2026-03-28 15:16:37 +03:00
parent 3a644b3b0b
commit 62a9249abf
3 changed files with 33 additions and 8 deletions
+24 -6
View File
@@ -104,7 +104,7 @@
case 'Enter': {
event.preventDefault();
const item = flatFiltered[highlightIndex];
if (item) {
if (item && !item.disabled) {
onselect(item.value);
}
break;
@@ -121,8 +121,9 @@
onclose();
}
function handleItemClick(value: string) {
onselect(value);
function handleItemClick(item: EntityPickerItem) {
if (item.disabled) return;
onselect(item.value);
}
/** Track the flat index across groups for highlight matching. */
@@ -204,18 +205,22 @@
<button
type="button"
class="entity-picker-item"
class:entity-picker-item--highlighted={isHighlighted}
class:entity-picker-item--highlighted={isHighlighted && !item.disabled}
class:entity-picker-item--current={isCurrent}
class:entity-picker-item--disabled={item.disabled}
data-highlighted={isHighlighted}
onclick={() => handleItemClick(item.value)}
onclick={() => handleItemClick(item)}
onmouseenter={() => { highlightIndex = flatIdx; }}
disabled={item.disabled}
>
{#if item.icon}
<span class="entity-picker-item-icon">{@html item.icon}</span>
{/if}
<span class="entity-picker-item-content">
<span class="entity-picker-item-label">{item.label}</span>
{#if item.description}
{#if item.disabledHint}
<span class="entity-picker-item-hint">{item.disabledHint}</span>
{:else if item.description}
<span class="entity-picker-item-description">{item.description}</span>
{/if}
</span>
@@ -422,4 +427,17 @@
overflow: hidden;
text-overflow: ellipsis;
}
.entity-picker-item--disabled {
opacity: 0.45;
cursor: default;
pointer-events: none;
}
.entity-picker-item-hint {
font-size: var(--text-xs);
color: var(--text-tertiary);
font-style: italic;
white-space: nowrap;
}
</style>
+2
View File
@@ -144,6 +144,8 @@ export interface EntityPickerItem {
description?: string;
icon?: string;
group?: string;
disabled?: boolean;
disabledHint?: string;
}
/** Volume mount configuration for a project. */
+7 -2
View File
@@ -33,17 +33,22 @@
imagePickerLoading = true;
try {
const registries = await api.listRegistries();
// Collect existing project images to mark as already added.
const existingImages = new Set(projects.map(p => p.image.toLowerCase()));
const items: EntityPickerItem[] = [];
for (const reg of registries) {
if (!reg.owner) continue;
try {
const images = await api.listRegistryImages(reg.id);
for (const img of images) {
const alreadyAdded = existingImages.has(img.full_ref.toLowerCase());
items.push({
value: JSON.stringify({ full_ref: img.full_ref, registryName: reg.name }),
label: img.full_ref,
description: reg.name,
group: reg.name
description: alreadyAdded ? undefined : reg.name,
group: reg.name,
disabled: alreadyAdded,
disabledHint: alreadyAdded ? 'Already added' : undefined
});
}
} catch {