mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-08 03:08:02 +00:00
refactor: remove unused automation dropdown components
Two dropdown components in the automations area, one for folders and one for terminals, are not imported by any route or component. Both were superseded by a different picker that is in use today. This removes around 265 lines. Two English translation keys lose their last consumer with them and are left in place, since regenerating the locale catalogues does not belong in this change.
This commit is contained in:
parent
8a42aa53e8
commit
b5ce7f9f8f
2 changed files with 0 additions and 266 deletions
|
|
@ -1,148 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import { folders } from '$lib/stores';
|
||||
import { decodeString } from '$lib/utils';
|
||||
|
||||
import Select from '$lib/components/common/Select.svelte';
|
||||
import Check from '$lib/components/icons/Check.svelte';
|
||||
import ChevronDown from '$lib/components/icons/ChevronDown.svelte';
|
||||
import Folder from '$lib/components/icons/Folder.svelte';
|
||||
import Search from '$lib/components/icons/Search.svelte';
|
||||
import XMark from '$lib/components/icons/XMark.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
export let folder_id = '';
|
||||
export let side: 'top' | 'bottom' = 'top';
|
||||
export let align: 'start' | 'end' = 'start';
|
||||
export let onChange: () => void = () => {};
|
||||
|
||||
let folderSearch = '';
|
||||
|
||||
const folderName = (folder: any) => decodeString(folder?.name ?? $i18n.t('Folder'));
|
||||
|
||||
const folderPath = (folder: any) => {
|
||||
const names: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
let current = folder;
|
||||
|
||||
while (current?.parent_id && !seen.has(current.parent_id)) {
|
||||
seen.add(current.parent_id);
|
||||
const parent = folderById.get(current.parent_id);
|
||||
if (!parent) break;
|
||||
names.unshift(folderName(parent));
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return names.join(' / ');
|
||||
};
|
||||
|
||||
$: folderOptions = [...((($folders ?? []) as any[]) ?? [])]
|
||||
.filter((folder) => folder?.id && !folder?.shared)
|
||||
.sort((a, b) => folderName(a).localeCompare(folderName(b)));
|
||||
$: folderById = new Map(folderOptions.map((folder) => [folder.id, folder]));
|
||||
$: selectedFolder = folderOptions.find((folder) => folder.id === folder_id);
|
||||
$: folderLabel = selectedFolder ? folderName(selectedFolder) : $i18n.t('Choose folder');
|
||||
$: normalizedSearch = folderSearch.trim().toLowerCase();
|
||||
$: filteredFolderOptions = normalizedSearch
|
||||
? folderOptions.filter((folder) =>
|
||||
`${folderName(folder)} ${folderPath(folder)}`.toLowerCase().includes(normalizedSearch)
|
||||
)
|
||||
: folderOptions;
|
||||
</script>
|
||||
|
||||
<Select
|
||||
bind:value={folder_id}
|
||||
items={folderOptions.map((folder) => ({ value: folder.id, label: folderName(folder) }))}
|
||||
placeholder={$i18n.t('Choose folder')}
|
||||
{align}
|
||||
{side}
|
||||
triggerClass="relative h-8 max-w-[11rem] flex items-center gap-1.5 px-2.5 py-1.5 bg-transparent rounded-2xl text-xs font-normal text-gray-600 transition hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100"
|
||||
contentClass="w-72 shadow-lg"
|
||||
maxHeight="18rem"
|
||||
onChange={() => onChange()}
|
||||
onClose={() => {
|
||||
folderSearch = '';
|
||||
}}
|
||||
>
|
||||
<svelte:fragment slot="trigger">
|
||||
<Folder className="size-3.5 shrink-0" />
|
||||
<div class="inline-flex h-input min-w-0 flex-1 truncate bg-transparent outline-hidden">
|
||||
{folderLabel}
|
||||
</div>
|
||||
|
||||
{#if folder_id}
|
||||
<button
|
||||
class="outline-none"
|
||||
type="button"
|
||||
on:click|stopPropagation={() => {
|
||||
folder_id = '';
|
||||
folderSearch = '';
|
||||
onChange();
|
||||
}}
|
||||
aria-label={$i18n.t('Clear')}
|
||||
>
|
||||
<XMark className="size-3.5" />
|
||||
</button>
|
||||
{:else}
|
||||
<ChevronDown className="size-2.5 shrink-0" strokeWidth="2.5" />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment let:selectItem>
|
||||
<div class="flex items-center gap-1.5 px-2 py-1">
|
||||
<Search className="size-3.5 shrink-0" strokeWidth="2.5" />
|
||||
<input
|
||||
bind:value={folderSearch}
|
||||
class="w-full bg-transparent text-[0.8125rem] outline-hidden"
|
||||
placeholder={$i18n.t('Search folders')}
|
||||
autocomplete="off"
|
||||
on:click|stopPropagation
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if folderOptions.length > 0}
|
||||
<hr class="mx-1 my-0.5 border-gray-50/30 dark:border-gray-800/30" />
|
||||
<div class="px-2 py-1 text-[0.6875rem] text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('Folders')}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#each filteredFolderOptions as folder (folder.id)}
|
||||
{@const path = folderPath(folder)}
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-[1.6875rem] w-full cursor-pointer items-center justify-between gap-2 rounded-xl bg-transparent px-2 text-[0.8125rem] hover:bg-gray-50/40 hover:text-gray-900 dark:hover:bg-gray-800/40 dark:hover:text-gray-100 {folder_id ===
|
||||
folder.id
|
||||
? 'text-gray-900 dark:text-gray-100'
|
||||
: 'text-gray-700 dark:text-gray-300'}"
|
||||
title={path ? `${path} / ${folderName(folder)}` : folderName(folder)}
|
||||
on:click={() => {
|
||||
selectItem({
|
||||
value: folder_id === folder.id ? '' : folder.id,
|
||||
label: folder_id === folder.id ? $i18n.t('Choose folder') : folderName(folder)
|
||||
});
|
||||
folderSearch = '';
|
||||
}}
|
||||
>
|
||||
<div class="flex min-w-0 items-center gap-1.5">
|
||||
<Folder className="size-3.5 shrink-0" />
|
||||
<span class="min-w-0 truncate">{folderName(folder)}</span>
|
||||
{#if path}
|
||||
<span class="min-w-0 truncate text-[0.6875rem] text-gray-400 dark:text-gray-500">
|
||||
{path}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if folder_id === folder.id}
|
||||
<Check className="size-3.5 shrink-0" strokeWidth="2" />
|
||||
{/if}
|
||||
</button>
|
||||
{:else}
|
||||
<div class="px-2 py-1 text-[0.6875rem] text-gray-500 dark:text-gray-400">
|
||||
{folderOptions.length > 0 ? $i18n.t('No results found') : $i18n.t('No folders')}
|
||||
</div>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
</Select>
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import type { TerminalServer } from '$lib/apis/terminal/index';
|
||||
|
||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||
import Cloud from '$lib/components/icons/Cloud.svelte';
|
||||
|
||||
const i18n = getContext('i18n');
|
||||
|
||||
export let terminalServers: TerminalServer[] = [];
|
||||
export let terminalServerId = '';
|
||||
export let terminalCwd = '';
|
||||
|
||||
export let side: 'top' | 'bottom' = 'top';
|
||||
export let align: 'start' | 'end' = 'start';
|
||||
|
||||
/** Optional callback when selection changes */
|
||||
export let onChange: () => void = () => {};
|
||||
|
||||
let showDropdown = false;
|
||||
|
||||
$: terminalLabel = terminalServerId
|
||||
? terminalServers.find((s) => s.id === terminalServerId)?.name || 'Terminal'
|
||||
: $i18n.t('Terminal');
|
||||
</script>
|
||||
|
||||
{#if terminalServers.length > 0}
|
||||
<Dropdown bind:show={showDropdown} {side} {align}>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
||||
{terminalServerId ? 'text-black dark:text-gray-100' : 'text-gray-600 dark:text-gray-400'}
|
||||
hover:text-gray-900 dark:hover:text-gray-100"
|
||||
>
|
||||
<Cloud className="size-3.5 shrink-0" strokeWidth="2" />
|
||||
<span class="whitespace-nowrap max-w-32 truncate">{terminalLabel}</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="2"
|
||||
stroke="currentColor"
|
||||
class="size-2.5"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div
|
||||
slot="content"
|
||||
class="rounded-xl shadow-lg border border-gray-200 dark:border-gray-800 flex flex-col bg-white dark:bg-gray-850 min-w-56 max-w-56 p-0.5"
|
||||
>
|
||||
<div class="px-2 text-[0.6875rem] text-gray-500 py-0.5">
|
||||
{$i18n.t('Terminal')}
|
||||
</div>
|
||||
|
||||
{#each terminalServers as server (server.id)}
|
||||
<button
|
||||
class="flex w-full h-[1.6875rem] justify-between gap-2 items-center px-2 text-[0.8125rem] cursor-pointer rounded-xl {terminalServerId ===
|
||||
server.id
|
||||
? 'text-gray-900 dark:text-gray-100'
|
||||
: 'text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100'}"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
if (terminalServerId === server.id) {
|
||||
terminalServerId = '';
|
||||
terminalCwd = '';
|
||||
} else {
|
||||
terminalServerId = server.id;
|
||||
}
|
||||
showDropdown = false;
|
||||
onChange();
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-1 gap-2 items-center truncate">
|
||||
<Cloud className="size-3.5 shrink-0" strokeWidth="2" />
|
||||
<span class="truncate">{server.name || server.id}</span>
|
||||
</div>
|
||||
{#if terminalServerId === server.id}
|
||||
<div class="shrink-0 text-emerald-600 dark:text-emerald-400">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="size-3.5"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
{#if terminalServerId}
|
||||
<div class="border-t border-gray-100 dark:border-gray-800 mt-1 pt-1">
|
||||
<div class="px-2 py-0.5 text-[0.6875rem] text-gray-500">
|
||||
{$i18n.t('Working Directory')}
|
||||
</div>
|
||||
<div class="px-2">
|
||||
<input
|
||||
type="text"
|
||||
bind:value={terminalCwd}
|
||||
placeholder="/home/user/project"
|
||||
class="w-full bg-transparent outline-hidden text-[0.8125rem] py-1 placeholder:text-gray-400 dark:placeholder:text-gray-600"
|
||||
on:click={(e) => e.stopPropagation()}
|
||||
on:input={onChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Dropdown>
|
||||
{/if}
|
||||
Loading…
Add table
Reference in a new issue