refac
This commit is contained in:
1 parent
a9617ca218
commit
34813573fa
34 files changed
+554
-652
No files matched your search
@@ -33,12 +33,12 @@
|
|||||||
import GarbageBin from '../icons/GarbageBin.svelte';
|
import GarbageBin from '../icons/GarbageBin.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
import Plus from '../icons/Plus.svelte';
|
import Plus from '../icons/Plus.svelte';
|
||||||
import ChevronRight from '../icons/ChevronRight.svelte';
|
|
||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import AddFunctionMenu from './Functions/AddFunctionMenu.svelte';
|
import AddFunctionMenu from './Functions/AddFunctionMenu.svelte';
|
||||||
import ImportModal from '../ImportModal.svelte';
|
import ImportModal from '../ImportModal.svelte';
|
||||||
import ViewSelector from '../workspace/common/ViewSelector.svelte';
|
import ViewSelector from '../workspace/common/ViewSelector.svelte';
|
||||||
import TagSelector from '../workspace/common/TagSelector.svelte';
|
import TagSelector from '../workspace/common/TagSelector.svelte';
|
||||||
|
import CommunityDiscover from '../workspace/common/CommunityDiscover.svelte';
|
||||||
import { capitalizeFirstLetter } from '$lib/utils';
|
import { capitalizeFirstLetter } from '$lib/utils';
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
|
|
||||||
@@ -352,11 +352,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 flex-1 items-center w-full gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1">
|
||||||
<div class="px-3.5 flex flex-1 items-center w-full space-x-2 py-0.5 pb-2">
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -381,47 +379,49 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
>
|
||||||
localStorage.workspaceViewOption = value;
|
<ViewSelector
|
||||||
|
bind:value={viewOption}
|
||||||
|
align="end"
|
||||||
|
onChange={async (value) => {
|
||||||
|
localStorage.workspaceViewOption = value;
|
||||||
|
|
||||||
await tick();
|
await tick();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TagSelector
|
<TagSelector
|
||||||
bind:value={selectedType}
|
bind:value={selectedType}
|
||||||
items={[
|
align="end"
|
||||||
{ value: 'pipe', label: $i18n.t('Pipe') },
|
items={[
|
||||||
{ value: 'filter', label: $i18n.t('Filter') },
|
{ value: 'pipe', label: $i18n.t('Pipe') },
|
||||||
{ value: 'action', label: $i18n.t('Action') },
|
{ value: 'filter', label: $i18n.t('Filter') },
|
||||||
{ value: 'event', label: $i18n.t('Event') }
|
{ value: 'action', label: $i18n.t('Action') },
|
||||||
]}
|
{ value: 'event', label: $i18n.t('Event') }
|
||||||
/>
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if (filteredItems ?? []).length !== 0}
|
{#if (filteredItems ?? []).length !== 0}
|
||||||
<div class="px-3 my-2 gap-1 lg:gap-2 grid lg:grid-cols-2">
|
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2">
|
||||||
{#each filteredItems as func (func.id)}
|
{#each filteredItems as func (func.id)}
|
||||||
<div
|
<div
|
||||||
class=" flex space-x-4 cursor-pointer w-full px-2 py-2 dark:hover:bg-white/5 hover:bg-black/5 rounded-xl"
|
class="flex space-x-4 cursor-pointer w-full px-2.5 py-1.5 rounded-2xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class=" flex flex-1 space-x-3.5 cursor-pointer w-full"
|
class=" flex flex-1 space-x-3.5 cursor-pointer w-full"
|
||||||
@@ -606,30 +606,11 @@
|
|||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
{#if $config?.features.enable_community_sharing}
|
{#if $config?.features.enable_community_sharing}
|
||||||
<div class=" my-16">
|
<CommunityDiscover
|
||||||
<div class=" text-xl font-medium mb-1 line-clamp-1">
|
href="https://openwebui.com/functions"
|
||||||
{$i18n.t('Made by Open WebUI Community')}
|
title={$i18n.t('Discover a function')}
|
||||||
</div>
|
description={$i18n.t('Discover, download, and explore custom functions')}
|
||||||
|
/>
|
||||||
<a
|
|
||||||
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
|
|
||||||
href="https://openwebui.com/functions"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class=" self-center">
|
|
||||||
<div class=" font-semibold line-clamp-1">{$i18n.t('Discover a function')}</div>
|
|
||||||
<div class=" text-sm line-clamp-1">
|
|
||||||
{$i18n.t('Discover, download, and explore custom functions')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<ChevronRight />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editHandler();
|
editHandler();
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cloneHandler();
|
cloneHandler();
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
runHandler();
|
runHandler();
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
||||||
text-gray-600 dark:text-gray-400 hover:bg-black/5 dark:hover:bg-white/5"
|
text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -91,8 +91,8 @@
|
|||||||
{#each filteredModels as model (model.id)}
|
{#each filteredModels as model (model.id)}
|
||||||
<button
|
<button
|
||||||
class="h-[1.6875rem] px-2 rounded-xl w-full text-left text-[13px] {model_id === model.id
|
class="h-[1.6875rem] px-2 rounded-xl w-full text-left text-[13px] {model_id === model.id
|
||||||
? 'bg-gray-50 dark:bg-gray-800'
|
? '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"
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
model_id = model.id;
|
model_id = model.id;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
||||||
text-gray-600 dark:text-gray-400 hover:bg-black/5 dark:hover:bg-white/5"
|
text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-100"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -284,7 +284,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="flex-1 py-1 text-xs rounded-xl transition {selectedDays.includes(d.key)
|
class="flex-1 py-1 text-xs rounded-xl transition {selectedDays.includes(d.key)
|
||||||
? 'bg-gray-50 dark:bg-gray-800 text-black dark:text-gray-100'
|
? 'text-black dark:text-gray-100'
|
||||||
: 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-200'}"
|
: 'text-gray-400 dark:text-gray-500 hover:text-gray-700 dark:hover:text-gray-200'}"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (selectedDays.includes(d.key)) {
|
if (selectedDays.includes(d.key)) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-2xl text-xs transition
|
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'}
|
{terminalServerId ? 'text-black dark:text-gray-100' : 'text-gray-600 dark:text-gray-400'}
|
||||||
hover:bg-black/5 dark:hover:bg-white/5"
|
hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
>
|
>
|
||||||
<Cloud className="size-3.5 shrink-0" strokeWidth="2" />
|
<Cloud className="size-3.5 shrink-0" strokeWidth="2" />
|
||||||
<span class="whitespace-nowrap max-w-32 truncate">{terminalLabel}</span>
|
<span class="whitespace-nowrap max-w-32 truncate">{terminalLabel}</span>
|
||||||
@@ -59,8 +59,8 @@
|
|||||||
<button
|
<button
|
||||||
class="flex w-full h-[1.6875rem] justify-between gap-2 items-center px-2 text-[13px] cursor-pointer rounded-xl {terminalServerId ===
|
class="flex w-full h-[1.6875rem] justify-between gap-2 items-center px-2 text-[13px] cursor-pointer rounded-xl {terminalServerId ===
|
||||||
server.id
|
server.id
|
||||||
? 'bg-gray-50 dark:bg-gray-800/50'
|
? 'text-gray-900 dark:text-gray-100'
|
||||||
: 'hover:bg-gray-50 dark:hover:bg-gray-800/50'}"
|
: 'text-gray-700 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100'}"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (terminalServerId === server.id) {
|
if (terminalServerId === server.id) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`rounded-xl! p-0.5! border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg ${className} [&>button]:flex [&>button]:w-full [&>button]:h-[1.6875rem] [&>button]:items-center [&>button]:gap-2 [&>button]:rounded-xl! [&>button]:px-2! [&>button]:text-[13px] [&>button:hover]:bg-gray-50/60 dark:[&>button:hover]:bg-gray-800/60 [&>a]:flex [&>a]:w-full [&>a]:h-[1.6875rem] [&>a]:items-center [&>a]:gap-2 [&>a]:rounded-xl! [&>a]:px-2! [&>a]:text-[13px] [&>a:hover]:bg-gray-50/60 dark:[&>a:hover]:bg-gray-800/60 [&>button_svg]:size-3.5 [&>a_svg]:size-3.5 [&>hr]:my-0.5 [&>hr]:mx-1`}
|
class={`rounded-xl! p-0.5! border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg ${className} [&_button:hover]:bg-transparent! [&_a:hover]:bg-transparent! [&_button:hover]:text-gray-900 dark:[&_button:hover]:text-gray-100 [&_a:hover]:text-gray-900 dark:[&_a:hover]:text-gray-100 [&>button]:flex [&>button]:w-full [&>button]:h-[1.6875rem]! [&>button]:items-center [&>button]:gap-2! [&>button]:rounded-xl! [&>button]:bg-transparent [&>button]:px-2! [&>button]:text-[13px]! [&>button]:font-normal! [&>a]:flex [&>a]:w-full [&>a]:h-[1.6875rem]! [&>a]:items-center [&>a]:gap-2! [&>a]:rounded-xl! [&>a]:bg-transparent [&>a]:px-2! [&>a]:text-[13px]! [&>a]:font-normal! [&_button_svg]:size-3.5! [&_a_svg]:size-3.5! [&>hr]:my-0.5 [&>hr]:mx-1`}
|
||||||
{style}
|
{style}
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
{align}
|
{align}
|
||||||
triggerClass={className
|
triggerClass={className
|
||||||
? className
|
? className
|
||||||
: 'flex shrink-0 items-center gap-2 bg-transparent px-0.5 text-sm placeholder-gray-400 outline-hidden focus:outline-hidden'}
|
: 'flex h-8 shrink-0 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition placeholder-gray-400 outline-hidden hover:text-gray-900 focus:outline-hidden dark:text-gray-200 dark:hover:text-gray-100'}
|
||||||
itemClass="flex w-full h-[1.6875rem] gap-2 items-center rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
itemClass="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
onChange(v);
|
onChange(v);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
/** CSS classes for each item button */
|
/** CSS classes for each item button */
|
||||||
export let itemClass =
|
export let itemClass =
|
||||||
'flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl';
|
'flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100';
|
||||||
|
|
||||||
/** Alignment of the dropdown: 'start' | 'end' */
|
/** Alignment of the dropdown: 'start' | 'end' */
|
||||||
export let align = 'start';
|
export let align = 'start';
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px] font-primary">
|
<DropdownMenu className="min-w-[170px] font-primary">
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] hover:bg-gray-50/60 dark:hover:bg-gray-800/60 transition"
|
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
onEdit();
|
onEdit();
|
||||||
show = false;
|
show = false;
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] hover:bg-gray-50/60 dark:hover:bg-gray-800/60 transition"
|
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onChat();
|
onChat();
|
||||||
show = false;
|
show = false;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
$: loadLocale($i18n.languages);
|
$: loadLocale($i18n.languages);
|
||||||
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { WEBUI_NAME, config, user, pinnedNotes } from '$lib/stores';
|
import { WEBUI_NAME, config, user, pinnedNotes, mobile, showSidebar } from '$lib/stores';
|
||||||
import {
|
import {
|
||||||
createNewNote,
|
createNewNote,
|
||||||
deleteNoteById,
|
deleteNoteById,
|
||||||
@@ -47,7 +47,6 @@
|
|||||||
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
import Plus from '../icons/Plus.svelte';
|
import Plus from '../icons/Plus.svelte';
|
||||||
import ChevronRight from '../icons/ChevronRight.svelte';
|
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
import Tooltip from '../common/Tooltip.svelte';
|
import Tooltip from '../common/Tooltip.svelte';
|
||||||
import NoteMenu from './Notes/NoteMenu.svelte';
|
import NoteMenu from './Notes/NoteMenu.svelte';
|
||||||
@@ -55,6 +54,7 @@
|
|||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import DropdownOptions from '../common/DropdownOptions.svelte';
|
import DropdownOptions from '../common/DropdownOptions.svelte';
|
||||||
import Loader from '../common/Loader.svelte';
|
import Loader from '../common/Loader.svelte';
|
||||||
|
import SidebarIcon from '../icons/Sidebar.svelte';
|
||||||
|
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
|
|
||||||
@@ -324,7 +324,7 @@
|
|||||||
|
|
||||||
<FilesOverlay show={dragged} />
|
<FilesOverlay show={dragged} />
|
||||||
|
|
||||||
<div id="notes-container" class="w-full min-h-full h-full px-3 md:px-[18px]">
|
<div id="notes-container" class="w-full min-h-full h-full">
|
||||||
{#if loaded}
|
{#if loaded}
|
||||||
<DeleteConfirmDialog
|
<DeleteConfirmDialog
|
||||||
bind:show={showDeleteConfirm}
|
bind:show={showDeleteConfirm}
|
||||||
@@ -339,15 +339,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</DeleteConfirmDialog>
|
</DeleteConfirmDialog>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
||||||
|
{#if $mobile}
|
||||||
|
<Tooltip content={$showSidebar ? $i18n.t('Close Sidebar') : $i18n.t('Open Sidebar')}>
|
||||||
|
<button
|
||||||
|
id="sidebar-toggle-button"
|
||||||
|
class="cursor-pointer flex rounded-lg hover:bg-gray-100 dark:hover:bg-gray-850 transition"
|
||||||
|
on:click={() => {
|
||||||
|
showSidebar.set(!$showSidebar);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="self-center p-1.5">
|
||||||
|
<SidebarIcon />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{$i18n.t('Notes')}
|
{$i18n.t('Notes')}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-lg font-medium text-gray-500 dark:text-gray-500">
|
<div class="text-lg font-medium text-gray-500 dark:text-gray-500">
|
||||||
{total}
|
{total ?? ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -364,17 +380,15 @@
|
|||||||
>
|
>
|
||||||
<Plus className="size-3" strokeWidth="2.5" />
|
<Plus className="size-3" strokeWidth="2.5" />
|
||||||
|
|
||||||
<div class=" ml-1 text-xs">{$i18n.t('New Note')}</div>
|
<div class="hidden md:block md:ml-1 text-xs">{$i18n.t('New Note')}</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 flex-1 items-center w-full gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1 items-center">
|
||||||
<div class="px-3.5 flex flex-1 items-center w-full space-x-2 py-0.5 pb-2">
|
|
||||||
<div class="flex flex-1 items-center">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -399,11 +413,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-3 flex justify-between">
|
|
||||||
<div
|
<div
|
||||||
class="flex w-full bg-transparent overflow-x-auto scrollbar-none"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
on:wheel={(e) => {
|
on:wheel={(e) => {
|
||||||
if (e.deltaY !== 0) {
|
if (e.deltaY !== 0) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -412,11 +424,10 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex gap-3 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<DropdownOptions
|
<DropdownOptions
|
||||||
align="start"
|
align="end"
|
||||||
className="flex shrink-0 items-center gap-2 px-3 py-1.5 text-sm bg-gray-50 dark:bg-gray-850 rounded-xl placeholder-gray-400 outline-hidden focus:outline-hidden"
|
|
||||||
bind:value={viewOption}
|
bind:value={viewOption}
|
||||||
items={[
|
items={[
|
||||||
{ value: null, label: $i18n.t('All') },
|
{ value: null, label: $i18n.t('All') },
|
||||||
@@ -434,7 +445,7 @@
|
|||||||
|
|
||||||
{#if [null, 'shared'].includes(viewOption)}
|
{#if [null, 'shared'].includes(viewOption)}
|
||||||
<DropdownOptions
|
<DropdownOptions
|
||||||
align="start"
|
align="end"
|
||||||
bind:value={permission}
|
bind:value={permission}
|
||||||
items={[
|
items={[
|
||||||
{ value: null, label: $i18n.t('Write') },
|
{ value: null, label: $i18n.t('Write') },
|
||||||
@@ -442,25 +453,23 @@
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="shrink-0">
|
<DropdownOptions
|
||||||
<DropdownOptions
|
align="end"
|
||||||
align="start"
|
bind:value={displayOption}
|
||||||
bind:value={displayOption}
|
items={[
|
||||||
items={[
|
{ value: null, label: $i18n.t('List') },
|
||||||
{ value: null, label: $i18n.t('List') },
|
{ value: 'grid', label: $i18n.t('Grid') }
|
||||||
{ value: 'grid', label: $i18n.t('Grid') }
|
]}
|
||||||
]}
|
onChange={() => {
|
||||||
onChange={() => {
|
if (displayOption) {
|
||||||
if (displayOption) {
|
localStorage.noteDisplayOption = displayOption;
|
||||||
localStorage.noteDisplayOption = displayOption;
|
} else {
|
||||||
} else {
|
delete localStorage.noteDisplayOption;
|
||||||
delete localStorage.noteDisplayOption;
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -468,22 +477,20 @@
|
|||||||
{#if (items ?? []).length > 0}
|
{#if (items ?? []).length > 0}
|
||||||
{@const groupedNotes = groupNotes(items)}
|
{@const groupedNotes = groupNotes(items)}
|
||||||
|
|
||||||
<div class="@container h-full py-2.5 px-2.5">
|
<div class="@container h-full my-1">
|
||||||
<div class="">
|
<div class="">
|
||||||
{#each groupedNotes as [timeRange, notesList], idx}
|
{#each groupedNotes as [timeRange, notesList], idx}
|
||||||
<div
|
<div class="w-full text-xs text-gray-500 dark:text-gray-500 px-2.5 pb-2.5">
|
||||||
class="w-full text-xs text-gray-500 dark:text-gray-500 font-medium px-2.5 pb-2.5"
|
|
||||||
>
|
|
||||||
{$i18n.t(timeRange)}
|
{$i18n.t(timeRange)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if displayOption === null}
|
{#if displayOption === null}
|
||||||
<div
|
<div
|
||||||
class="{groupedNotes.length - 1 !== idx ? 'mb-3' : ''} gap-1.5 flex flex-col"
|
class="{groupedNotes.length - 1 !== idx ? 'mb-3' : ''} gap-y-0.5 flex flex-col"
|
||||||
>
|
>
|
||||||
{#each notesList as note, idx (note.id)}
|
{#each notesList as note, idx (note.id)}
|
||||||
<div
|
<div
|
||||||
class=" flex cursor-pointer w-full px-3.5 py-1.5 border border-gray-50 dark:border-gray-850/30 bg-transparent dark:hover:bg-gray-850 hover:bg-white rounded-2xl transition"
|
class="flex cursor-pointer w-full px-3 py-2 bg-transparent hover:bg-gray-50/70 dark:hover:bg-gray-850/50 rounded-2xl transition"
|
||||||
>
|
>
|
||||||
<a href={`/notes/${note.id}`} class="w-full flex flex-col justify-between">
|
<a href={`/notes/${note.id}`} class="w-full flex flex-col justify-between">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
@@ -493,9 +500,7 @@
|
|||||||
className="flex-1"
|
className="flex-1"
|
||||||
placement="top-start"
|
placement="top-start"
|
||||||
>
|
>
|
||||||
<div
|
<div class="text-sm capitalize flex-1 w-full line-clamp-1">
|
||||||
class=" text-sm font-medium capitalize flex-1 w-full line-clamp-1"
|
|
||||||
>
|
|
||||||
{note.title}
|
{note.title}
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -555,7 +560,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="self-center w-fit text-sm p-1 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
|
class="self-center w-fit text-sm p-1 text-gray-500 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100 rounded-xl"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<EllipsisHorizontal className="size-5" />
|
<EllipsisHorizontal className="size-5" />
|
||||||
@@ -577,7 +582,7 @@
|
|||||||
>
|
>
|
||||||
{#each notesList as note, idx (note.id)}
|
{#each notesList as note, idx (note.id)}
|
||||||
<div
|
<div
|
||||||
class=" flex space-x-4 cursor-pointer w-full px-4.5 py-4 border border-gray-50 dark:border-gray-850/30 bg-transparent dark:hover:bg-gray-850 hover:bg-white rounded-2xl transition"
|
class="flex space-x-4 cursor-pointer w-full px-3 py-2.5 bg-transparent hover:bg-gray-50/70 dark:hover:bg-gray-850/50 rounded-2xl transition"
|
||||||
>
|
>
|
||||||
<div class=" flex flex-1 space-x-4 cursor-pointer w-full">
|
<div class=" flex flex-1 space-x-4 cursor-pointer w-full">
|
||||||
<a
|
<a
|
||||||
@@ -588,7 +593,7 @@
|
|||||||
<div
|
<div
|
||||||
class=" flex items-center gap-2 self-center mb-1 justify-between"
|
class=" flex items-center gap-2 self-center mb-1 justify-between"
|
||||||
>
|
>
|
||||||
<div class=" font-semibold line-clamp-1 capitalize">
|
<div class="line-clamp-1 capitalize">
|
||||||
{note.title}
|
{note.title}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -625,7 +630,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="self-center w-fit text-sm p-1 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
|
class="self-center w-fit text-sm p-1 text-gray-500 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100 rounded-xl"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<EllipsisHorizontal className="size-5" />
|
<EllipsisHorizontal className="size-5" />
|
||||||
|
|||||||
@@ -43,14 +43,14 @@
|
|||||||
<DropdownSub contentClass="select-none z-50">
|
<DropdownSub contentClass="select-none z-50">
|
||||||
<button
|
<button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
>
|
>
|
||||||
<Download className="size-3.5" strokeWidth="2" />
|
<Download className="size-3.5" strokeWidth="2" />
|
||||||
<div class="flex items-center">{$i18n.t('Download')}</div>
|
<div class="flex items-center">{$i18n.t('Download')}</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onDownload('txt');
|
onDownload('txt');
|
||||||
}}
|
}}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onDownload('md');
|
onDownload('md');
|
||||||
}}
|
}}
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onDownload('pdf');
|
onDownload('pdf');
|
||||||
}}
|
}}
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<DropdownSub contentClass="select-none z-50">
|
<DropdownSub contentClass="select-none z-50">
|
||||||
<button
|
<button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
>
|
>
|
||||||
<Share className="size-3.5" strokeWidth="2" />
|
<Share className="size-3.5" strokeWidth="2" />
|
||||||
<div class="flex items-center">{$i18n.t('Share')}</div>
|
<div class="flex items-center">{$i18n.t('Share')}</div>
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
{#if onCopyLink}
|
{#if onCopyLink}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onCopyLink();
|
onCopyLink();
|
||||||
}}
|
}}
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
|
|
||||||
{#if onCopyToClipboard}
|
{#if onCopyToClipboard}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onCopyToClipboard();
|
onCopyToClipboard();
|
||||||
}}
|
}}
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
|
|
||||||
{#if onPin}
|
{#if onPin}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onPin();
|
onPin();
|
||||||
show = false;
|
show = false;
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onDelete();
|
onDelete();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px] font-primary">
|
<DropdownMenu className="min-w-[170px] font-primary">
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] hover:bg-gray-50/60 dark:hover:bg-gray-800/60 transition"
|
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
onRecord();
|
onRecord();
|
||||||
show = false;
|
show = false;
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] hover:bg-gray-50/60 dark:hover:bg-gray-800/60 transition"
|
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onCaptureAudio();
|
onCaptureAudio();
|
||||||
show = false;
|
show = false;
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] hover:bg-gray-50/60 dark:hover:bg-gray-800/60 transition"
|
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload();
|
onUpload();
|
||||||
show = false;
|
show = false;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
import Tooltip from '../common/Tooltip.svelte';
|
import Tooltip from '../common/Tooltip.svelte';
|
||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import ViewSelector from './common/ViewSelector.svelte';
|
import ViewSelector from './common/ViewSelector.svelte';
|
||||||
|
import TagSelector from './common/TagSelector.svelte';
|
||||||
import Loader from '../common/Loader.svelte';
|
import Loader from '../common/Loader.svelte';
|
||||||
|
|
||||||
type KnowledgeListItem = {
|
type KnowledgeListItem = {
|
||||||
@@ -187,7 +188,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
||||||
<div>
|
<div>
|
||||||
@@ -212,11 +213,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 w-full items-center gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1">
|
||||||
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -242,52 +241,54 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
|
||||||
localStorage.workspaceViewOption = value;
|
|
||||||
|
|
||||||
await tick();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<select
|
|
||||||
class="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 bg-gray-50 dark:bg-gray-850 rounded-xl outline-hidden"
|
|
||||||
bind:value={sourceOption}
|
|
||||||
on:change={async () => {
|
|
||||||
localStorage.workspaceKnowledgeSourceOption = sourceOption;
|
|
||||||
await tick();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<option value="">{$i18n.t('All Sources')}</option>
|
<ViewSelector
|
||||||
<option value="local">{$i18n.t('Local')}</option>
|
bind:value={viewOption}
|
||||||
<option value="external">{$i18n.t('Connected')}</option>
|
align="end"
|
||||||
</select>
|
onChange={async (value) => {
|
||||||
|
localStorage.workspaceViewOption = value;
|
||||||
|
|
||||||
|
await tick();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TagSelector
|
||||||
|
bind:value={sourceOption}
|
||||||
|
align="end"
|
||||||
|
placeholder={$i18n.t('All Sources')}
|
||||||
|
items={[
|
||||||
|
{ value: 'local', label: $i18n.t('Local') },
|
||||||
|
{ value: 'external', label: $i18n.t('Connected') }
|
||||||
|
]}
|
||||||
|
onChange={async () => {
|
||||||
|
localStorage.workspaceKnowledgeSourceOption = sourceOption;
|
||||||
|
await tick();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if items !== null && total !== null}
|
{#if items !== null && total !== null}
|
||||||
{#if (items ?? []).length !== 0}
|
{#if (items ?? []).length !== 0}
|
||||||
<!-- The Aleph dreams itself into being, and the void learns its own name -->
|
<!-- The Aleph dreams itself into being, and the void learns its own name -->
|
||||||
<div class=" my-2 px-3 grid grid-cols-1 lg:grid-cols-2 gap-2">
|
<div class="my-1 grid grid-cols-1 lg:grid-cols-2 gap-x-2 gap-y-0.5">
|
||||||
{#each items as item}
|
{#each items as item}
|
||||||
<button
|
<button
|
||||||
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
|
class="flex space-x-4 cursor-pointer text-left w-full px-2.5 py-1.5 transition rounded-2xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (item?.meta?.document) {
|
if (item?.meta?.document) {
|
||||||
toast.error(
|
toast.error(
|
||||||
@@ -413,10 +414,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" text-gray-500 text-xs m-2">
|
|
||||||
ⓘ {$i18n.t("Use '#' in the prompt input to load and include your knowledge.")}
|
|
||||||
</div>
|
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full h-full flex justify-center items-center">
|
<div class="w-full h-full flex justify-center items-center">
|
||||||
<Spinner className="size-5" />
|
<Spinner className="size-5" />
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
{#if onExport}
|
{#if onExport}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onExport();
|
onExport();
|
||||||
}}
|
}}
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
dispatch('delete');
|
dispatch('delete');
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1410,7 +1410,7 @@
|
|||||||
|
|
||||||
<Dropdown align="end">
|
<Dropdown align="end">
|
||||||
<button
|
<button
|
||||||
class="p-1.5 mr-1 rounded-xl text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
|
class="p-1.5 mr-1 rounded-xl text-gray-500 bg-transparent hover:text-gray-900 dark:hover:text-gray-100 transition"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<AdjustmentsHorizontal className="size-3.5" strokeWidth="2" />
|
<AdjustmentsHorizontal className="size-3.5" strokeWidth="2" />
|
||||||
@@ -1419,7 +1419,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[180px]">
|
<DropdownMenu className="min-w-[180px]">
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
includeContent = !includeContent;
|
includeContent = !includeContent;
|
||||||
@@ -1482,8 +1482,8 @@
|
|||||||
class="flex gap-3 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
|
class="flex gap-3 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<DropdownOptions
|
<DropdownOptions
|
||||||
align="start"
|
align="end"
|
||||||
className="flex shrink-0 items-center gap-2 px-3 py-1.5 text-sm bg-gray-50 dark:bg-gray-850 rounded-xl placeholder-gray-400 outline-hidden focus:outline-hidden"
|
className="flex h-8 shrink-0 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition placeholder-gray-400 outline-hidden hover:text-gray-900 focus:outline-hidden dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
bind:value={viewOption}
|
bind:value={viewOption}
|
||||||
items={[
|
items={[
|
||||||
{ value: null, label: $i18n.t('All') },
|
{ value: null, label: $i18n.t('All') },
|
||||||
@@ -1500,19 +1500,19 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<DropdownOptions
|
<DropdownOptions
|
||||||
align="start"
|
align="end"
|
||||||
bind:value={sortKey}
|
bind:value={sortKey}
|
||||||
placeholder={$i18n.t('Sort')}
|
placeholder={$i18n.t('Sort')}
|
||||||
items={[
|
items={[
|
||||||
{ value: 'name', label: $i18n.t('Name') },
|
{ value: 'name', label: $i18n.t('Name') },
|
||||||
{ value: 'created_at', label: $i18n.t('Created At') },
|
{ value: 'created_at', label: $i18n.t('Created') },
|
||||||
{ value: 'updated_at', label: $i18n.t('Updated At') }
|
{ value: 'updated_at', label: $i18n.t('Updated') }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if sortKey}
|
{#if sortKey}
|
||||||
<DropdownOptions
|
<DropdownOptions
|
||||||
align="start"
|
align="end"
|
||||||
bind:value={direction}
|
bind:value={direction}
|
||||||
items={[
|
items={[
|
||||||
{ value: 'asc', label: $i18n.t('Asc') },
|
{ value: 'asc', label: $i18n.t('Asc') },
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
>
|
>
|
||||||
<Tooltip content={$i18n.t('Add Content')}>
|
<Tooltip content={$i18n.t('Add Content')}>
|
||||||
<button
|
<button
|
||||||
class=" p-1.5 rounded-xl hover:bg-gray-100 dark:bg-gray-850 dark:hover:bg-gray-800 transition font-medium text-sm flex items-center space-x-1"
|
class="p-1.5 rounded-xl bg-transparent transition text-[13px] font-normal flex items-center space-x-1 hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={(e) => {
|
on:click={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
show = true;
|
show = true;
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[200px] transition">
|
<DropdownMenu className="min-w-[200px] transition">
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload({ type: 'new_directory' });
|
onUpload({ type: 'new_directory' });
|
||||||
show = false;
|
show = false;
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
<hr class="my-1 border-gray-100 dark:border-gray-800" />
|
<hr class="my-1 border-gray-100 dark:border-gray-800" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload({ type: 'files' });
|
onUpload({ type: 'files' });
|
||||||
}}
|
}}
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload({ type: 'directory' });
|
onUpload({ type: 'directory' });
|
||||||
}}
|
}}
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onSync();
|
onSync();
|
||||||
}}
|
}}
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload({ type: 'web' });
|
onUpload({ type: 'web' });
|
||||||
}}
|
}}
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onUpload({ type: 'text' });
|
onUpload({ type: 'text' });
|
||||||
}}
|
}}
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
<hr class="my-1 border-gray-100 dark:border-gray-800" />
|
<hr class="my-1 border-gray-100 dark:border-gray-800" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onReset();
|
onReset();
|
||||||
show = false;
|
show = false;
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
<DropdownMenu className="min-w-[140px] z-[9999999]">
|
<DropdownMenu className="min-w-[140px] z-[9999999]">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => startRename()}
|
on:click={() => startRename()}
|
||||||
>
|
>
|
||||||
<Pencil className="size-3.5" />
|
<Pencil className="size-3.5" />
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => onDelete(directory.id)}
|
on:click={() => onDelete(directory.id)}
|
||||||
>
|
>
|
||||||
<GarbageBin className="size-3.5" />
|
<GarbageBin className="size-3.5" />
|
||||||
|
|||||||
@@ -188,7 +188,7 @@
|
|||||||
<DropdownMenu className="min-w-[140px] z-[9999999]">
|
<DropdownMenu className="min-w-[140px] z-[9999999]">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
startRename(file);
|
startRename(file);
|
||||||
}}
|
}}
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
let fileId = file?.id ?? file?.tempId;
|
let fileId = file?.id ?? file?.tempId;
|
||||||
window.open(`${WEBUI_BASE_URL}/api/v1/files/${fileId}/content`, '_blank');
|
window.open(`${WEBUI_BASE_URL}/api/v1/files/${fileId}/content`, '_blank');
|
||||||
@@ -209,7 +209,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="select-none flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition items-center gap-2 text-sm"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] transition hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
onDelete(file?.id ?? file?.tempId);
|
onDelete(file?.id ?? file?.tempId);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -37,17 +37,18 @@
|
|||||||
import GarbageBin from '../icons/GarbageBin.svelte';
|
import GarbageBin from '../icons/GarbageBin.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
import Plus from '../icons/Plus.svelte';
|
import Plus from '../icons/Plus.svelte';
|
||||||
import ChevronRight from '../icons/ChevronRight.svelte';
|
|
||||||
import Switch from '../common/Switch.svelte';
|
import Switch from '../common/Switch.svelte';
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import EyeSlash from '../icons/EyeSlash.svelte';
|
import EyeSlash from '../icons/EyeSlash.svelte';
|
||||||
import Eye from '../icons/Eye.svelte';
|
import Eye from '../icons/Eye.svelte';
|
||||||
|
import ChevronDown from '../icons/ChevronDown.svelte';
|
||||||
|
|
||||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
|
import DropdownMenu from '$lib/components/common/DropdownMenu.svelte';
|
||||||
import ViewSelector from './common/ViewSelector.svelte';
|
import ViewSelector from './common/ViewSelector.svelte';
|
||||||
import TagSelector from './common/TagSelector.svelte';
|
import TagSelector from './common/TagSelector.svelte';
|
||||||
|
import CommunityDiscover from './common/CommunityDiscover.svelte';
|
||||||
import Pagination from '../common/Pagination.svelte';
|
import Pagination from '../common/Pagination.svelte';
|
||||||
import Badge from '$lib/components/common/Badge.svelte';
|
import Badge from '$lib/components/common/Badge.svelte';
|
||||||
|
|
||||||
@@ -373,7 +374,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<input
|
<input
|
||||||
id="models-import-input"
|
id="models-import-input"
|
||||||
bind:this={modelsImportInputElement}
|
bind:this={modelsImportInputElement}
|
||||||
@@ -481,11 +482,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 flex-1 items-center w-full gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1 items-center">
|
||||||
<div class="px-3.5 flex flex-1 items-center w-full space-x-2 py-0.5 pb-2">
|
|
||||||
<div class="flex flex-1 items-center">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -520,113 +519,114 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-0.5 whitespace-nowrap"
|
class="flex max-w-[60%] shrink-0 items-center gap-1 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
>
|
||||||
localStorage.workspaceViewOption = value;
|
<ViewSelector
|
||||||
await tick();
|
bind:value={viewOption}
|
||||||
}}
|
align="end"
|
||||||
/>
|
onChange={async (value) => {
|
||||||
|
localStorage.workspaceViewOption = value;
|
||||||
{#if (tags ?? []).length > 0}
|
await tick();
|
||||||
<TagSelector
|
}}
|
||||||
bind:value={selectedTag}
|
|
||||||
items={tags.map((tag) => {
|
|
||||||
return { value: tag, label: tag };
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-1"></div>
|
{#if (tags ?? []).length > 0}
|
||||||
|
<TagSelector
|
||||||
<Dropdown>
|
bind:value={selectedTag}
|
||||||
<Tooltip content={$i18n.t('Actions')}>
|
align="end"
|
||||||
<button
|
items={tags.map((tag) => {
|
||||||
class="p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition"
|
return { value: tag, label: tag };
|
||||||
type="button"
|
})}
|
||||||
>
|
/>
|
||||||
<EllipsisHorizontal className="size-4" />
|
{/if}
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<div slot="content">
|
|
||||||
<DropdownMenu className="w-[170px] shadow-sm">
|
|
||||||
<button
|
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
|
||||||
type="button"
|
|
||||||
on:click={() => {
|
|
||||||
enableAllHandler();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CheckCircle className="size-4" />
|
|
||||||
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
|
||||||
type="button"
|
|
||||||
on:click={() => {
|
|
||||||
disableAllHandler();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Minus className="size-4" />
|
|
||||||
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<hr class="border-gray-100 dark:border-gray-800 my-1" />
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
|
||||||
type="button"
|
|
||||||
on:click={() => {
|
|
||||||
showAllHandler();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Eye className="size-4" />
|
|
||||||
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
|
||||||
type="button"
|
|
||||||
on:click={() => {
|
|
||||||
hideAllHandler();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<EyeSlash className="size-4" />
|
|
||||||
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
|
||||||
</button>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
|
||||||
|
<Dropdown align="end">
|
||||||
|
<Tooltip content={$i18n.t('Actions')}>
|
||||||
|
<button
|
||||||
|
class="flex h-8 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>{$i18n.t('Actions')}</span>
|
||||||
|
<ChevronDown className="size-3" strokeWidth="2.5" />
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<div slot="content">
|
||||||
|
<DropdownMenu className="w-[170px] shadow-sm">
|
||||||
|
<button
|
||||||
|
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => {
|
||||||
|
enableAllHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckCircle className="size-3.5" />
|
||||||
|
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => {
|
||||||
|
disableAllHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Minus className="size-3.5" />
|
||||||
|
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<hr class="mx-1 my-0.5 border-gray-100 dark:border-gray-800" />
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => {
|
||||||
|
showAllHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Eye className="size-3.5" />
|
||||||
|
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="flex h-[1.6875rem] w-full cursor-pointer select-none items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => {
|
||||||
|
hideAllHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EyeSlash className="size-3.5" />
|
||||||
|
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
||||||
|
</button>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if models !== null}
|
{#if models !== null}
|
||||||
{#if (models ?? []).length !== 0}
|
{#if (models ?? []).length !== 0}
|
||||||
<div class=" px-3 my-2 gap-1 lg:gap-2 grid lg:grid-cols-2" id="model-list">
|
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2" id="model-list">
|
||||||
{#each models as model (model.id)}
|
{#each models as model (model.id)}
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<div
|
<div
|
||||||
class="flex transition rounded-2xl w-full p-2.5 {model.write_access
|
class="flex transition w-full px-2.5 py-1.5 rounded-2xl {model.write_access
|
||||||
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
|
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
|
||||||
: 'dark:hover:bg-gray-850/50 hover:bg-gray-50'}"
|
: ''}"
|
||||||
id="model-item-{model.id}"
|
id="model-item-{model.id}"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (model.write_access) {
|
if (model.write_access) {
|
||||||
@@ -849,30 +849,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if $config?.features.enable_community_sharing}
|
{#if $config?.features.enable_community_sharing}
|
||||||
<div class=" my-16">
|
<CommunityDiscover
|
||||||
<div class=" text-xl font-medium mb-1 line-clamp-1">
|
href="https://openwebui.com/models"
|
||||||
{$i18n.t('Made by Open WebUI Community')}
|
title={$i18n.t('Discover a model')}
|
||||||
</div>
|
description={$i18n.t('Discover, download, and explore model presets')}
|
||||||
|
/>
|
||||||
<a
|
|
||||||
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
|
|
||||||
href="https://openwebui.com/models"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class=" self-center">
|
|
||||||
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a model')}</div>
|
|
||||||
<div class=" text-sm line-clamp-1">
|
|
||||||
{$i18n.t('Discover, download, and explore model presets')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<ChevronRight />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full h-full flex justify-center items-center">
|
<div class="w-full h-full flex justify-center items-center">
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="h-[1.6875rem] px-2 rounded-xl w-full text-left flex justify-between items-center text-[13px] hover:bg-gray-50/60 hover:dark:bg-gray-800/60 hover:dark:text-gray-100 selected-command-option-button"
|
class="h-[1.6875rem] px-2 rounded-xl w-full text-left flex justify-between items-center text-[13px] bg-transparent hover:text-gray-900 dark:hover:text-gray-100 selected-command-option-button"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="w-full flex-1"
|
class="w-full flex-1"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
{#if writeAccess}
|
{#if writeAccess}
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editHandler();
|
editHandler();
|
||||||
}}
|
}}
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
{#if writeAccess}
|
{#if writeAccess}
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
hideHandler();
|
hideHandler();
|
||||||
}}
|
}}
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
pinModelHandler(model?.id);
|
pinModelHandler(model?.id);
|
||||||
}}
|
}}
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
|
|
||||||
{#if writeAccess}
|
{#if writeAccess}
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cloneHandler();
|
cloneHandler();
|
||||||
}}
|
}}
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
copyLinkHandler();
|
copyLinkHandler();
|
||||||
}}
|
}}
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
|
|
||||||
{#if writeAccess && ($currentUser?.role === 'admin' || $currentUser?.permissions?.workspace?.models_export)}
|
{#if writeAccess && ($currentUser?.role === 'admin' || $currentUser?.permissions?.workspace?.models_export)}
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
exportHandler();
|
exportHandler();
|
||||||
}}
|
}}
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
|
|
||||||
{#if writeAccess && $config?.features.enable_community_sharing}
|
{#if writeAccess && $config?.features.enable_community_sharing}
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
shareHandler();
|
shareHandler();
|
||||||
}}
|
}}
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
<hr class="border-gray-50/30 dark:border-gray-800/30 my-1" />
|
<hr class="border-gray-50/30 dark:border-gray-800/30 my-1" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -23,13 +23,13 @@
|
|||||||
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
import DeleteConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
import Plus from '../icons/Plus.svelte';
|
import Plus from '../icons/Plus.svelte';
|
||||||
import ChevronRight from '../icons/ChevronRight.svelte';
|
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
import Tooltip from '../common/Tooltip.svelte';
|
import Tooltip from '../common/Tooltip.svelte';
|
||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import GarbageBin from '../icons/GarbageBin.svelte';
|
import GarbageBin from '../icons/GarbageBin.svelte';
|
||||||
import ViewSelector from './common/ViewSelector.svelte';
|
import ViewSelector from './common/ViewSelector.svelte';
|
||||||
import TagSelector from './common/TagSelector.svelte';
|
import TagSelector from './common/TagSelector.svelte';
|
||||||
|
import CommunityDiscover from './common/CommunityDiscover.svelte';
|
||||||
import Badge from '$lib/components/common/Badge.svelte';
|
import Badge from '$lib/components/common/Badge.svelte';
|
||||||
import Switch from '../common/Switch.svelte';
|
import Switch from '../common/Switch.svelte';
|
||||||
import Pagination from '../common/Pagination.svelte';
|
import Pagination from '../common/Pagination.svelte';
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</DeleteConfirmDialog>
|
</DeleteConfirmDialog>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<input
|
<input
|
||||||
id="prompts-import-input"
|
id="prompts-import-input"
|
||||||
bind:this={promptsImportInputElement}
|
bind:this={promptsImportInputElement}
|
||||||
@@ -323,11 +323,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 w-full items-center gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1">
|
||||||
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -354,36 +352,38 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
>
|
||||||
localStorage.workspaceViewOption = value;
|
<ViewSelector
|
||||||
page = 1;
|
bind:value={viewOption}
|
||||||
await tick();
|
align="end"
|
||||||
}}
|
onChange={async (value) => {
|
||||||
/>
|
localStorage.workspaceViewOption = value;
|
||||||
|
page = 1;
|
||||||
{#if (tags ?? []).length > 0}
|
await tick();
|
||||||
<TagSelector
|
}}
|
||||||
bind:value={selectedTag}
|
|
||||||
items={tags.map((tag) => ({ value: tag, label: tag }))}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
|
||||||
|
{#if (tags ?? []).length > 0}
|
||||||
|
<TagSelector
|
||||||
|
bind:value={selectedTag}
|
||||||
|
align="end"
|
||||||
|
items={tags.map((tag) => ({ value: tag, label: tag }))}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -393,10 +393,10 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else if (prompts ?? []).length !== 0}
|
{:else if (prompts ?? []).length !== 0}
|
||||||
<!-- Before they call, I will answer; while they are yet speaking, I will hear. -->
|
<!-- Before they call, I will answer; while they are yet speaking, I will hear. -->
|
||||||
<div class="gap-2 grid my-2 px-3 lg:grid-cols-2">
|
<div class="gap-x-2 gap-y-0.5 grid my-1 lg:grid-cols-2">
|
||||||
{#each prompts as prompt (prompt.id)}
|
{#each prompts as prompt (prompt.id)}
|
||||||
<a
|
<a
|
||||||
class=" flex space-x-4 cursor-pointer text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
|
class="flex space-x-4 cursor-pointer text-left w-full px-2.5 py-1.5 transition rounded-2xl hover:bg-gray-50/70 dark:hover:bg-gray-850/50"
|
||||||
href={`/workspace/prompts/${prompt.id}`}
|
href={`/workspace/prompts/${prompt.id}`}
|
||||||
>
|
>
|
||||||
<div class=" flex flex-col flex-1 space-x-4 cursor-pointer w-full pl-1">
|
<div class=" flex flex-col flex-1 space-x-4 cursor-pointer w-full pl-1">
|
||||||
@@ -535,30 +535,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if $config?.features.enable_community_sharing}
|
{#if $config?.features.enable_community_sharing}
|
||||||
<div class=" my-16">
|
<CommunityDiscover
|
||||||
<div class=" text-xl font-medium mb-1 line-clamp-1">
|
href="https://openwebui.com/prompts"
|
||||||
{$i18n.t('Made by Open WebUI Community')}
|
title={$i18n.t('Discover a prompt')}
|
||||||
</div>
|
description={$i18n.t('Discover, download, and explore custom prompts')}
|
||||||
|
/>
|
||||||
<a
|
|
||||||
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
|
|
||||||
href="https://openwebui.com/prompts"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class=" self-center">
|
|
||||||
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a prompt')}</div>
|
|
||||||
<div class=" text-sm line-clamp-1">
|
|
||||||
{$i18n.t('Discover, download, and explore custom prompts')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<ChevronRight />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full h-full flex justify-center items-center">
|
<div class="w-full h-full flex justify-center items-center">
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
show = false;
|
show = false;
|
||||||
showDeleteConfirmDialog = true;
|
showDeleteConfirmDialog = true;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editHandler();
|
editHandler();
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
{#if $config.features.enable_community_sharing}
|
{#if $config.features.enable_community_sharing}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
shareHandler();
|
shareHandler();
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cloneHandler();
|
cloneHandler();
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.prompts_export}
|
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.prompts_export}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
exportHandler();
|
exportHandler();
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
|
|||||||
@@ -184,7 +184,7 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
{#if loaded}
|
{#if loaded}
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
||||||
<div>
|
<div>
|
||||||
@@ -312,11 +312,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 w-full items-center gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1">
|
||||||
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
|
|
||||||
<div class="flex flex-1">
|
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -342,29 +340,30 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
>
|
||||||
localStorage.workspaceViewOption = value;
|
<ViewSelector
|
||||||
page = 1;
|
bind:value={viewOption}
|
||||||
await tick();
|
align="end"
|
||||||
}}
|
onChange={async (value) => {
|
||||||
/>
|
localStorage.workspaceViewOption = value;
|
||||||
|
page = 1;
|
||||||
|
await tick();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -373,12 +372,12 @@
|
|||||||
<Spinner className="size-5" />
|
<Spinner className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
{:else if (filteredItems ?? []).length !== 0}
|
{:else if (filteredItems ?? []).length !== 0}
|
||||||
<div class=" my-2 gap-2 grid px-3 lg:grid-cols-2">
|
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2">
|
||||||
{#each filteredItems as skill}
|
{#each filteredItems as skill}
|
||||||
<Tooltip content={skill?.description ?? skill?.id}>
|
<Tooltip content={skill?.description ?? skill?.id}>
|
||||||
<div
|
<div
|
||||||
class=" flex space-x-4 text-left w-full px-3 py-2.5 transition rounded-2xl {skill.write_access
|
class="flex space-x-4 text-left w-full px-2.5 py-1.5 transition rounded-2xl {skill.write_access
|
||||||
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
|
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
|
||||||
: 'cursor-not-allowed opacity-60'}"
|
: 'cursor-not-allowed opacity-60'}"
|
||||||
>
|
>
|
||||||
{#if skill.write_access}
|
{#if skill.write_access}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editHandler();
|
editHandler();
|
||||||
}}
|
}}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cloneHandler();
|
cloneHandler();
|
||||||
}}
|
}}
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills_export}
|
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills_export}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
exportHandler();
|
exportHandler();
|
||||||
}}
|
}}
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
import GarbageBin from '../icons/GarbageBin.svelte';
|
import GarbageBin from '../icons/GarbageBin.svelte';
|
||||||
import Search from '../icons/Search.svelte';
|
import Search from '../icons/Search.svelte';
|
||||||
import Plus from '../icons/Plus.svelte';
|
import Plus from '../icons/Plus.svelte';
|
||||||
import ChevronRight from '../icons/ChevronRight.svelte';
|
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
import XMark from '../icons/XMark.svelte';
|
import XMark from '../icons/XMark.svelte';
|
||||||
import AddToolMenu from './Tools/AddToolMenu.svelte';
|
import AddToolMenu from './Tools/AddToolMenu.svelte';
|
||||||
import ImportModal from '../ImportModal.svelte';
|
import ImportModal from '../ImportModal.svelte';
|
||||||
import ViewSelector from './common/ViewSelector.svelte';
|
import ViewSelector from './common/ViewSelector.svelte';
|
||||||
|
import CommunityDiscover from './common/CommunityDiscover.svelte';
|
||||||
import Badge from '$lib/components/common/Badge.svelte';
|
import Badge from '$lib/components/common/Badge.svelte';
|
||||||
|
|
||||||
let shiftKey = false;
|
let shiftKey = false;
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{#if loaded}
|
{#if loaded}
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<input
|
<input
|
||||||
id="documents-import-input"
|
id="documents-import-input"
|
||||||
bind:this={toolsImportInputElement}
|
bind:this={toolsImportInputElement}
|
||||||
@@ -313,12 +313,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
|
||||||
>
|
|
||||||
<!-- The iron remembers its forge. -->
|
<!-- The iron remembers its forge. -->
|
||||||
<div class=" flex w-full space-x-2 py-0.5 px-3.5 pb-2">
|
<div class="flex h-8 w-full items-center gap-2">
|
||||||
<div class="flex flex-1">
|
<div class="flex min-w-0 flex-1">
|
||||||
<div class=" self-center ml-1 mr-3">
|
<div class=" self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -344,39 +342,40 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1"
|
|
||||||
on:wheel={(e) => {
|
|
||||||
if (e.deltaY !== 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.currentTarget.scrollLeft += e.deltaY;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
bind:this={tagsContainerElement}
|
bind:this={tagsContainerElement}
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<ViewSelector
|
<div
|
||||||
bind:value={viewOption}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
onChange={async (value) => {
|
>
|
||||||
localStorage.workspaceViewOption = value;
|
<ViewSelector
|
||||||
|
bind:value={viewOption}
|
||||||
|
align="end"
|
||||||
|
onChange={async (value) => {
|
||||||
|
localStorage.workspaceViewOption = value;
|
||||||
|
|
||||||
await tick();
|
await tick();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if (filteredItems ?? []).length !== 0}
|
{#if (filteredItems ?? []).length !== 0}
|
||||||
<div class=" my-2 gap-2 grid px-3 lg:grid-cols-2">
|
<div class="my-1 gap-x-2 gap-y-0.5 grid lg:grid-cols-2">
|
||||||
{#each filteredItems as tool}
|
{#each filteredItems as tool}
|
||||||
<Tooltip content={tool?.meta?.description ?? tool?.id}>
|
<Tooltip content={tool?.meta?.description ?? tool?.id}>
|
||||||
<div
|
<div
|
||||||
class=" flex space-x-4 text-left w-full px-3 py-2.5 transition rounded-2xl {tool.write_access
|
class="flex space-x-4 text-left w-full px-2.5 py-1.5 transition rounded-2xl {tool.write_access
|
||||||
? 'cursor-pointer dark:hover:bg-gray-850/50 hover:bg-gray-50'
|
? 'cursor-pointer hover:bg-gray-50/70 dark:hover:bg-gray-850/50'
|
||||||
: 'cursor-not-allowed opacity-60'}"
|
: 'cursor-not-allowed opacity-60'}"
|
||||||
>
|
>
|
||||||
{#if tool.write_access}
|
{#if tool.write_access}
|
||||||
@@ -565,30 +564,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if $config?.features.enable_community_sharing}
|
{#if $config?.features.enable_community_sharing}
|
||||||
<div class=" my-16">
|
<CommunityDiscover
|
||||||
<div class=" text-xl font-medium mb-1 line-clamp-1">
|
href="https://openwebui.com/tools"
|
||||||
{$i18n.t('Made by Open WebUI Community')}
|
title={$i18n.t('Discover a tool')}
|
||||||
</div>
|
description={$i18n.t('Discover, download, and explore custom tools')}
|
||||||
|
/>
|
||||||
<a
|
|
||||||
class=" flex cursor-pointer items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-850 w-full mb-2 px-3.5 py-1.5 rounded-xl transition"
|
|
||||||
href="https://openwebui.com/tools"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<div class=" self-center">
|
|
||||||
<div class=" font-medium line-clamp-1">{$i18n.t('Discover a tool')}</div>
|
|
||||||
<div class=" text-sm line-clamp-1">
|
|
||||||
{$i18n.t('Discover, download, and explore custom tools')}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<ChevronRight />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<DeleteConfirmDialog
|
<DeleteConfirmDialog
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[190px]">
|
<DropdownMenu className="min-w-[190px]">
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
createHandler();
|
createHandler();
|
||||||
show = false;
|
show = false;
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
importFromLinkHandler();
|
importFromLinkHandler();
|
||||||
show = false;
|
show = false;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu className="min-w-[170px]">
|
<DropdownMenu className="min-w-[170px]">
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
editHandler();
|
editHandler();
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
{#if $config.features.enable_community_sharing}
|
{#if $config.features.enable_community_sharing}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
shareHandler();
|
shareHandler();
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cloneHandler();
|
cloneHandler();
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.tools_export}
|
{#if $user?.role === 'admin' || $user?.permissions?.workspace?.tools_export}
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
exportHandler();
|
exportHandler();
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
<hr class="border-gray-50 dark:border-gray-850/30 mx-1 my-0.5" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="select-none flex h-[1.6875rem] w-full items-center gap-2 rounded-xl px-2 text-[13px] cursor-pointer hover:bg-gray-50/60 dark:hover:bg-gray-800/60"
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteHandler();
|
deleteHandler();
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
|
||||||
|
import ChevronRight from '$lib/components/icons/ChevronRight.svelte';
|
||||||
|
|
||||||
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
|
export let href = '';
|
||||||
|
export let title = '';
|
||||||
|
export let description = '';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="mt-6 px-2">
|
||||||
|
<div class="mb-0.5 text-[11px] font-normal text-gray-400 dark:text-gray-600">
|
||||||
|
{$i18n.t('Made by Open WebUI Community')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a
|
||||||
|
class="flex w-full cursor-pointer items-center justify-between gap-3 px-0 py-1 text-left transition"
|
||||||
|
{href}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<div class="min-w-0">
|
||||||
|
<div class="line-clamp-1 text-[13px] font-normal text-gray-700 dark:text-gray-200">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div class="line-clamp-1 text-xs text-gray-500 dark:text-gray-500">
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ChevronRight className="size-3.5 shrink-0 text-gray-400 dark:text-gray-600" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let placeholder = $i18n.t('Tag');
|
export let placeholder = $i18n.t('Tag');
|
||||||
|
export let align = 'start';
|
||||||
export let onChange: (value: string) => void = () => {};
|
export let onChange: (value: string) => void = () => {};
|
||||||
|
|
||||||
export let items = [];
|
export let items = [];
|
||||||
@@ -19,13 +20,14 @@
|
|||||||
bind:value
|
bind:value
|
||||||
{items}
|
{items}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
triggerClass="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 rounded-xl "
|
{align}
|
||||||
itemClass="flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl capitalize"
|
triggerClass="relative h-8 w-full flex items-center gap-0.5 px-1.5 py-1.5 bg-transparent rounded-xl text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
|
itemClass="flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] capitalize hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
onChange={() => onChange(value)}
|
onChange={() => onChange(value)}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="trigger" let:selectedLabel>
|
<svelte:fragment slot="trigger" let:selectedLabel>
|
||||||
<div
|
<div
|
||||||
class="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden capitalize"
|
class="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden capitalize"
|
||||||
>
|
>
|
||||||
{#if value}
|
{#if value}
|
||||||
{value}
|
{value}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
export let value = '';
|
export let value = '';
|
||||||
export let placeholder = $i18n.t('Select view');
|
export let placeholder = $i18n.t('Select view');
|
||||||
|
export let align = 'start';
|
||||||
export let onChange: (value: string) => void = () => {};
|
export let onChange: (value: string) => void = () => {};
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
@@ -22,13 +23,14 @@
|
|||||||
bind:value
|
bind:value
|
||||||
{items}
|
{items}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
triggerClass="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 bg-gray-50 dark:bg-gray-850 rounded-xl "
|
{align}
|
||||||
labelClass="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
triggerClass="relative h-8 w-full flex items-center gap-0.5 px-1.5 py-1.5 bg-transparent rounded-xl text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
|
labelClass="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
||||||
onChange={() => onChange(value)}
|
onChange={() => onChange(value)}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="trigger" let:selectedLabel>
|
<svelte:fragment slot="trigger" let:selectedLabel>
|
||||||
<span
|
<span
|
||||||
class="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
class="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
||||||
>
|
>
|
||||||
{selectedLabel}
|
{selectedLabel}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -260,7 +260,7 @@
|
|||||||
<div class="flex-1 max-h-full overflow-y-auto">
|
<div class="flex-1 max-h-full overflow-y-auto">
|
||||||
{#if loaded}
|
{#if loaded}
|
||||||
<div class="pb-1 px-3 md:px-[18px] pt-2">
|
<div class="pb-1 px-3 md:px-[18px] pt-2">
|
||||||
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-3">
|
<div class="flex flex-col gap-1 px-1 mt-1.5 mb-2">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
<div class="flex items-center md:self-center text-xl font-medium px-0.5 gap-2 shrink-0">
|
||||||
{#if $mobile}
|
{#if $mobile}
|
||||||
@@ -303,11 +303,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="space-y-1">
|
||||||
class="py-2 bg-white dark:bg-gray-900 rounded-3xl border border-gray-100/30 dark:border-gray-850/30"
|
<div class="flex h-8 flex-1 items-center w-full gap-2">
|
||||||
>
|
<div class="flex min-w-0 flex-1 items-center">
|
||||||
<div class="px-3.5 flex flex-1 items-center w-full space-x-2 py-0.5 pb-2">
|
|
||||||
<div class="flex flex-1 items-center">
|
|
||||||
<div class="self-center ml-1 mr-3">
|
<div class="self-center ml-1 mr-3">
|
||||||
<Search className="size-3.5" />
|
<Search className="size-3.5" />
|
||||||
</div>
|
</div>
|
||||||
@@ -335,76 +333,83 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="px-3 flex w-full bg-transparent overflow-x-auto scrollbar-none -mx-1">
|
|
||||||
<div
|
<div
|
||||||
class="flex gap-0.5 w-fit text-center text-sm rounded-full bg-transparent px-1.5 whitespace-nowrap"
|
class="flex max-w-[55%] shrink-0 overflow-x-auto scrollbar-none"
|
||||||
|
on:wheel={(e) => {
|
||||||
|
if (e.deltaY !== 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.currentTarget.scrollLeft += e.deltaY;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Select
|
<div
|
||||||
bind:value={statusFilter}
|
class="flex w-fit gap-0.5 text-center text-sm rounded-full bg-transparent whitespace-nowrap"
|
||||||
items={[
|
|
||||||
{ value: 'all', label: $i18n.t('All') },
|
|
||||||
{ value: 'active', label: $i18n.t('Active') },
|
|
||||||
{ value: 'paused', label: $i18n.t('Paused') }
|
|
||||||
]}
|
|
||||||
onChange={() => {
|
|
||||||
page = 1;
|
|
||||||
}}
|
|
||||||
triggerClass="relative w-full flex items-center gap-0.5 px-2.5 py-1.5 bg-gray-50 dark:bg-gray-850 rounded-xl"
|
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="trigger" let:selectedLabel>
|
<Select
|
||||||
<span
|
bind:value={statusFilter}
|
||||||
class="inline-flex h-input px-0.5 w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
align="end"
|
||||||
>
|
items={[
|
||||||
{selectedLabel}
|
{ value: 'all', label: $i18n.t('All') },
|
||||||
</span>
|
{ value: 'active', label: $i18n.t('Active') },
|
||||||
<ChevronDown className="size-3.5" strokeWidth="2.5" />
|
{ value: 'paused', label: $i18n.t('Paused') }
|
||||||
</svelte:fragment>
|
]}
|
||||||
|
onChange={() => {
|
||||||
<svelte:fragment slot="item" let:item let:selected>
|
page = 1;
|
||||||
{item.label}
|
}}
|
||||||
<div class="ml-auto {selected ? '' : 'invisible'}">
|
triggerClass="relative h-8 w-full flex items-center gap-0.5 px-1.5 py-1.5 bg-transparent rounded-xl text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
<Check />
|
|
||||||
</div>
|
|
||||||
</svelte:fragment>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-1"></div>
|
|
||||||
|
|
||||||
<Dropdown align="end">
|
|
||||||
<Tooltip content={$i18n.t('Actions')}>
|
|
||||||
<button
|
|
||||||
class="p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition"
|
|
||||||
type="button"
|
|
||||||
aria-label={$i18n.t('Actions')}
|
|
||||||
>
|
>
|
||||||
<EllipsisHorizontal className="size-4" />
|
<svelte:fragment slot="trigger" let:selectedLabel>
|
||||||
</button>
|
<span
|
||||||
</Tooltip>
|
class="inline-flex h-input w-full outline-hidden bg-transparent truncate placeholder-gray-400 focus:outline-hidden"
|
||||||
|
>
|
||||||
|
{selectedLabel}
|
||||||
|
</span>
|
||||||
|
<ChevronDown className="size-3.5" strokeWidth="2.5" />
|
||||||
|
</svelte:fragment>
|
||||||
|
|
||||||
<div slot="content">
|
<svelte:fragment slot="item" let:item let:selected>
|
||||||
<DropdownMenu className="w-[170px] shadow-sm">
|
{item.label}
|
||||||
<button
|
<div class="ml-auto {selected ? '' : 'invisible'}">
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
<Check />
|
||||||
type="button"
|
</div>
|
||||||
on:click={() => bulkToggleHandler(true)}
|
</svelte:fragment>
|
||||||
>
|
</Select>
|
||||||
<CheckCircle className="size-4" />
|
|
||||||
{$i18n.t('Enable All')}
|
<Dropdown align="end">
|
||||||
</button>
|
<Tooltip content={$i18n.t('Actions')}>
|
||||||
<button
|
<button
|
||||||
class="select-none flex w-full gap-2 items-center px-3 py-1.5 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
|
class="flex h-8 items-center gap-1.5 rounded-xl bg-transparent px-1.5 text-[13px] font-normal text-gray-700 transition hover:text-gray-900 dark:text-gray-200 dark:hover:text-gray-100"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={() => bulkToggleHandler(false)}
|
>
|
||||||
>
|
<span>{$i18n.t('Actions')}</span>
|
||||||
<Minus className="size-4" />
|
<ChevronDown className="size-3" strokeWidth="2.5" />
|
||||||
{$i18n.t('Disable All')}
|
</button>
|
||||||
</button>
|
</Tooltip>
|
||||||
</DropdownMenu>
|
|
||||||
|
<div slot="content">
|
||||||
|
<DropdownMenu className="w-[170px] shadow-sm">
|
||||||
|
<button
|
||||||
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => bulkToggleHandler(true)}
|
||||||
|
>
|
||||||
|
<CheckCircle className="size-3.5" />
|
||||||
|
{$i18n.t('Enable All')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="select-none flex h-[1.6875rem] w-full cursor-pointer items-center gap-2 rounded-xl bg-transparent px-2 text-[13px] hover:text-gray-900 dark:hover:text-gray-100"
|
||||||
|
type="button"
|
||||||
|
on:click={() => bulkToggleHandler(false)}
|
||||||
|
>
|
||||||
|
<Minus className="size-3.5" />
|
||||||
|
{$i18n.t('Disable All')}
|
||||||
|
</button>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if automations === null || loading}
|
{#if automations === null || loading}
|
||||||
@@ -430,10 +435,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="gap-2 grid my-2 px-3">
|
<div class="gap-y-0.5 grid my-1">
|
||||||
{#each automations as automation (automation.id)}
|
{#each automations as automation (automation.id)}
|
||||||
<a
|
<a
|
||||||
class="flex space-x-4 text-left w-full px-3 py-2.5 dark:hover:bg-gray-850/50 hover:bg-gray-50 transition rounded-2xl"
|
class="flex space-x-4 text-left w-full px-3 py-2 bg-transparent hover:bg-gray-50/70 dark:hover:bg-gray-850/50 transition rounded-2xl"
|
||||||
href={`/automations/${automation.id}`}
|
href={`/automations/${automation.id}`}
|
||||||
>
|
>
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
@@ -460,7 +465,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="self-center w-fit text-sm p-1.5 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
|
class="self-center w-fit text-sm p-1.5 text-gray-500 hover:text-gray-900 dark:text-gray-300 dark:hover:text-gray-100 rounded-xl"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<EllipsisHorizontal className="size-5" />
|
<EllipsisHorizontal className="size-5" />
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getContext, onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
|
||||||
|
|
||||||
import dayjs from '$lib/dayjs';
|
import dayjs from '$lib/dayjs';
|
||||||
import { mobile, showArchivedChats, showSidebar, user } from '$lib/stores';
|
import { showSidebar } from '$lib/stores';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
|
|
||||||
import { createNoteHandler } from '$lib/components/notes/utils';
|
import { createNoteHandler } from '$lib/components/notes/utils';
|
||||||
|
|
||||||
import UserMenu from '$lib/components/layout/Sidebar/UserMenu.svelte';
|
|
||||||
import Notes from '$lib/components/notes/Notes.svelte';
|
import Notes from '$lib/components/notes/Notes.svelte';
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Spinner from '$lib/components/common/Spinner.svelte';
|
||||||
import Sidebar from '$lib/components/icons/Sidebar.svelte';
|
|
||||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
|
||||||
|
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
|
|
||||||
@@ -38,80 +33,20 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if loaded}
|
<div
|
||||||
<div
|
class="flex flex-col w-full h-screen max-h-[100dvh] transition-width duration-200 ease-in-out {$showSidebar
|
||||||
class=" flex flex-col w-full h-screen max-h-[100dvh] transition-width duration-200 ease-in-out {$showSidebar
|
? 'md:max-w-[calc(100%-var(--sidebar-width))]'
|
||||||
? 'md:max-w-[calc(100%-var(--sidebar-width))]'
|
: ''} max-w-full"
|
||||||
: ''} max-w-full"
|
>
|
||||||
>
|
<div class="flex-1 max-h-full overflow-y-auto">
|
||||||
<nav class=" px-2 pt-1.5 backdrop-blur-xl w-full drag-region">
|
{#if loaded}
|
||||||
<div class=" flex items-center">
|
<div class="pb-1 px-3 md:px-[18px] pt-2">
|
||||||
{#if $mobile}
|
<Notes />
|
||||||
<div class="{$showSidebar ? 'md:hidden' : ''} flex flex-none items-center">
|
|
||||||
<Tooltip
|
|
||||||
content={$showSidebar ? $i18n.t('Close Sidebar') : $i18n.t('Open Sidebar')}
|
|
||||||
interactive={true}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
id="sidebar-toggle-button"
|
|
||||||
class=" cursor-pointer flex rounded-lg hover:bg-gray-100 dark:hover:bg-gray-850 transition cursor-"
|
|
||||||
on:click={() => {
|
|
||||||
showSidebar.set(!$showSidebar);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div class=" self-center p-1.5">
|
|
||||||
<Sidebar />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="ml-2 py-0.5 self-center flex items-center justify-between w-full">
|
|
||||||
<div class="">
|
|
||||||
<div
|
|
||||||
class="flex gap-1 scrollbar-none overflow-x-auto w-fit text-center text-sm font-medium bg-transparent py-1 touch-auto pointer-events-auto"
|
|
||||||
>
|
|
||||||
<a class="min-w-fit transition" href="/notes">
|
|
||||||
{$i18n.t('Notes')}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class=" self-center flex items-center gap-1">
|
|
||||||
{#if $user !== undefined && $user !== null}
|
|
||||||
<UserMenu
|
|
||||||
className="w-[240px]"
|
|
||||||
role={$user?.role}
|
|
||||||
help={true}
|
|
||||||
on:show={(e) => {
|
|
||||||
if (e.detail === 'archived-chat') {
|
|
||||||
showArchivedChats.set(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="select-none flex rounded-xl p-1.5 w-full hover:bg-gray-50 dark:hover:bg-gray-850 transition"
|
|
||||||
aria-label="User Menu"
|
|
||||||
>
|
|
||||||
<div class=" self-center">
|
|
||||||
<img
|
|
||||||
src={`${WEBUI_API_BASE_URL}/users/${$user?.id}/profile/image`}
|
|
||||||
class="size-6 object-cover rounded-full"
|
|
||||||
alt="User profile"
|
|
||||||
draggable="false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</UserMenu>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
{:else}
|
||||||
|
<div class="w-full h-full flex justify-center items-center">
|
||||||
<div class=" flex-1 max-h-full overflow-y-auto @container">
|
<Spinner className="size-5" />
|
||||||
<Notes />
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
Reference in new issue
Block a user