mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 00:06:06 +00:00
fix: add null guards in hub displayItems filters to prevent TypeError
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
5abcc09617
commit
93ec1ada9c
@@ -47,11 +47,11 @@
|
||||
let result = filteredItems
|
||||
if (summaryFilter) {
|
||||
const s = summaryFilter.toLowerCase()
|
||||
result = result.filter((x) => x.summary.toLowerCase().includes(s))
|
||||
result = result.filter((x) => (x.summary ?? '').toLowerCase().includes(s))
|
||||
}
|
||||
if (pathFilter) {
|
||||
const p = pathFilter.toLowerCase()
|
||||
result = result.filter((x) => x.path.toLowerCase().includes(p))
|
||||
result = result.filter((x) => (x.path ?? '').toLowerCase().includes(p))
|
||||
}
|
||||
return result
|
||||
})
|
||||
@@ -74,68 +74,69 @@
|
||||
{#if $disableHubStore}
|
||||
<!-- Hub disabled, show nothing -->
|
||||
{:else}
|
||||
<SearchItems
|
||||
{filter}
|
||||
items={prefilteredItems}
|
||||
bind:filteredItems
|
||||
f={(x) => x.summary + ' (' + x.apps.join(', ') + ')'}
|
||||
/>
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Apps'
|
||||
}}
|
||||
bind:value={filter}
|
||||
class="grow !pr-9"
|
||||
{size}
|
||||
<SearchItems
|
||||
{filter}
|
||||
items={prefilteredItems}
|
||||
bind:filteredItems
|
||||
f={(x) => x.summary + ' (' + x.apps.join(', ') + ')'}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Apps'
|
||||
}}
|
||||
bind:value={filter}
|
||||
class="grow !pr-9"
|
||||
{size}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if hubApps}
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary">
|
||||
{#each displayItems as item (item)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow justify-between hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => dispatch('pick', item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="app" />
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the
|
||||
Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if hubApps}
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary">
|
||||
{#each displayItems as item (item)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow justify-between hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => dispatch('pick', item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="app" />
|
||||
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
{:else}
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
{:else}
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="min-w-1/3 gap-2 flex flex-wrap justify-end">
|
||||
{#each item.apps as app}
|
||||
<Badge color="gray" baseClass="border">{app}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<div class="min-w-1/3 gap-2 flex flex-wrap justify-end">
|
||||
{#each item.apps as app}
|
||||
<Badge color="gray" baseClass="border">{app}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
let result = filteredItems
|
||||
if (summaryFilter) {
|
||||
const s = summaryFilter.toLowerCase()
|
||||
result = result.filter((x) => x.summary.toLowerCase().includes(s))
|
||||
result = result.filter((x) => (x.summary ?? '').toLowerCase().includes(s))
|
||||
}
|
||||
if (pathFilter) {
|
||||
const p = pathFilter.toLowerCase()
|
||||
result = result.filter((x) => x.path.toLowerCase().includes(p))
|
||||
result = result.filter((x) => (x.path ?? '').toLowerCase().includes(p))
|
||||
}
|
||||
return result
|
||||
})
|
||||
@@ -74,70 +74,71 @@
|
||||
{#if $disableHubStore}
|
||||
<!-- Hub disabled, show nothing -->
|
||||
{:else}
|
||||
<SearchItems
|
||||
{filter}
|
||||
items={prefilteredItems}
|
||||
bind:filteredItems
|
||||
f={(x) => x.summary + ' (' + x.apps.join(', ') + ')'}
|
||||
/>
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Flows'
|
||||
}}
|
||||
bind:value={filter}
|
||||
{size}
|
||||
class="grow !pr-9"
|
||||
<SearchItems
|
||||
{filter}
|
||||
items={prefilteredItems}
|
||||
bind:filteredItems
|
||||
f={(x) => x.summary + ' (' + x.apps.join(', ') + ')'}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Flows'
|
||||
}}
|
||||
bind:value={filter}
|
||||
{size}
|
||||
class="grow !pr-9"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if hubFlows}
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary overflow-hidden">
|
||||
{#each displayItems as item (item)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow justify-between hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => dispatch('pick', item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="flow" />
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the
|
||||
Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if hubFlows}
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary overflow-hidden">
|
||||
{#each displayItems as item (item)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow justify-between hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => dispatch('pick', item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<RowIcon kind="flow" />
|
||||
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
{:else}
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold">
|
||||
{#if item.marked}
|
||||
{@html item.marked ?? ''}
|
||||
{:else}
|
||||
{item.summary ?? ''}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="min-w-1/3 gap-2 flex flex-wrap justify-end">
|
||||
{#each item.apps as app}
|
||||
<Badge color="gray" baseClass="border">{app}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="my-2"></div>
|
||||
<div class="min-w-1/3 gap-2 flex flex-wrap justify-end">
|
||||
{#each item.apps as app}
|
||||
<Badge color="gray" baseClass="border">{app}</Badge>
|
||||
{/each}
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="my-2"></div>
|
||||
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[[4], 0.5]} />
|
||||
{/each}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -143,11 +143,11 @@
|
||||
let result = items
|
||||
if (summaryFilter) {
|
||||
const s = summaryFilter.toLowerCase()
|
||||
result = result.filter((x) => x.summary.toLowerCase().includes(s))
|
||||
result = result.filter((x) => (x.summary ?? '').toLowerCase().includes(s))
|
||||
}
|
||||
if (pathFilter) {
|
||||
const p = pathFilter.toLowerCase()
|
||||
result = result.filter((x) => x.path.toLowerCase().includes(p))
|
||||
result = result.filter((x) => (x.path ?? '').toLowerCase().includes(p))
|
||||
}
|
||||
return result
|
||||
})
|
||||
@@ -165,74 +165,75 @@
|
||||
{#if $disableHubStore}
|
||||
<!-- Hub disabled, show nothing -->
|
||||
{:else}
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<div class="relative w-full">
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Scripts'
|
||||
}}
|
||||
bind:value={filter}
|
||||
class="grow !pr-9"
|
||||
{size}
|
||||
/>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin text-gray-400 absolute right-2 top-1" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if (items.length > 0 && apps.length > 0) || !loading}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary">
|
||||
{#each displayItems as item (item.path)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => handlePick(item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex justify-center items-center">
|
||||
{#if item['app'] in APP_TO_ICON_COMPONENT}
|
||||
{@const SvelteComponent = APP_TO_ICON_COMPONENT[item['app']]}
|
||||
<SvelteComponent height={18} width={18} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold mb-1">
|
||||
{item.summary ?? ''}
|
||||
</div>
|
||||
<div class="text-secondary text-2xs font-normal">
|
||||
{item.path}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#if kind !== 'script'}
|
||||
<Badge color="gray" baseClass="border">{capitalize(kind)}</Badge>
|
||||
{/if}
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{#if displayItems.length == 20}
|
||||
<div class="text-primary text-xs font-normal py-4">
|
||||
There are more items than being displayed. Refine your search.
|
||||
{#if !hideSearchbar}
|
||||
<div class="w-full flex items-center gap-2">
|
||||
{@render children?.()}
|
||||
<div class="relative w-full">
|
||||
<TextInput
|
||||
inputProps={{
|
||||
placeholder: 'Search Hub Scripts'
|
||||
}}
|
||||
bind:value={filter}
|
||||
class="grow !pr-9"
|
||||
{size}
|
||||
/>
|
||||
{#if loading}
|
||||
<Loader2 class="animate-spin text-gray-400 absolute right-2 top-1" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[0.5, [4]]} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
{#if hubNotAvailable}
|
||||
<Alert type="warning" title="Hub not available">
|
||||
Could not connect to the Windmill Hub. If you are in a closed environment, you can disable the
|
||||
Hub in the <a href="/#superadmin-settings?tab=private_hub">instance settings</a>.
|
||||
</Alert>
|
||||
{:else if (items.length > 0 && apps.length > 0) || !loading}
|
||||
<ListFilters {syncQuery} filters={apps} bind:selectedFilter={appFilter} resourceType />
|
||||
{#if displayItems.length == 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<ul class="divide-y border rounded-md bg-surface-tertiary">
|
||||
{#each displayItems as item (item.path)}
|
||||
<li class="flex flex-row w-full">
|
||||
<button
|
||||
class="p-4 gap-4 flex flex-row grow hover:bg-surface-hover transition-all items-center"
|
||||
onclick={() => handlePick(item)}
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex justify-center items-center">
|
||||
{#if item['app'] in APP_TO_ICON_COMPONENT}
|
||||
{@const SvelteComponent = APP_TO_ICON_COMPONENT[item['app']]}
|
||||
<SvelteComponent height={18} width={18} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="w-full text-left">
|
||||
<div class="text-emphasis flex-wrap text-xs font-semibold mb-1">
|
||||
{item.summary ?? ''}
|
||||
</div>
|
||||
<div class="text-secondary text-2xs font-normal">
|
||||
{item.path}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#if kind !== 'script'}
|
||||
<Badge color="gray" baseClass="border">{capitalize(kind)}</Badge>
|
||||
{/if}
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{#if displayItems.length == 20}
|
||||
<div class="text-primary text-xs font-normal py-4">
|
||||
There are more items than being displayed. Refine your search.
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
{#each Array(10).fill(0) as _}
|
||||
<Skeleton layout={[0.5, [4]]} />
|
||||
{/each}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user