refac
This commit is contained in:
@@ -43,8 +43,7 @@
|
|||||||
import Minus from '$lib/components/icons/Minus.svelte';
|
import Minus from '$lib/components/icons/Minus.svelte';
|
||||||
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
|
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
import AdminViewSelector from './Models/AdminViewSelector.svelte';
|
import AdminViewSelector from './Models/AdminViewSelector.svelte';
|
||||||
import Pagination from '$lib/components/common/Pagination.svelte';
|
import Pagination from '$lib/components/common/Pagination.svelte';
|
||||||
@@ -495,55 +494,55 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="w-full max-w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
|
class="w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
|
||||||
sideOffset={-2}
|
|
||||||
side="bottom"
|
|
||||||
align="end"
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
enableAllHandler();
|
enableAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CheckCircle className="size-4" />
|
<CheckCircle className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
disableAllHandler();
|
disableAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Minus className="size-4" />
|
<Minus className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<hr class="border-gray-100 dark:border-gray-800 my-1" />
|
<hr class="border-gray-100 dark:border-gray-800 my-1" />
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
showAllHandler();
|
showAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Eye className="size-4" />
|
<Eye className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
hideAllHandler();
|
hideAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<EyeSlash className="size-4" />
|
<EyeSlash className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import { getContext, onMount, tick } from 'svelte';
|
import { getContext, onMount, tick } from 'svelte';
|
||||||
|
|
||||||
import { config, user, tools as _tools, mobile } from '$lib/stores';
|
import { config, user, tools as _tools, mobile } from '$lib/stores';
|
||||||
@@ -45,33 +43,31 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="w-full max-w-[200px] rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-999 bg-white dark:bg-gray-850 dark:text-white shadow-lg transition"
|
class="w-[200px] rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-999 bg-white dark:bg-gray-850 dark:text-white shadow-lg transition"
|
||||||
sideOffset={4}
|
|
||||||
alignOffset={-6}
|
|
||||||
side="bottom"
|
|
||||||
align="start"
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<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/50 rounded-xl"
|
class="select-none 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/50 rounded-xl"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
uploadFilesHandler();
|
uploadFilesHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Clip />
|
<Clip />
|
||||||
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
|
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<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/50 rounded-xl"
|
class="select-none 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/50 rounded-xl"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
screenCaptureHandler();
|
screenCaptureHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Camera />
|
<Camera />
|
||||||
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
|
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|
||||||
|
|||||||
@@ -194,7 +194,7 @@
|
|||||||
|
|
||||||
{#if $user !== undefined}
|
{#if $user !== undefined}
|
||||||
<UserMenu
|
<UserMenu
|
||||||
className="max-w-[240px]"
|
className="w-[240px]"
|
||||||
role={$user?.role}
|
role={$user?.role}
|
||||||
help={true}
|
help={true}
|
||||||
on:show={(e) => {
|
on:show={(e) => {
|
||||||
|
|||||||
@@ -89,8 +89,7 @@
|
|||||||
import PlusAlt from '../icons/PlusAlt.svelte';
|
import PlusAlt from '../icons/PlusAlt.svelte';
|
||||||
import Dropdown from '../common/Dropdown.svelte';
|
import Dropdown from '../common/Dropdown.svelte';
|
||||||
|
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
|
|
||||||
import CommandSuggestionList from './MessageInput/CommandSuggestionList.svelte';
|
import CommandSuggestionList from './MessageInput/CommandSuggestionList.svelte';
|
||||||
import Knobs from '../icons/Knobs.svelte';
|
import Knobs from '../icons/Knobs.svelte';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { getContext, onMount, tick } from 'svelte';
|
import { getContext, onMount, tick } from 'svelte';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
|
|
||||||
import { config, user, tools as _tools, mobile, knowledge } from '$lib/stores';
|
import { config, user, tools as _tools, mobile, knowledge } from '$lib/stores';
|
||||||
import { getKnowledgeBases } from '$lib/apis/knowledge';
|
import { getKnowledgeBases } from '$lib/apis/knowledge';
|
||||||
@@ -122,13 +122,8 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="w-full max-w-70 rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg max-h-72 overflow-y-auto overflow-x-hidden scrollbar-thin transition"
|
class="w-70 rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg max-h-72 overflow-y-auto overflow-x-hidden scrollbar-thin transition"
|
||||||
sideOffset={4}
|
|
||||||
alignOffset={-6}
|
|
||||||
side="bottom"
|
|
||||||
align="start"
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
>
|
||||||
{#if tab === ''}
|
{#if tab === ''}
|
||||||
<div in:fly={{ x: -20, duration: 150 }}>
|
<div in:fly={{ x: -20, duration: 150 }}>
|
||||||
@@ -140,10 +135,11 @@
|
|||||||
: ''}
|
: ''}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
|
||||||
? 'opacity-50'
|
? 'opacity-50'
|
||||||
: ''}"
|
: ''}"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (fileUploadEnabled) {
|
if (fileUploadEnabled) {
|
||||||
uploadFilesHandler();
|
uploadFilesHandler();
|
||||||
@@ -153,7 +149,7 @@
|
|||||||
<Clip />
|
<Clip />
|
||||||
|
|
||||||
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
|
<div class="line-clamp-1">{$i18n.t('Upload Files')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -164,10 +160,11 @@
|
|||||||
: ''}
|
: ''}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl {!fileUploadEnabled
|
||||||
? 'opacity-50'
|
? 'opacity-50'
|
||||||
: ''}"
|
: ''}"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (fileUploadEnabled) {
|
if (fileUploadEnabled) {
|
||||||
if (!detectMobile()) {
|
if (!detectMobile()) {
|
||||||
@@ -184,7 +181,7 @@
|
|||||||
>
|
>
|
||||||
<Camera />
|
<Camera />
|
||||||
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
|
<div class=" line-clamp-1">{$i18n.t('Capture')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@@ -193,10 +190,11 @@
|
|||||||
: ''}
|
: ''}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!webUploadEnabled
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl {!webUploadEnabled
|
||||||
? 'opacity-50'
|
? 'opacity-50'
|
||||||
: ''}"
|
: ''}"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (webUploadEnabled) {
|
if (webUploadEnabled) {
|
||||||
showAttachWebpageModal = true;
|
showAttachWebpageModal = true;
|
||||||
@@ -205,7 +203,7 @@
|
|||||||
>
|
>
|
||||||
<GlobeAlt />
|
<GlobeAlt />
|
||||||
<div class="line-clamp-1">{$i18n.t('Attach Webpage')}</div>
|
<div class="line-clamp-1">{$i18n.t('Attach Webpage')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{#if $config?.features?.enable_notes ?? false}
|
{#if $config?.features?.enable_notes ?? false}
|
||||||
@@ -302,8 +300,9 @@
|
|||||||
|
|
||||||
{#if fileUploadEnabled}
|
{#if fileUploadEnabled}
|
||||||
{#if $config?.features?.enable_google_drive_integration}
|
{#if $config?.features?.enable_google_drive_integration}
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
uploadGoogleDriveHandler();
|
uploadGoogleDriveHandler();
|
||||||
}}
|
}}
|
||||||
@@ -335,7 +334,7 @@
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<div class="line-clamp-1">{$i18n.t('Google Drive')}</div>
|
<div class="line-clamp-1">{$i18n.t('Google Drive')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $config?.features?.enable_onedrive_integration && ($config?.features?.enable_onedrive_personal || $config?.features?.enable_onedrive_business)}
|
{#if $config?.features?.enable_onedrive_integration && ($config?.features?.enable_onedrive_personal || $config?.features?.enable_onedrive_business)}
|
||||||
@@ -521,8 +520,9 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if $config?.features?.enable_onedrive_personal}
|
{#if $config?.features?.enable_onedrive_personal}
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
uploadOneDriveHandler('personal');
|
uploadOneDriveHandler('personal');
|
||||||
}}
|
}}
|
||||||
@@ -530,12 +530,13 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive (personal)')}</div>
|
<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive (personal)')}</div>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if $config?.features?.enable_onedrive_business}
|
{#if $config?.features?.enable_onedrive_business}
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
|
class="flex w-full gap-2 items-center px-3 py-1.5 text-sm select-none cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 rounded-xl text-left"
|
||||||
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
uploadOneDriveHandler('organizations');
|
uploadOneDriveHandler('organizations');
|
||||||
}}
|
}}
|
||||||
@@ -546,10 +547,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-gray-500">{$i18n.t('Includes SharePoint')}</div>
|
<div class="text-xs text-gray-500">{$i18n.t('Includes SharePoint')}</div>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|||||||
@@ -230,7 +230,7 @@
|
|||||||
|
|
||||||
{#if $user !== undefined && $user !== null}
|
{#if $user !== undefined && $user !== null}
|
||||||
<UserMenu
|
<UserMenu
|
||||||
className="max-w-[240px]"
|
className="w-[240px]"
|
||||||
role={$user?.role}
|
role={$user?.role}
|
||||||
help={true}
|
help={true}
|
||||||
on:show={(e) => {
|
on:show={(e) => {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
import { flyAndScale } from '$lib/utils/transitions';
|
||||||
import { tick } from 'svelte';
|
import { createEventDispatcher, tick } from 'svelte';
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
/** Whether the dropdown is open */
|
/** Whether the dropdown is open */
|
||||||
export let show = false;
|
export let show = false;
|
||||||
@@ -104,6 +106,7 @@
|
|||||||
async function toggleOpen() {
|
async function toggleOpen() {
|
||||||
show = !show;
|
show = !show;
|
||||||
onOpenChange(show);
|
onOpenChange(show);
|
||||||
|
dispatch('change', show);
|
||||||
if (show) {
|
if (show) {
|
||||||
await tick();
|
await tick();
|
||||||
positionContent();
|
positionContent();
|
||||||
@@ -126,12 +129,14 @@
|
|||||||
if (contentEl?.contains(event.target)) return;
|
if (contentEl?.contains(event.target)) return;
|
||||||
show = false;
|
show = false;
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
|
dispatch('change', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeydown(event) {
|
function handleKeydown(event) {
|
||||||
if (event.key === 'Escape' && show) {
|
if (event.key === 'Escape' && show) {
|
||||||
show = false;
|
show = false;
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
|
dispatch('change', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +144,7 @@
|
|||||||
export function close() {
|
export function close() {
|
||||||
show = false;
|
show = false;
|
||||||
onOpenChange(false);
|
onOpenChange(false);
|
||||||
|
dispatch('change', false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import VirtualList from '@sveltejs/svelte-virtual-list';
|
import VirtualList from '@sveltejs/svelte-virtual-list';
|
||||||
|
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
|
|
||||||
import emojiGroups from '$lib/emoji-groups.json';
|
import emojiGroups from '$lib/emoji-groups.json';
|
||||||
@@ -107,79 +106,74 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DropdownMenu.Root
|
<Dropdown
|
||||||
bind:open={show}
|
bind:show
|
||||||
closeFocus={false}
|
{align}
|
||||||
onOpenChange={(state) => {
|
on:change={(e) => {
|
||||||
if (!state) {
|
if (e.detail === false) {
|
||||||
search = '';
|
search = '';
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
typeahead={false}
|
|
||||||
>
|
>
|
||||||
<DropdownMenu.Trigger>
|
<slot />
|
||||||
<slot />
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
<DropdownMenu.Content
|
|
||||||
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
|
|
||||||
sideOffset={8}
|
|
||||||
{side}
|
|
||||||
{align}
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
|
||||||
<div class="mb-1 px-4 pt-2.5 pb-2">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="w-full text-sm bg-transparent outline-hidden"
|
|
||||||
placeholder={$i18n.t('Search all emojis')}
|
|
||||||
bind:value={search}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div slot="content">
|
||||||
|
<div
|
||||||
|
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
|
||||||
|
>
|
||||||
|
<div class="mb-1 px-4 pt-2.5 pb-2">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="w-full text-sm bg-transparent outline-hidden"
|
||||||
|
placeholder={$i18n.t('Search all emojis')}
|
||||||
|
bind:value={search}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Virtualized Emoji List -->
|
<!-- Virtualized Emoji List -->
|
||||||
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
|
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
|
||||||
{#if emojiRows.length === 0}
|
{#if emojiRows.length === 0}
|
||||||
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
|
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
|
||||||
{$i18n.t('No results')}
|
{$i18n.t('No results')}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="w-full flex ml-0.5">
|
<div class="w-full flex ml-0.5">
|
||||||
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
{#if item.length === 1 && item[0].type === 'group'}
|
{#if item.length === 1 && item[0].type === 'group'}
|
||||||
<!-- Render group header -->
|
<!-- Render group header -->
|
||||||
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
|
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
|
||||||
{item[0].label}
|
{item[0].label}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Render emojis in a row -->
|
<!-- Render emojis in a row -->
|
||||||
<div class="flex items-center gap-1.5 w-full">
|
<div class="flex items-center gap-1.5 w-full">
|
||||||
{#each item as emojiItem}
|
{#each item as emojiItem}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
|
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
|
|
||||||
on:click={() => selectEmoji(emojiItem)}
|
|
||||||
>
|
>
|
||||||
<img
|
<button
|
||||||
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
|
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
|
||||||
alt={emojiItem.name}
|
on:click={() => selectEmoji(emojiItem)}
|
||||||
class="size-5"
|
>
|
||||||
loading="lazy"
|
<img
|
||||||
/>
|
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
|
||||||
</button>
|
alt={emojiItem.name}
|
||||||
</Tooltip>
|
class="size-5"
|
||||||
{/each}
|
loading="lazy"
|
||||||
</div>
|
/>
|
||||||
{/if}
|
</button>
|
||||||
</div>
|
</Tooltip>
|
||||||
</VirtualList>
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
</VirtualList>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</DropdownMenu.Root>
|
</Dropdown>
|
||||||
|
|||||||
@@ -1398,7 +1398,7 @@
|
|||||||
role={$user?.role}
|
role={$user?.role}
|
||||||
profile={$config?.features?.enable_user_status ?? true}
|
profile={$config?.features?.enable_user_status ?? true}
|
||||||
showActiveUsers={false}
|
showActiveUsers={false}
|
||||||
className="max-w-[calc(var(--sidebar-width)-1rem)]"
|
className="w-[calc(var(--sidebar-width)-1rem)]"
|
||||||
on:show={(e) => {
|
on:show={(e) => {
|
||||||
if (e.detail === 'archived-chat') {
|
if (e.detail === 'archived-chat') {
|
||||||
showArchivedChats.set(true);
|
showArchivedChats.set(true);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { createEventDispatcher, getContext, onMount, tick } from 'svelte';
|
import { createEventDispatcher, getContext, onMount, tick } from 'svelte';
|
||||||
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { fade, slide } from 'svelte/transition';
|
import { fade, slide } from 'svelte/transition';
|
||||||
|
|
||||||
@@ -13,6 +11,7 @@
|
|||||||
|
|
||||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
|
import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
|
||||||
import QuestionMarkCircle from '$lib/components/icons/QuestionMarkCircle.svelte';
|
import QuestionMarkCircle from '$lib/components/icons/QuestionMarkCircle.svelte';
|
||||||
@@ -38,7 +37,7 @@
|
|||||||
export let profile = false;
|
export let profile = false;
|
||||||
export let help = false;
|
export let help = false;
|
||||||
|
|
||||||
export let className = 'max-w-[240px]';
|
export let className = 'w-[240px]';
|
||||||
export let align = 'end';
|
export let align = 'end';
|
||||||
|
|
||||||
export let showActiveUsers = true;
|
export let showActiveUsers = true;
|
||||||
@@ -60,7 +59,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDropdownChange = (state: boolean) => {
|
const handleDropdownChange = (e) => {
|
||||||
|
const state = e.detail;
|
||||||
dispatch('change', state);
|
dispatch('change', state);
|
||||||
|
|
||||||
// Fetch usage info when dropdown opens, if user has permission
|
// Fetch usage info when dropdown opens, if user has permission
|
||||||
@@ -79,18 +79,12 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
<DropdownMenu.Root bind:open={show} onOpenChange={handleDropdownChange}>
|
<Dropdown bind:show on:change={handleDropdownChange} {align}>
|
||||||
<DropdownMenu.Trigger>
|
<slot />
|
||||||
<slot />
|
|
||||||
</DropdownMenu.Trigger>
|
|
||||||
|
|
||||||
<slot name="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="w-full {className} rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg text-sm"
|
class="{className} rounded-2xl px-1 py-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg text-sm"
|
||||||
sideOffset={4}
|
|
||||||
side="top"
|
|
||||||
{align}
|
|
||||||
transition={(e) => fade(e, { duration: 100 })}
|
|
||||||
>
|
>
|
||||||
{#if profile}
|
{#if profile}
|
||||||
<div class=" flex gap-3.5 w-full p-2.5 items-center">
|
<div class=" flex gap-3.5 w-full p-2.5 items-center">
|
||||||
@@ -201,8 +195,9 @@
|
|||||||
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1.5 p-0" />
|
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1.5 p-0" />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
|
type="button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
show = false;
|
show = false;
|
||||||
|
|
||||||
@@ -218,10 +213,11 @@
|
|||||||
<Settings className="w-5 h-5" strokeWidth="1.5" />
|
<Settings className="w-5 h-5" strokeWidth="1.5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Settings')}</div>
|
<div class=" self-center truncate">{$i18n.t('Settings')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
|
type="button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
show = false;
|
show = false;
|
||||||
|
|
||||||
@@ -238,11 +234,10 @@
|
|||||||
<ArchiveBox className="size-5" strokeWidth="1.5" />
|
<ArchiveBox className="size-5" strokeWidth="1.5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Archived Chats')}</div>
|
<div class=" self-center truncate">{$i18n.t('Archived Chats')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
{#if role === 'admin'}
|
{#if role === 'admin'}
|
||||||
<DropdownMenu.Item
|
<a
|
||||||
as="a"
|
|
||||||
href="/playground"
|
href="/playground"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
@@ -258,9 +253,8 @@
|
|||||||
<Code className="size-5" strokeWidth="1.5" />
|
<Code className="size-5" strokeWidth="1.5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Playground')}</div>
|
<div class=" self-center truncate">{$i18n.t('Playground')}</div>
|
||||||
</DropdownMenu.Item>
|
</a>
|
||||||
<DropdownMenu.Item
|
<a
|
||||||
as="a"
|
|
||||||
href="/admin"
|
href="/admin"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
@@ -276,7 +270,7 @@
|
|||||||
<UserGroup className="w-5 h-5" strokeWidth="1.5" />
|
<UserGroup className="w-5 h-5" strokeWidth="1.5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Admin Panel')}</div>
|
<div class=" self-center truncate">{$i18n.t('Admin Panel')}</div>
|
||||||
</DropdownMenu.Item>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if help}
|
{#if help}
|
||||||
@@ -285,8 +279,7 @@
|
|||||||
<!-- {$i18n.t('Help')} -->
|
<!-- {$i18n.t('Help')} -->
|
||||||
|
|
||||||
{#if $user?.role === 'admin'}
|
{#if $user?.role === 'admin'}
|
||||||
<DropdownMenu.Item
|
<a
|
||||||
as="a"
|
|
||||||
href="https://docs.openwebui.com"
|
href="https://docs.openwebui.com"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
@@ -300,11 +293,10 @@
|
|||||||
<QuestionMarkCircle className="size-5" />
|
<QuestionMarkCircle className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Documentation')}</div>
|
<div class=" self-center truncate">{$i18n.t('Documentation')}</div>
|
||||||
</DropdownMenu.Item>
|
</a>
|
||||||
|
|
||||||
<!-- Releases -->
|
<!-- Releases -->
|
||||||
<DropdownMenu.Item
|
<a
|
||||||
as="a"
|
|
||||||
href="https://github.com/open-webui/open-webui/releases"
|
href="https://github.com/open-webui/open-webui/releases"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
@@ -318,11 +310,12 @@
|
|||||||
<Map className="size-5" />
|
<Map className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Releases')}</div>
|
<div class=" self-center truncate">{$i18n.t('Releases')}</div>
|
||||||
</DropdownMenu.Item>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
|
type="button"
|
||||||
id="chat-share-button"
|
id="chat-share-button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
show = false;
|
show = false;
|
||||||
@@ -338,13 +331,14 @@
|
|||||||
<Keyboard className="size-5" />
|
<Keyboard className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Keyboard shortcuts')}</div>
|
<div class=" self-center truncate">{$i18n.t('Keyboard shortcuts')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1 p-0" />
|
<hr class=" border-gray-50/30 dark:border-gray-800/30 my-1 p-0" />
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
|
||||||
|
type="button"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
const res = await userSignOut();
|
const res = await userSignOut();
|
||||||
user.set(null);
|
user.set(null);
|
||||||
@@ -358,7 +352,7 @@
|
|||||||
<SignOut className="w-5 h-5" strokeWidth="1.5" />
|
<SignOut className="w-5 h-5" strokeWidth="1.5" />
|
||||||
</div>
|
</div>
|
||||||
<div class=" self-center truncate">{$i18n.t('Sign Out')}</div>
|
<div class=" self-center truncate">{$i18n.t('Sign Out')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
{#if showActiveUsers && ($config?.features?.enable_public_active_users_count || role === 'admin') && usage}
|
{#if showActiveUsers && ($config?.features?.enable_public_active_users_count || role === 'admin') && usage}
|
||||||
{#if usage?.user_count}
|
{#if usage?.user_count}
|
||||||
@@ -395,10 +389,6 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
<!-- <DropdownMenu.Item class="flex items-center py-1.5 px-3 text-sm ">
|
</div>
|
||||||
<div class="flex items-center">Profile</div>
|
</Dropdown>
|
||||||
</DropdownMenu.Item> -->
|
|
||||||
</DropdownMenu.Content>
|
|
||||||
</slot>
|
|
||||||
</DropdownMenu.Root>
|
|
||||||
|
|||||||
@@ -43,8 +43,7 @@
|
|||||||
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 { DropdownMenu } from 'bits-ui';
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
import Dropdown from '$lib/components/common/Dropdown.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';
|
||||||
@@ -517,55 +516,55 @@
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="w-full max-w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
|
class="w-[170px] rounded-xl p-1 border border-gray-100 dark:border-gray-800 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
|
||||||
sideOffset={-2}
|
|
||||||
side="bottom"
|
|
||||||
align="end"
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
enableAllHandler();
|
enableAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CheckCircle className="size-4" />
|
<CheckCircle className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
<div class="flex items-center">{$i18n.t('Enable All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
disableAllHandler();
|
disableAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Minus className="size-4" />
|
<Minus className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
<div class="flex items-center">{$i18n.t('Disable All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<hr class="border-gray-100 dark:border-gray-800 my-1" />
|
<hr class="border-gray-100 dark:border-gray-800 my-1" />
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
showAllHandler();
|
showAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Eye className="size-4" />
|
<Eye className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
<div class="flex items-center">{$i18n.t('Show All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
|
|
||||||
<DropdownMenu.Item
|
<button
|
||||||
class="select-none flex 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="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={() => {
|
on:click={() => {
|
||||||
hideAllHandler();
|
hideAllHandler();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<EyeSlash className="size-4" />
|
<EyeSlash className="size-4" />
|
||||||
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
<div class="flex items-center">{$i18n.t('Hide All')}</div>
|
||||||
</DropdownMenu.Item>
|
</button>
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { DropdownMenu } from 'bits-ui';
|
|
||||||
import { onMount, onDestroy, getContext, createEventDispatcher } from 'svelte';
|
import { onMount, onDestroy, getContext, createEventDispatcher } from 'svelte';
|
||||||
import { searchNotes } from '$lib/apis/notes';
|
import { searchNotes } from '$lib/apis/notes';
|
||||||
import { searchKnowledgeBases, searchKnowledgeFiles } from '$lib/apis/knowledge';
|
import { searchKnowledgeBases, searchKnowledgeFiles } from '$lib/apis/knowledge';
|
||||||
|
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
|
||||||
import { decodeString } from '$lib/utils';
|
import { decodeString } from '$lib/utils';
|
||||||
|
|
||||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||||
@@ -118,12 +118,8 @@
|
|||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<div slot="content">
|
<div slot="content">
|
||||||
<DropdownMenu.Content
|
<div
|
||||||
class="z-[10000] text-black dark:text-white rounded-2xl shadow-lg border border-gray-200 dark:border-gray-800 flex flex-col bg-white dark:bg-gray-850 w-70 p-1.5"
|
class="z-[10000] text-black dark:text-white rounded-2xl shadow-lg border border-gray-200 dark:border-gray-800 flex flex-col bg-white dark:bg-gray-850 w-70 p-1.5"
|
||||||
sideOffset={8}
|
|
||||||
side="bottom"
|
|
||||||
align="start"
|
|
||||||
transition={flyAndScale}
|
|
||||||
>
|
>
|
||||||
<div class=" flex w-full space-x-2 px-2 pb-0.5">
|
<div class=" flex w-full space-x-2 px-2 pb-0.5">
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
@@ -210,6 +206,6 @@
|
|||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu.Content>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
<div class=" self-center flex items-center gap-1">
|
<div class=" self-center flex items-center gap-1">
|
||||||
{#if $user !== undefined && $user !== null}
|
{#if $user !== undefined && $user !== null}
|
||||||
<UserMenu
|
<UserMenu
|
||||||
className="max-w-[240px]"
|
className="w-[240px]"
|
||||||
role={$user?.role}
|
role={$user?.role}
|
||||||
help={true}
|
help={true}
|
||||||
on:show={(e) => {
|
on:show={(e) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user